#	Compile and link .c, .obj and/or .lib files for Windows NT, Release 2.2.59
#	Copyright (c) 1992-1995 by Hamilton Laboratories.  All rights reserved.


#	If NTVersion >= 612 (Daytona beta or later) then

#		The compiler is assumed to be cl.exe on both Intel and MIPS and
#		cl.exe (VC++) or the older claxp.exe on Alpha.

#		If CPU == PPC then
#			If NTVersion >= 944 then
#				The compiler is cl.exe.
#			else
#				It's mcl.exe.

#	else

#		On Intel, the compiler is cl386.exe.

#		If CPU == MIPS then

#			Either the old MIPS compiler or the new hybrid Microsoft/MIPS
#			compiler may be used.

#			If NTVersion < 404 (not March beta) then
#				The old MIPS compiler is the default
#			else
#				The new compiler is the default.

#			You may explicitly specify old or new using the -old or -new options.

#		If CPU == ALPHA then

#			Either the old Alpha compiler or the new hybrid Microsoft/DEC
#			compiler may be used.

#			If NTVersion < 404 (not March beta) then
#				The old ALPHA compiler is the default
#			else
#				The new compiler is the default.

#			You may explicitly specify old or new using the -old or -new options.

#		If CPU == PPC then the compiler is mcl.exe.

#  By default or if the -console flag is specified, cl will assume it's
#	building a console application.  If -GUI is specified, it expects to
#	build a graphical application.

#	Compilation options:

#		i386 Compile:		-c -Od -Zi -W4 -DNT -Di386=1 -D_X86_=1 -DWIN32
#								-D_WIN32 -Dend=EndOfData

#		MIPS Compile:
#			using MIPS:		-c -std -O -o $i:b.obj -EL -DNT -DMIPS=1
#								-D_MIPS_=1 -DWIN32 -D_WIN32 -Dend=EndOfData
#			using new MS:	-c -Od -Zi -W4 -DNT -DMIPS=1 -D_MIPS_=1 -DWIN32
#								-D_WIN32 -Dend=EndOfData

#		ALPHA Compile:
#			using DEC:		-c -std -G 0 -o $i:b.obj -checkstack 4096 -00 -EL
#								-Dend=EndOfData -DNT -DALPHA=1 -DWIN32 -D_WIN32 -excpt
#								-DDEVL=1 -I<include directories>
#			using new MS:	-c -Od -Zi -W4 -DNT -DALPHA=1 -D_ALPHA_=1 -DWIN32
#								-D_WIN32 -Dend=EndOfData -D__stdcall= -D_cdecl=

#		PPC Compile:		-c -Od -Zi -W4 -DNT -DPPC=1 -D_PPC_=1 -DWIN32 -D_WIN32
#								-Dend=EndOfData

#		In addition, if NTVersion >= 807 (Daytona final release), the
#		following compile options will be added:
#
#								-Dtry=__try -Dexcept=__except -Dleave=__leave
#								-Dfinally=__finally -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl

#	Link options:

#		Console Link:		-subsystem:console -entry:mainCRTStartup -debug:full
#								-debugtype:both

#		GUI Link:			-subsystem:windows -entry:WinMainCRTStartup -debug:full
#								-debugtype:both

#									If NTVersion >= 612 then then additional
#									option, -NODEFAULTLIB, will be added to the
#									link parameters.

#									If NTVersion >= 807 then the additional
#									options, -INCREMENTAL:NO -PDB:NONE -RELEASE
#									will be added to the link parameters.

#	(Note that this script uses the single-threaded C run-time library.
#	unless you compile with -D_MT.  We recommend using the single-threaded
#	library even if you are building a multi-threaded application, because
#	the CRTL _beginthread routine is inherently unsafe.  The handle it
#	returns is closed by the CRTL's thread epilogue when the child thread
#	exits.  Since the scheduling of threads is indeterminate and NT reuses
#	handle values quickly, the handle returned by _beginthread is not
#	dependable.  We recommend instead that the single-threaded library be
#	used, with critical section calls around any use of a CRTL function.)

#	All the output is filtered thru ferr which filters out nuisance
#	error messages such as the warnings about no modules extracted from
#	a given .lib file or about assignments inside conditional tests.
#	The list of nuisance messages is kept in skip file pointed to by the
#	skip variable.  If skip isn't set or doesn't point to a real file, cl.csh
#	wil attempt to look for a skip file in the same directory with this
#	script.

if (! $?skip || ! -e $skip) then
	#	Look for the filter file in the same directory with this cl.csh script.
	set s = `whereis cl.csh`
	if ($#s && -e $s[0]:h\skip) then
		set skip = $fullpath($s[0]:h\skip)
		alias ferr fgrep -vqf $skip
	else
		echo -2 Warning:  Output filter file not found!  No filtering will be done.
		alias ferr cat
	end
else
	alias ferr	fgrep -vqf $skip
end

proc cl(args)
	local i, j, ^
			debug, c_only, O_opt, O_opt_specified, options, ^
			c_files, obj_files, res_files, rc_files, lib_files, ^
			exe, ldir, stdlibs, ntdll, use_old_cc, GUI_app, linker, ^
			D_MT, DSE

	switch (upper(CPU))
		case "MIPS":
			@ O_opt = (use_old_cc = NTVersion < 404) ? "-O" : "-Od"
			break
		case "ALPHA":
			@ O_opt = (use_old_cc = NTVersion < 404) ? "-O0" : "-Od"
			break
		default:
			@ O_opt = "-Od"
	end

	@ c_only = 0
	for i = 0 to $#args - 1 do
		@ j = substr(args[i], 1, 1)
		if (j == '-' || j == '/') then
			if (substr(args[i], 2) == 'c') then
				@ c_only = 1
			else
				if (substr(args[i], 2, 1) == 'O') then
					set O_opt = $args[i]
					@ O_opt_specified = 1
				else
					switch (substr(args[i], 2))
						case "old":
							@ use_old_cc = 1
							if (!O_opt_specifed) then
								switch (upper(CPU))
									case "MIPS":
										@ O_opt = "-O"
										break
									case "ALPHA":
										@ O_opt = "-O0"
								end
							end
							break
						case "new":
							@ use_old_cc = 0
							if (!O_opt_specifed) then
								switch (upper(CPU))
									case "MIPS":
										@ O_opt = "-Od"
										break
									case "ALPHA":
										@ O_opt = "-Od"
								end
							end
							break
						case "console":
							@ GUI_app = 0
							break
						case "GUI":
							@ GUI_app = 1
							break
						case "D_MT":
							@ D_MT = 1
						default:
							set options = $options $args[i]
					end
				end
			end
		else
			switch ($args[i]:e)
				case 'c':
				case 'cxx':
				case 'cpp':
					set c_files = $c_files $args[i]
					set obj_files = $obj_files $args[i]:b.obj
					break
				case 'obj':
				case 'rbj':
					set obj_files = $obj_files $args[i]
					break
				case 'exe':
					set exe = $args[i]
					break
				case 'rc':
					set rc_files = $rc_files $args[i]
					break
				case 'res':
					set res_files = $res_files $args[i]
					break
				case 'lib':
				default:
					set lib_files = $lib_files $args[i]
			end
		end
	end

	#	Run the resource compiler and cvtres on each .rc file
	foreach i ($rc_files)
		echo rc -r $i
		rc -r $i
		echo cvtres -$CPU $i:b.res -o $i:b.rbj
		cvtres -$CPU $i:b.res -o $i:b.rbj
		set obj_files = $obj_files $i:b.rbj
	end

	#	Run cvtres on each .res file
	foreach i ($res_files)
		echo cvtres -$CPU $i -o $i:b.rbj
		cvtres -$CPU $i -o $i:b.rbj
		set obj_files = $obj_files $i:b.rbj
	end

	#	Run the compile step on each .c file.

	if (NTVersion >= 807) then
		set DSE = -Dtry=__try -Dexcept=__except -Dleave=__leave ^
						-Dfinally=__finally -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl
	end

	(switch (upper(CPU))
		case "MIPS":
			if (NTVersion < 612 && use_old_cc) then
				foreach i ($c_files)
					echo cc -c -std -O -o $i:b.obj -EL -DNT -DMIPS=1 -D_MIPS_=1 ^
							-DWIN32 -D_WIN32 -Dend=EndOfData $options $i
					cc -c -std -O -o $i:b.obj -EL -DNT -DMIPS=1 -D_MIPS_=1 ^
							-DWIN32 -D_WIN32 -Dend=EndOfData $options $i
					if ($status) return
					echo mip2coff $i:b.obj
					mip2coff $i:b.obj
					if ($status) return
				end
			else
				local cc
				@ cc = NTVersion < 612 ? "mcl.exe" : "cl.exe"
				foreach i ($c_files)
					echo $cc -c $O_opt -Zi -W4 -DNT -DMIPS=1 -D_MIPS_=1 -DWIN32 ^
							-D_WIN32 -Dend=EndOfData $DSE $options $i
					$cc -c $O_opt -Zi -W4 -DNT -DMIPS=1 -D_MIPS_=1 -DWIN32 ^
							-D_WIN32 -Dend=EndOfData $DSE $options $i
					if ($status) return
				end
			end
			break

		case "ALPHA":
			if (NTVersion < 612 && use_old_cc) then
				if (NTVersion < 522) then
					#	Alpha compiler doesn't handle the INCLUDE environment
					#	variable properly -- it has to be passed on the command
					#	line.
					set Inc = -I$INCLUDE:gs/;/ -I/
					if (NTVersion < 404) set options = -EL -excpt -DDEVL=1 $options
				end
				foreach i ($c_files)
					echo acc -c -std -G 0 -o $i:b.obj -checkstack 4096			^
							$O_opt -Dend=EndOfData -DNT -DALPHA=1 -D_ALPHA_=1	^
							-DWIN32 -D_WIN32 $options $Inc $i
					acc -c -std -G 0 -o $i:b.obj -checkstack 4096				^
							$O_opt -Dend=EndOfData -DNT -DALPHA=1 -D_ALPHA_=1	^
							-DWIN32 -D_WIN32 $options $Inc $i
					if ($status) return
					echo a2coff $i:b.obj
					a2coff $i:b.obj
					if ($status) return
				end
			else
				@ cc = `whereis cl.exe` != '' ? "cl.exe" : "claxp"
				foreach i ($c_files)
					echo $cc -c $O_opt -Zi -W4 -DNT -DALPHA=1 -D_ALPHA_=1	^
							-DWIN32 -D_WIN32 -Dend=EndOfData -D__stdcall= 		^
							-D_cdecl= $DSE $options $i
					$cc -c $O_opt -Zi -W4 -DNT -DALPHA=1 -D_ALPHA_=1 -DWIN32 ^
							-D_WIN32 -Dend=EndOfData -D__stdcall= -D_cdecl= $DSE ^
							$options $i
					if ($status) return
				end
			end
			break

		case "PPC":
			@ cc = NTVersion >= 944 ? "cl.exe" : "mcl"
			foreach i ($c_files)
				echo $cc -c $O_opt -Zi -W4 -DNT -DPPC=1 -D_PPC_=1 -DWIN32 ^
						-D_WIN32 -Dend=EndOfData $DSE $options $i
				$cc -c $O_opt -Zi -W4 -DNT -DPPC=1 -D_PPC_=1 -DWIN32 ^
						-D_WIN32 -Dend=EndOfData $DSE $options $i
				if ($status) return
			end
			break

		default:
			local cc
			@ cc = NTVersion < 612 ? "cl386.exe" : "cl.exe"
			foreach i ($c_files)
				echo $cc -c $O_opt -Zi -W4 -DNT -Di386=1 -D_X86_=1 -DWIN32 ^
						-D_WIN32 -Dend=EndOfData $DSE $options $i
				$cc -c $O_opt -Zi -W4 -DNT -Di386=1 -D_X86_=1 -DWIN32 ^
						-D_WIN32 -Dend=EndOfData $DSE $options $i
				if ($status) return
			end
	end

	if (! $c_only) then

		local defflag
		if (NTVersion >= 612) then
			if (NTVersion >= 807) then
				set defflag = -NODEFAULTLIB -INCREMENTAL:NO -PDB:NONE -RELEASE
			else
				set defflag = -NODEFAULTLIB
			end
		end

		#	If no .exe file was specified, name the output to match the
		#	first .c or .obj file on the command line.
		if (exe == '') then
			@ exe = $#c_files == 0 ? $obj_files[0]:b.exe : $c_files[0]:b.exe
		end

		@ stdlibs = D_MT ? "libcmt.lib" : "libc.lib"
		if (NTVersion >= 404) then

			#	Figure out whether ntdll.lib exists on this build.
			if (LIB =~ "*;*") then
				foreach i ($LIB:gs/;/ /)
					if (-e $i\ntdll.lib) then
						set ntdll = ntdll.lib
						break;
					else
						if (CPU == "ALPHA" && -e $i\alpha\ntdll.lib) then
							set ntdll = ntdll.lib
						end
					end
				end
			else
				if (-e $LIB\ntdll.lib) set ntdll = ntdll.lib
			end
			if (NTVersion < 807) then
				set linker = link32
			else
				set linker = link
			end
			if (GUI_app) then
				set stdlibs = $stdlibs $ntdll kernel32.lib advapi32.lib ^
					user32.lib gdi32.lib winspool.lib comdlg32.lib
			else
				set stdlibs = $stdlibs $ntdll kernel32.lib user32.lib advapi32.lib
			end

		else

			#	Figure out where libc.lib (or libcmt.lib) lives on the LIB path.
			if (LIB =~ "*;*") then
				foreach i ($LIB:gs/;/ /)
					if (-e $i\$stdlibs) then
						@ ldir = i
						break
					else
						if (CPU == "ALPHA" && -e $i\alpha\$stdlibs) then
							set ldir = $i\alpha
							break
						end
					end
				end
			else
				@ ldir = LIB
			end

			set linker = coff -link

			if (CPU == "ALPHA") then
				if (GUI_app) then
					set stdlibs = $ldir\{$stdlibs,{ntdll,kernel32,advapi32}.lib} ^
						$ldir\{user32,gdi32,winspool,comdlg32}.lib
				else
					set stdlibs = $ldir\{$stdlibs,{ntdll,kernel32,user32,advapi32}.lib}
				end
			else
				set stdlibs = $ldir\{$stdlibs,^*.lib}
			end
		end

		#	Run the link step, with debug info.
		if (GUI_app) then
			echo $linker -subsystem:windows -entry:WinMainCRTStartup -debug:full	^
				-debugtype:both -out:$exe $defflag $obj_files $lib_files "$stdlibs"
			$linker -subsystem:windows -entry:WinMainCRTStartup -debug:full		^
				-debugtype:both -out:$exe $defflag $obj_files $lib_files $stdlibs
		else
			echo $linker -subsystem:console -entry:mainCRTStartup -debug:full	^
				-debugtype:both -out:$exe $defflag $obj_files $lib_files "$stdlibs"
			$linker -subsystem:console -entry:mainCRTStartup -debug:full		^
				-debugtype:both -out:$exe $defflag $obj_files $lib_files $stdlibs
		end
	end) |& ferr
end

cl $argv
