From 72c6dece05777c6158e9d6726c879d2c1cb74d2c Mon Sep 17 00:00:00 2001
From: davygrvy <davygrvy@noemail.net>
Date: Thu, 28 Mar 2002 23:23:02 +0000
Subject: 	* win/.cvsignore (new): 	* win/lamp.bmp (new): 	*
 win/makefile.vc: 	* win/nmakehlp.c (new): 	* win/rules.vc: 
 Brought the makefile up-to-date with Tcl's one. 	This now has support
 for Win9x issues and the winhelp target now 	exists.  Color scheme can be
 changed.  I'm just imparting a first 	suggestion using orange :)  I'll have
 to think about the install 	portion of the helpfile as I'll need to do
 some tricks to insert 	tk's contents file into Tcl's using some special
 winhlp32.exe 	switches.  [Bug 533862 527941]

FossilOrigin-Name: 8bb6331b52c3c5354d532404f7dc125089c6b701
---
 win/.cvsignore  |  15 +++
 win/lamp.bmp    | Bin 0 -> 2102 bytes
 win/makefile.vc | 171 +++++++++++++++++++++-----------
 win/nmakehlp.c  | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 win/rules.vc    | 111 +++++++++++++++++----
 5 files changed, 521 insertions(+), 73 deletions(-)
 create mode 100644 win/.cvsignore
 create mode 100644 win/lamp.bmp
 create mode 100644 win/nmakehlp.c

diff --git a/win/.cvsignore b/win/.cvsignore
new file mode 100644
index 0000000..b986cda
--- /dev/null
+++ b/win/.cvsignore
@@ -0,0 +1,15 @@
+Debug
+Release
+*.opt
+*.ncb
+*.plg
+*.00?
+*.o
+*.obj
+*.i
+*.asm
+Makefile
+tcl.hpj
+tclConfig.sh
+nmakehlp.exe
+.#*
diff --git a/win/lamp.bmp b/win/lamp.bmp
new file mode 100644
index 0000000..834c0f9
Binary files /dev/null and b/win/lamp.bmp differ
diff --git a/win/makefile.vc b/win/makefile.vc
index 28933e4..31838f1 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -9,10 +9,10 @@
 # Copyright (c) 1995-1996 Sun Microsystems, Inc.
 # Copyright (c) 1998-2000 Ajuba Solutions.
 # Copyright (c) 2001 ActiveState Corporation.
-# Copyright (c) 2001 Tomasoft Engineering.
+# Copyright (c) 2001-2002 David Gravereaux.
 #
 #------------------------------------------------------------------------------
-# RCS: @(#) $Id: makefile.vc,v 1.52 2002/03/21 17:48:54 davygrvy Exp $
+# RCS: @(#) $Id: makefile.vc,v 1.53 2002/03/28 23:23:03 davygrvy Exp $
 #------------------------------------------------------------------------------
 
 !if "$(MSVCDIR)" == ""
@@ -62,6 +62,8 @@ the environment.  Jump to this line to read the new instructions.
 #		Sets the location for where to find the Tcl headers and
 #		libraries.  The install point is assumed when not
 #		specified.  This can be the source tree or an installation.
+#		Tk does need the source directory, though.  Tk comes very close
+#		to not needing the sources.
 #
 #	INSTALLDIR=<path>
 #		Sets where to install Tcl from the built binaries.
@@ -205,27 +207,26 @@ TCL_LIBRARY	= $(INSTALLDIR)\lib
 TCLREGLIB	= $(INSTALLDIR)\lib\$(TCLREGLIBNAME)
 TCLDDELIB	= $(INSTALLDIR)\lib\$(TCLDDELIBNAME)
 TCLTMP_DIR	= \must\have\tcl\sources\to\build\this\target
+COFFBASE	= \must\have\tcl\sources\to\build\this\target
+TOOLSDIR	= \must\have\tcl\sources\to\build\this\target
 !else
-TCLSH		= $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLNAMEPREFIX)sh$(VERSION)$(SUFX).exe
+TCLSH		= $(TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(VERSION)$(SUFX).exe
 TCLSTUBLIB	= $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLSTUBLIBNAME)
 TCLIMPLIB	= $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLIMPLIBNAME)
 TCL_LIBRARY	= $(TCLDIR)\library
 TCLREGLIB	= $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLREGLIBNAME)
 TCLDDELIB	= $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLDDELIBNAME)
 TCLTMP_DIR	= $(TCLDIR)\win\$(TMP_DIR:tk=tcl)
+COFFBASE	= $(TCLDIR)\win\coffbase.txt
+TOOLSDIR	= $(TCLDIR)\tools
 !endif
 
 WISH 		= $(OUT_DIR)\$(WISHNAMEPREFIX)$(VERSION)$(SUFX).exe
 WISHC 		= $(OUT_DIR)\$(WISHNAMEPREFIX)c$(VERSION)$(SUFX).exe
 
-#TKHLPBASE	= $(PROJECT)$(VERSION)
-#TKHLP		= $(OUT_DIR)\$(TKHLPBASE).hlp
-#TKHLPCNT	= $(OUT_DIR)\$(TKHLPBASE).cnt
-
 TKTEST		= $(OUT_DIR)\$(PROJECT)test.exe
 CAT32		= $(OUT_DIR)\cat32.exe
 RMDIR		= .\rmd.bat
-MKDIR		= .\mkd.bat
 RM		= del
 
 LIB_INSTALL_DIR		= $(INSTALLDIR)\lib
@@ -369,6 +370,7 @@ WINDIR          = $(ROOT)\win
 GENERICDIR	= $(ROOT)\generic
 XLIBDIR		= $(ROOT)\xlib
 BITMAPDIR	= $(ROOT)\bitmaps
+DOCDIR		= $(ROOT)\doc
 RCDIR		= $(WINDIR)\rc
 
 !if $(TCLINSTALL)
@@ -399,7 +401,15 @@ cdebug = -Oti
 !endif
 
 # declarations common to all compiler options
-cflags = -nologo -c -W3 -Fp$(TMP_DIR)^\ -YX
+cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\
+
+!if $(PENT_0F_ERRATA)
+cflags = $(cflags) -QI0f
+!endif
+
+!if $(ITAN_B_ERRATA)
+cflags = $(cflags) -QIA64_Bx
+!endif
 
 !if $(MSVCRT)
 crt = -MD$(DBGX)
@@ -418,29 +428,35 @@ WISH_CFLAGS	= $(BASE_CLFAGS) $(TK_DEFINES)
 #---------------------------------------------------------------------
 
 !if $(DEBUG)
-ldebug	    = -debug:full -debugtype:cv
+ldebug	= -debug:full -debugtype:cv
 !else
-ldebug	    = -release
+ldebug	= -release -opt:ref -opt:icf,3
 !endif
 
 # declarations common to all linker options
-lflags	    = -nologo -machine:$(MACHINE)
-
-# declarations for use on Intel i386, i486, and Pentium systems
-!IF "$(MACHINE)" == "IX86"
-DLLENTRY    = @12
-dlllflags   = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll
-!ELSE IF "$(MACHINE)" == "IA64"
-DLLENTRY    = @12
-dlllflags   = $(lflags) -dll
-!ELSE
-dlllflags   = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll
-!ENDIF
-
-conlflags   = $(lflags) -subsystem:console -entry:mainCRTStartup
-guilflags   = $(lflags) -subsystem:windows -entry:WinMainCRTStartup
-
-baselibs    = kernel32.lib advapi32.lib user32.lib
+lflags	= -nologo -machine:$(MACHINE) $(ldebug)
+
+!if $(PROFILE)
+lflags	= $(lflags) -profile
+!endif
+
+!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
+# align sections for PE size savings.
+lflags	= $(lflags) -opt:nowin98
+!else if !$(ALIGN98_HACK) && $(STATIC_BUILD)
+# align sections for speed in loading by choosing the virtual page size.
+lflags	= $(lflags) -align:4096
+!endif
+
+!if $(LOIMPACT)
+lflags	= $(lflags) -ws:aggressive
+!endif
+
+dlllflags = $(lflags) -dll
+conlflags = $(lflags) -subsystem:console
+guilflags = $(lflags) -subsystem:windows
+
+baselibs   = kernel32.lib advapi32.lib user32.lib
 guilibs	    = $(baselibs) gdi32.lib comdlg32.lib winspool.lib imm32.lib comctl32.lib
 
 
@@ -496,8 +512,8 @@ rundemo: setup $(TKTEST) $(TKLIB) $(CAT32)
 	$(TKTEST) $(ROOT)\library\demos\widget
 
 setup:
-	@$(MKDIR) $(TMP_DIR)
-	@$(MKDIR) $(OUT_DIR)
+	@if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
+	@if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
 
 console-wish : $(WISHC)
 
@@ -511,7 +527,8 @@ $(TKLIB): $(TKOBJS)
 $**
 <<
 !else
-	$(link32) $(ldebug) $(dlllflags) -out:$@ $(guilibs) $(TCLSTUBLIB) @<<
+	$(link32) $(ldebug) $(dlllflags) -base:@$(COFFBASE),tk -out:$@ \
+		$(guilibs) $(TCLSTUBLIB) @<<
 $**
 <<
 	-@del $*.exp
@@ -568,34 +585,68 @@ genstubs:
 # Regenerate the windows help files.
 #---------------------------------------------------------------------
 
-#MAN2TCL		= $(TOOLSDIR)\man2tcl
-#TCLRTF		= $(TOOLSDIR)\tcl.rtf
-#MAN2HELP	= $(TOOLSDIR)\man2help.tcl
-#TCLHPJ		= $(TOOLSDIR)\tcl.hpj
-
-#winhelp: $(TCLHLP)
-
-#$(TCLHLP): $(TCLRTF)
-#	cd $(TOOLSDIR)
-#	start /wait hcrtf.exe -x tcl.hpj
-#	cd $(MAKEDIR)
-#	copy $(TOOLSDIR)\$(TCLHLPBASE).hlp $(OUT_DIR)
-#	copy $(TOOLSDIR)\$(TCLHLPBASE).cnt $(OUT_DIR)
-
-#$(TCLHPJ): $(TCLHPJ).in
-#	copy $(TCLHPJ).in $(TCLHPJ)
+TCLHLPBASE	= $(PROJECT)$(VERSION)
+HELPFILE	= $(OUT_DIR)\$(TCLHLPBASE).hlp
+HELPCNT		= $(OUT_DIR)\$(TCLHLPBASE).cnt
+DOCTMP_DIR	= $(OUT_DIR)\$(PROJECT)_docs
+HELPRTF		= $(DOCTMP_DIR)\$(PROJECT).rtf
+MAN2HELP	= $(DOCTMP_DIR)\man2help.tcl
+MAN2HELP2	= $(DOCTMP_DIR)\man2help2.tcl
+INDEX		= $(DOCTMP_DIR)\index.tcl
+BMP		= $(DOCTMP_DIR)\lamp.bmp
+BMP_NOPATH	= lamp.bmp
+MAN2TCL		= $(DOCTMP_DIR)\man2tcl.exe
+
+winhelp: docsetup $(HELPFILE)
+
+docsetup:
+	@if not exist $(DOCTMP_DIR)\nul mkdir $(DOCTMP_DIR)
+
+$(MAN2HELP) $(MAN2HELP2) $(INDEX): $(TOOLSDIR)\$$(@F)
+	copy $(TOOLSDIR)\$(@F) $(@D)
+
+$(BMP):
+	copy $(WINDIR)\$(@F) $(@D)
+
+$(HELPFILE): $(HELPRTF) $(BMP)
+	cd $(DOCTMP_DIR)
+	start /wait hcrtf.exe -x <<$(PROJECT).hpj
+[OPTIONS]
+COMPRESS=12 Hall Zeck
+LCID=0x409 0x0 0x0 ; English (United States)
+TITLE=Tcl/Tk Reference Manual
+BMROOT=.
+CNT=$(@B).cnt
+HLP=$(@B).hlp
+
+[FILES]
+$(PROJECT).rtf
+
+[WINDOWS]
+main="Tcl/Tk Reference Manual",,27648,(r15263976),(r4227327)
+
+[CONFIG]
+BrowseButtons()
+CreateButton(1, "Web", ExecFile("http://www.tcl.tk"))
+CreateButton(2, "SF", ExecFile("http://sf.net/projects/tcl"))
+CreateButton(3, "Wiki", ExecFile("http://wiki.tcl.tk"))
+CreateButton(4, "FAQ", ExecFile("http://www.purl.org/NET/Tcl-FAQ/"))
+<<
+	cd $(MAKEDIR)
+	copy "$(DOCTMP_DIR)\$(@B).hlp" "$(OUT_DIR)"
+	copy "$(DOCTMP_DIR)\$(@B).cnt" "$(OUT_DIR)"
 
-#$(MAN2TCL).exe: $(MAN2TCL).obj 
-#	cd $(TOOLSDIR)
-#	$(cc32) -nologo -G4 -ML -O2 $(MAN2TCL).c
-#	cd $(MAKEDIR)
+$(MAN2TCL): $(TOOLSDIR)\$$(@B).c
+	$(cc32) -nologo -G4 -ML -O2 -Fo$(@D)\ $(TOOLSDIR)\$(@B).c -link -out:$@
 
-#$(TCLRTF): $(MAN2TCL).exe $(TCLSH)
-#	cd $(TOOLSDIR)
-#	..\win\$(TCLSH) $(MAN2HELP) $(PROJECT) $(VERSION) $(ROOT)/doc \
-#		../../tk$(DOTVERSION)/doc
-#	cd $(MAKEDIR)
+$(HELPRTF): $(MAN2TCL) $(MAN2HELP) $(MAN2HELP2) $(INDEX)
+	$(TCLSH) $(MAN2HELP:\=/) -bitmap $(BMP_NOPATH) $(PROJECT) $(VERSION) $(DOCDIR:\=/)
 
+install-docs:
+!if exist($(HELPFILE))
+	@xcopy /i /y "$(HELPFILE)" "$(DOC_INSTALL_DIR)\"
+	@xcopy /i /y "$(HELPCNT)" "$(DOC_INSTALL_DIR)\"
+!endif
 
 #---------------------------------------------------------------------
 # Special case object file targets
@@ -675,7 +726,15 @@ $(GENERICDIR)/tkMenu.c: $(GENERICDIR)/tkMenu.h
 $(GENERICDIR)/tkMenuDraw.c: $(GENERICDIR)/tkMenu.h
 $(WINDIR)/tkWinMenu.c: $(GENERICDIR)/tkMenu.h
 
+!if exist("$(OUT_DIR)\depend.mk")
+!include "$(OUT_DIR)\depend.mk"
+!message *** Dependency rules in effect.
+!else
+!message *** Dependency rules are not being used.
+!endif
 
+### add a spacer in the output
+!message
 
 #---------------------------------------------------------------------
 # Implicit rules
diff --git a/win/nmakehlp.c b/win/nmakehlp.c
new file mode 100644
index 0000000..9a27028
--- /dev/null
+++ b/win/nmakehlp.c
@@ -0,0 +1,297 @@
+/* ----------------------------------------------------------------------------
+ * nmakehlp.c --
+ *
+ *	This is used to fix limitations within nmake and the environment.
+ *
+ * Copyright (c) 2002 by David Gravereaux.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * ----------------------------------------------------------------------------
+ * RCS: @(#) $Id: nmakehlp.c,v 1.1 2002/03/28 23:23:03 davygrvy Exp $
+ * ----------------------------------------------------------------------------
+ */
+#include <windows.h>
+#pragma comment (lib, "user32.lib")
+#pragma comment (lib, "kernel32.lib")
+
+/* protos */
+int CheckForCompilerFeature (const char *option);
+int CheckForLinkerFeature (const char *option);
+int IsIn (const char *string, const char *substring);
+DWORD WINAPI ReadFromPipe (LPVOID args);
+
+/* globals */
+typedef struct {
+    HANDLE pipe;
+    char buffer[1000];
+} pipeinfo;
+
+pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
+pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
+
+
+
+/* exitcodes: 0 == no, 1 == yes, 2 == error */
+int
+main (int argc, char *argv[])
+{
+    char msg[300];
+    DWORD dwWritten;
+    int chars;
+
+    if (argc > 1 && *argv[1] == '-') {
+	switch (*(argv[1]+1)) {
+	case 'c':
+	    if (argc != 3) {
+		chars = wsprintf(msg, "usage: %s -c <compiler option>\n"
+			"Tests for whether cl.exe supports an option\n"
+			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+		return 2;
+	    }
+	    return CheckForCompilerFeature(argv[2]);
+	case 'l':
+	    if (argc != 3) {
+		chars = wsprintf(msg, "usage: %s -l <linker option>\n"
+			"Tests for whether link.exe supports an option\n"
+			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+		return 2;
+	    }
+	    return CheckForLinkerFeature(argv[2]);
+	case 'f':
+	    if (argc == 2) {
+		chars = wsprintf(msg, "usage: %s -f <string> <substring>\n"
+		    "Find a substring within another\n"
+		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+		return 2;
+	    } else if (argc == 3) {
+		/* if the string is blank, there is no match */
+		return 0;
+	    } else {
+		return IsIn(argv[2], argv[3]);
+	    }
+	}
+    }
+    chars = wsprintf(msg, "usage: %s -c|-l|-f ...\n"
+	    "This is a little helper app to equalize shell differences between WinNT and\n"
+	    "Win9x and get nmake.exe to accomplish its job.\n",
+	    argv[0]);
+    WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+    return 2;
+}
+
+int
+CheckForCompilerFeature (const char *option)
+{
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    SECURITY_ATTRIBUTES sa;
+    DWORD threadID;
+    char msg[300];
+    BOOL ok;
+    HANDLE hProcess, h, pipeThreads[2];
+    char cmdline[100];
+
+    hProcess = GetCurrentProcess();
+
+    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+    ZeroMemory(&si, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+    si.dwFlags   = STARTF_USESTDHANDLES;
+    si.hStdInput = INVALID_HANDLE_VALUE;
+
+    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = FALSE;
+
+    /* create a non-inheritible pipe. */
+    CreatePipe(&Out.pipe, &h, &sa, 0);
+
+    /* dupe the write side, make it inheritible, and close the original. */
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 
+	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /* Same as above, but for the error side. */
+    CreatePipe(&Err.pipe, &h, &sa, 0);
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
+	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /* base command line */
+    strcpy(cmdline, "cl.exe -nologo -c -TC -Fdtemp ");
+    /* append our option for testing */
+    strcat(cmdline, option);
+    /* filename to compile, which exists, but is nothing and empty. */
+    strcat(cmdline, " nul");
+
+    ok = CreateProcess(
+	    NULL,	    /* Module name. */
+	    cmdline,	    /* Command line. */
+	    NULL,	    /* Process handle not inheritable. */
+	    NULL,	    /* Thread handle not inheritable. */
+	    TRUE,	    /* yes, inherit handles. */
+	    DETACHED_PROCESS, /* No console for you. */
+	    NULL,	    /* Use parent's environment block. */
+	    NULL,	    /* Use parent's starting directory. */
+	    &si,	    /* Pointer to STARTUPINFO structure. */
+	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */
+
+    if (!ok) {
+	DWORD err = GetLastError();
+	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
+
+	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
+		(300-chars), 0);
+	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
+	return 2;
+    }
+
+    /* close our references to the write handles that have now been inherited. */
+    CloseHandle(si.hStdOutput);
+    CloseHandle(si.hStdError);
+
+    WaitForInputIdle(pi.hProcess, 5000);
+    CloseHandle(pi.hThread);
+
+    /* start the pipe reader threads. */
+    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
+    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
+
+    /* block waiting for the process to end. */
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    CloseHandle(pi.hProcess);
+
+    /* clean up temporary files before returning */
+    DeleteFile("temp.idb");
+    DeleteFile("temp.pdb");
+
+    /* wait for our pipe to get done reading, should it be a little slow. */
+    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
+    CloseHandle(pipeThreads[0]);
+    CloseHandle(pipeThreads[1]);
+
+    /* look for the commandline warning code in both streams. */
+    return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL);
+}
+
+int
+CheckForLinkerFeature (const char *option)
+{
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    SECURITY_ATTRIBUTES sa;
+    DWORD threadID;
+    char msg[300];
+    BOOL ok;
+    HANDLE hProcess, h, pipeThreads[2];
+    char cmdline[100];
+
+    hProcess = GetCurrentProcess();
+
+    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+    ZeroMemory(&si, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+    si.dwFlags   = STARTF_USESTDHANDLES;
+    si.hStdInput = INVALID_HANDLE_VALUE;
+
+    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = TRUE;
+
+    /* create a non-inheritible pipe. */
+    CreatePipe(&Out.pipe, &h, &sa, 0);
+
+    /* dupe the write side, make it inheritible, and close the original. */
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 
+	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /* Same as above, but for the error side. */
+    CreatePipe(&Err.pipe, &h, &sa, 0);
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
+	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /* base command line */
+    strcpy(cmdline, "link.exe -nologo ");
+    /* append our option for testing */
+    strcat(cmdline, option);
+    /* filename to compile, which exists, but is nothing and empty. */
+//    strcat(cmdline, " nul");
+
+    ok = CreateProcess(
+	    NULL,	    /* Module name. */
+	    cmdline,	    /* Command line. */
+	    NULL,	    /* Process handle not inheritable. */
+	    NULL,	    /* Thread handle not inheritable. */
+	    TRUE,	    /* yes, inherit handles. */
+	    DETACHED_PROCESS, /* No console for you. */
+	    NULL,	    /* Use parent's environment block. */
+	    NULL,	    /* Use parent's starting directory. */
+	    &si,	    /* Pointer to STARTUPINFO structure. */
+	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */
+
+    if (!ok) {
+	DWORD err = GetLastError();
+	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
+
+	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
+		(300-chars), 0);
+	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
+	return 2;
+    }
+
+    /* close our references to the write handles that have now been inherited. */
+    CloseHandle(si.hStdOutput);
+    CloseHandle(si.hStdError);
+
+    WaitForInputIdle(pi.hProcess, 5000);
+    CloseHandle(pi.hThread);
+
+    /* start the pipe reader threads. */
+    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
+    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
+
+    /* block waiting for the process to end. */
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    CloseHandle(pi.hProcess);
+
+    /* wait for our pipe to get done reading, should it be a little slow. */
+    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
+    CloseHandle(pipeThreads[0]);
+    CloseHandle(pipeThreads[1]);
+
+    /* look for the commandline warning code in the stderr stream. */
+    return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL);
+}
+
+DWORD WINAPI
+ReadFromPipe (LPVOID args)
+{
+    pipeinfo *pi = (pipeinfo *) args;
+    char *lastBuf = pi->buffer;
+    DWORD dwRead;
+    BOOL ok;
+
+again:
+    ok = ReadFile(pi->pipe, lastBuf, 25, &dwRead, 0L);
+    if (!ok || dwRead == 0) {
+	CloseHandle(pi->pipe);
+	return 0;
+    }
+    lastBuf += dwRead;
+    goto again;
+
+    return 0;  /* makes the compiler happy */
+}
+
+int
+IsIn (const char *string, const char *substring)
+{
+    return (strstr(string, substring) != NULL);
+}
diff --git a/win/rules.vc b/win/rules.vc
index 95f33fe..402a5d9 100644
--- a/win/rules.vc
+++ b/win/rules.vc
@@ -7,10 +7,10 @@
 # See the file "license.terms" for information on usage and redistribution
 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 # 
-# Copyright (c) 2001 Tomasoft Engineering.
+# Copyright (c) 2001-2002 David Gravereaux.
 #
 #------------------------------------------------------------------------------
-# RCS: @(#) $Id: rules.vc,v 1.1 2001/11/13 02:46:23 davygrvy Exp $
+# RCS: @(#) $Id: rules.vc,v 1.2 2002/03/28 23:23:03 davygrvy Exp $
 #------------------------------------------------------------------------------
 
 !ifndef _RULES_VC
@@ -29,61 +29,128 @@ INSTALLDIR	= C:\Progra~1\Tcl
 MACHINE		= IX86
 !endif
 
+!message ===============================================================================
+
+#----------------------------------------------------------
+# build the helper app we need to overcome nmake's limiting
+# environment.
+#----------------------------------------------------------
+
+!if !exist(nmakehlp.exe)
+!if [$(cc32) -nologo -ML nmakehlp.c -link -subsystem:console > nul]
+!endif
+!endif
+
+#----------------------------------------------------------
+# Test for compiler features
+#----------------------------------------------------------
+
+### test for optimizations
+!if [nmakehlp -c -Ox]
+!message *** Compiler has 'Optimizations'
+OPTIMIZING	= 1
+!else
+!message *** Compiler doesn't have 'Optimizations'
+OPTIMIZING	= 0
+!endif
+
+!if "$(MACHINE)" == "IX86"
+### test for pentium errata
+!if [nmakehlp -c -QI0f]
+!message *** Compiler has 'Pentium 0x0f fix'
+PENT_0F_ERRATA	= 1
+!else
+!message *** Compiler doesn't have 'Pentium 0x0f fix'
+PENT_0F_ERRATA	= 0
+!endif
+### test for -align:4096, when align:512 will do.
+!if [nmakehlp -l -opt:nowin98]
+!message *** Linker has 'Win98 alignment problem'
+ALIGN98_HACK	= 1
+!else
+!message *** Linker doesn't have 'Win98 alignment problem'
+ALIGN98_HACK	= 0
+!endif
+!else
+PENT_0F_ERRATA	= 0
+ALIGN98_HACK	= 0
+!endif
+
+!if "$(MACHINE)" == "IA64"
+### test for Itanium errata
+!if [nmakehlp -c -QIA64_Bx]
+!message *** Compiler has 'B-stepping errata workarounds'
+ITAN_B_ERRATA	= 1
+!else
+!message *** Compiler doesn't have 'B-stepping errata workarounds'
+ITAN_B_ERRATA	= 0
+!endif
+!else
+ITAN_B_ERRATA	= 0
+!endif
 
 #----------------------------------------------------------
 # Decode the options requested.
 #----------------------------------------------------------
-!if "$(OPTS)" == "" || ![echo $(OPTS) | find /i "none" > nul]
+
+!if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"]
 STATIC_BUILD	= 0
 TCL_THREADS	= 0
 DEBUG		= 0
 PROFILE		= 0
 MSVCRT		= 0
+LOIMPACT	= 0
 TCL_LINKWITHEXTENSIONS	= 0
 !else
-!if ![echo $(OPTS) | find /i "static" > nul]
+!if [nmakehlp -f $(OPTS) "static"]
 !message *** Doing static
 STATIC_BUILD	= 1
 !else
 STATIC_BUILD	= 0
 !endif
-!if ![echo $(OPTS) | find /i "msvcrt" > nul]
+!if [nmakehlp -f $(OPTS) "msvcrt"]
 !message *** Doing msvcrt
 MSVCRT		= 1
 !else
 MSVCRT		= 0
 !endif
-!if ![echo $(OPTS) | find /i "linkexten" > nul]
+!if [nmakehlp -f $(OPTS) "linkexten"]
 !message *** Doing linkexten
 TCL_LINKWITHEXTENSIONS	= 1
 !else
 TCL_LINKWITHEXTENSIONS	= 0
 !endif
-!if ![echo $(OPTS) | find /i "threads" > nul]
+!if [nmakehlp -f $(OPTS) "threads"]
 !message *** Doing threads
 TCL_THREADS	= 1
 !else
 TCL_THREADS	= 0
 !endif
-!if ![echo $(OPTS) | find /i "symbols" > nul]
+!if [nmakehlp -f $(OPTS) "symbols"]
 !message *** Doing symbols
 DEBUG		= 1
 !else
 DEBUG		= 0
 !endif
-!if ![echo $(OPTS) | find /i "profile" > nul]
+!if [nmakehlp -f $(OPTS) "profile"]
 !message *** Doing profile
 PROFILE		= 1
 !else
 PROFILE		= 0
 !endif
+!if [nmakehlp -f $(OPTS) "loimpact"]
+!message *** Doing loimpact
+LOIMPACT	= 1
+!else
+LOIMPACT	= 0
+!endif
 !endif
 
 
 !if !$(STATIC_BUILD)
 # Make sure we don't build overly fat DLLs.
 MSVCRT		= 1
-# Shouldn't statically put the extensions inside the shell when dynamic.
+# We shouldn't statically put the extensions inside the shell when dynamic.
 TCL_LINKWITHEXTENSIONS = 0
 !endif
 
@@ -140,25 +207,22 @@ OUT_DIR	    = $(TMP_DIR)
 !endif
 !endif
 
-!message *** Intermediate directory will be '$(TMP_DIR)'
-!message *** Output directory will be '$(OUT_DIR)'
-!message *** Suffix for binaries will be '$(SUFX)'
-
 
 #----------------------------------------------------------
 # Decode the statistics requested.
 #----------------------------------------------------------
-!if "$(STATS)" == "" || ![echo $(STATS) | find /i "none" > nul]
+
+!if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"]
 TCL_MEM_DEBUG	    = 0
 TCL_COMPILE_DEBUG   = 0
 !else
-!if ![echo $(STATS) | find /i "memdbg" > nul]
+!if [nmakehlp -f $(STATS) "memdbg"]
 !message *** Doing memdbg
 TCL_MEM_DEBUG	    = 1
 !else
 TCL_MEM_DEBUG	    = 0
 !endif
-!if ![echo $(STATS) | find /i "compdbg" > nul]
+!if [nmakehlp -f $(STATS) "compdbg"]
 !message *** Doing compdbg
 TCL_COMPILE_DEBUG   = 1
 !else
@@ -166,6 +230,11 @@ TCL_COMPILE_DEBUG   = 0
 !endif
 !endif
 
+
+#----------------------------------------------------------
+# Set our defines armed with our options.
+#----------------------------------------------------------
+
 OPTDEFINES	=
 !if $(TCL_MEM_DEBUG)
 OPTDEFINES	= -DTCL_MEM_DEBUG
@@ -180,6 +249,14 @@ OPTDEFINES	= $(OPTDEFINES) -DTCL_THREADS=1
 OPTDEFINES	= $(OPTDEFINES) -DSTATIC_BUILD
 !endif
 
+
+#----------------------------------------------------------
+# Display stats being used.
+#----------------------------------------------------------
+
+!message *** Intermediate directory will be '$(TMP_DIR)'
+!message *** Output directory will be '$(OUT_DIR)'
+!message *** Suffix for binaries will be '$(SUFX)'
 !message *** Optional defines are '$(OPTDEFINES)'
 
 !endif
-- 
cgit v0.12