Tcl UDP

Check-in [b990a0bdd3]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Pulling change from trunk
Timelines: family | ancestors | descendants | both | practcl
Files: files | file ages | folders
SHA1: b990a0bdd32cd66061bc3be6779da3b72bda6ae0
User & Date: seandeelywoods 2017-08-28 20:07:13
Context
2017-11-28
14:53
Pulling changes from trunk Leaf check-in: 97b3bd3fc7 user: seandeelywoods tags: practcl
2017-08-28
20:07
Pulling change from trunk check-in: b990a0bdd3 user: seandeelywoods tags: practcl
14:16
Merged nmake build changes check-in: bf7683880f user: apnadkarni tags: trunk
2016-06-21
23:55
Removed the local tracking of the tclconfig/ directory. One will now be populated from ../tclconfig for a fresh fossil checkout Updated the build system to tea 3.10 udp now populates a config.tcl file on ./configure. This file contains the same build information as is fed into the Makefile, but it is formated in a tcl friendly key/value list format check-in: 7c396e1a76 user: tne tags: practcl
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to README.

    46     46   	$ make test
    47     47   	$ make install
    48     48   
    49     49   WINDOWS BUILD
    50     50   =============
    51     51   
    52     52   See the tcl/win/README file included in the Tcl src dist for details
    53         -about how to build the extension under Windows. We suggest using
    54         -the Msys + Mingw build process since it is significantly easier
    55         -than building with VC++ or Cygwin.
           53  +about how to build the extension under Windows.
    56     54   
    57         -This package includes a Visual Studio project file to help in building
    58         -with VC++.
    59         -
    60         -The package has been built using both VC++6 and Msys + Mingw. 
    61         -
    62         -Microsoft Platform SDK 2003 is required for building. The following minimal
    63         -example will install the extension in the C:\Tcl\lib directory.
           55  +The following minimal example will build and install the extension in the
           56  +C:\Tcl\lib directory.
    64     57   
    65     58   	$ cd tcludp/win
    66     59   	$ nmake -f makefile.vc realclean all 
    67         -	$ nmake -f makefile.vc install INSTALLDIR=C:\Tcl\lib
           60  +	$ nmake -f makefile.vc install INSTALLDIR=C:\Tcl
           61  +
           62  +The Visual Studio project file included in the win directory
           63  +is *ancient* and deprecated. It is not suitable for modern versions
           64  +of Tcl and Visual Studio.
    68     65   
    69     66   DOCUMENTATION BUILD
    70     67   ===================
    71     68   
    72     69   Use the following command to create the UNIX documentation (based on udp.man file):
    73     70   
    74     71   	$ cd tcludp

Changes to generic/udp_tcl.c.

   261    261    *  interpreter
   262    262    * ----------------------------------------------------------------------
   263    263    */
   264    264   int
   265    265   udpOpen(ClientData clientData, Tcl_Interp *interp,
   266    266           int argc, CONST84 char * argv[]) 
   267    267   {
          268  +#ifdef WIN32
          269  +    SOCKET sock;
          270  +#else
   268    271       int sock;
          272  +#endif
   269    273       char channelName[20];
   270    274       UdpState *statePtr;
   271    275       uint16_t localport = 0;
   272    276       int reuse = 0;
   273    277   	struct sockaddr_storage addr,sockaddr;
   274    278   	socklen_t addr_len;
   275    279       unsigned long status = 1;
................................................................................
   370    374       
   371    375       UDPTRACE("Open socket %d. Bind socket to port %d\n", 
   372    376                sock, ntohs(localport));
   373    377   
   374    378       statePtr = (UdpState *) ckalloc((unsigned) sizeof(UdpState));
   375    379       memset(statePtr, 0, sizeof(UdpState));
   376    380       statePtr->sock = sock;
   377         -    sprintf(channelName, "sock%d", statePtr->sock);
          381  +    sprintf(channelName, "sock" SOCKET_PRINTF_FMT, statePtr->sock);
   378    382       statePtr->channel = Tcl_CreateChannel(&Udp_ChannelType, channelName,
   379    383                                             (ClientData) statePtr,
   380    384                                             (TCL_READABLE | TCL_WRITABLE | TCL_MODE_NONBLOCKING));
   381    385       statePtr->doread = 1;
   382    386       statePtr->multicast = 0;
   383    387       statePtr->groupsObj = Tcl_NewListObj(0, NULL);
   384    388       Tcl_IncrRefCount(statePtr->groupsObj);
................................................................................
   635    639                   p->actual_size = actual_size;
   636    640   #ifdef WIN32
   637    641   				/* 
   638    642   				 * In windows, do not use getnameinfo() since this function does
   639    643   				 * not work correctly in case of multithreaded. Also inet_ntop() is
   640    644   				 * not available in older windows versions.
   641    645   				 */
   642         -				if (WSAAddressToString((struct sockaddr *)&recvaddr,socksize,
          646  +				if (WSAAddressToStringA((struct sockaddr *)&recvaddr,socksize,
   643    647   					NULL,remoteaddr,&remoteaddrlen)==0) {
   644    648   					/* 
   645    649   					 * We now have an address in the format of <ip address>:<port> 
   646    650   					 * Search backwards for the last ':'
   647    651   					 */
   648    652   					portaddr = strrchr(remoteaddr,':') + 1;
   649    653   					strncpy(hostaddr,remoteaddr,strlen(remoteaddr)-strlen(portaddr)-1);
................................................................................
   804    808   {
   805    809       static int initialized = 0; /* 1 if the socket sys has been initialized. */
   806    810       static int hasSockets = 0;  /* 1 if the system supports sockets. */
   807    811       HANDLE socketThread;
   808    812       DWORD id;
   809    813       
   810    814       if (!initialized) {
   811         -        OSVERSIONINFO info;
   812         -        
   813    815           initialized = 1;
   814    816           
   815         -        /*
   816         -         * Find out if we're running on Win32s.
   817         -         */
   818         -        
   819         -        info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   820         -        GetVersionEx(&info);
   821         -        
   822         -        /*
   823         -         * Check to see if Sockets are supported on this system.  Since
   824         -         * win32s panics if we call WSAStartup on a system that doesn't
   825         -         * have winsock.dll, we need to look for it on the system first.
   826         -         * If we find winsock, then load the library and initialize the
   827         -         * stub table.
   828         -         */
   829         -        
   830         -        if ((info.dwPlatformId != VER_PLATFORM_WIN32s)
   831         -            || (SearchPath(NULL, "WINSOCK", ".DLL", 0, NULL, NULL) != 0)) {
   832         -            hasSockets = InitSockets();
   833         -        }
          817  +        /* Load the library and initialize the stub table. */
          818  +        hasSockets = InitSockets();
   834    819           
   835    820           /*
   836    821            * Start the socketThread window and set the thread priority of the
   837    822            * socketThread as highest
   838    823            */
   839    824           
   840    825           sockList = NULL;
................................................................................
   876    861    *  The socket is closed.
   877    862    *
   878    863    * ----------------------------------------------------------------------
   879    864    */
   880    865   static int 
   881    866   udpClose(ClientData instanceData, Tcl_Interp *interp)
   882    867   {
          868  +#ifdef _WIN32
          869  +    SOCKET sock;
          870  +#else
   883    871       int sock;
          872  +#endif
   884    873       int errorCode = 0;
   885    874       int objc;
   886    875       Tcl_Obj **objv;
   887    876       UdpState *statePtr = (UdpState *) instanceData;
   888    877   #ifdef WIN32
   889    878       UdpState *tmp, *p;
   890    879       
................................................................................
   937    926           errorCode = errno;
   938    927       }
   939    928       ckfree((char *) statePtr);
   940    929       if (errorCode != 0) {
   941    930   #ifndef WIN32
   942    931           sprintf(errBuf, "udp_close: %d, error: %d\n", sock, errorCode);
   943    932   #else
   944         -        sprintf(errBuf, "udp_cose: %d, error: %d\n", sock, WSAGetLastError());
          933  +        sprintf(errBuf, "udp_close: " SOCKET_PRINTF_FMT ", error: %d\n", sock, WSAGetLastError());
   945    934   #endif
   946    935           UDPTRACE("UDP error - close %d", sock);
   947    936       } else {
   948    937           UDPTRACE("Close socket %d\n", sock);
   949    938       }
   950    939       
   951    940   #ifdef WIN32
................................................................................
  1928   1917       va_list args;
  1929   1918       
  1930   1919   #ifdef WIN32
  1931   1920   
  1932   1921       static char buffer[1024];
  1933   1922       va_start (args, format);
  1934   1923       _vsnprintf(buffer, 1023, format, args);
  1935         -    OutputDebugString(buffer);
         1924  +    OutputDebugStringA(buffer);
  1936   1925   
  1937   1926   #else /* ! WIN32 */
  1938   1927   
  1939   1928       va_start (args, format);
  1940   1929       vfprintf(dbg, format, args);
  1941   1930       fflush(dbg);
  1942   1931   

Changes to generic/udp_tcl.h.

    83     83     struct PacketList *next;
    84     84   } PacketList;
    85     85   
    86     86   #endif /* WIN32 */
    87     87   
    88     88   typedef struct UdpState {
    89     89     Tcl_Channel       channel;
           90  +#ifdef _WIN32
           91  +  SOCKET            sock;
           92  +#else
    90     93     int               sock;
           94  +#endif
    91     95     char              remotehost[256]; /* send packets to */
    92     96     uint16_t          remoteport;
    93     97     char              peerhost[256];   /* receive packets from */
    94     98     uint16_t          peerport;
    95     99     uint16_t          localport;
    96    100     int               doread;
    97    101   #ifdef WIN32
................................................................................
   103    107     Tcl_ThreadId      threadId;        /* for Tcl_ThreadAlert */
   104    108   #endif
   105    109     short				ss_family;		 /* indicator set for ipv4 or ipv6 usage */
   106    110     int               multicast;       /* indicator set for multicast add */
   107    111     Tcl_Obj          *groupsObj;       /* list of the mcast groups */
   108    112   } UdpState;
   109    113   
          114  +
          115  +#if defined(WIN32) && defined(_M_AMD64)
          116  +# define SOCKET_PRINTF_FMT "%I64u"
          117  +#else
          118  +# define SOCKET_PRINTF_FMT "%d"
          119  +#endif
          120  +
   110    121   
   111    122   EXTERN int Udp_Init(Tcl_Interp *interp);
   112    123   EXTERN int Udp_SafeInit(Tcl_Interp *interp);
   113    124   
   114    125   #endif

Changes to win/makefile.vc.

    11     11   # See the file "license.terms" for information on usage and redistribution
    12     12   # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    13     13   # 
    14     14   # Copyright (c) 1995-1996 Sun Microsystems, Inc.
    15     15   # Copyright (c) 1998-2000 Ajuba Solutions.
    16     16   # Copyright (c) 2001 ActiveState Corporation.
    17     17   # Copyright (c) 2001-2002 David Gravereaux.
    18         -# Copyright (c) 2003 Pat Thoyts
           18  +# Copyright (c) 2003-2006 Pat Thoyts
    19     19   #
    20     20   #-------------------------------------------------------------------------
    21         -# RCS: @(#)$Id: makefile.vc,v 1.9 2014/08/23 05:28:40 huubeikens Exp $
           21  +# RCS: @(#)$Id$
    22     22   #-------------------------------------------------------------------------
    23     23   
    24         -!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCToolkitInstallDir)
           24  +# Check to see we are configured to build with MSVC (MSDEVDIR or MSVCDIR)
           25  +# or with the MS Platform SDK (MSSDK). Visual Studio .NET 2003 and 2005 define
           26  +# VCINSTALLDIR instead. The MSVC Toolkit release defines yet another.
           27  +!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(MSSDK) && !defined(VCINSTALLDIR) && !defined(VCToolkitInstallDir)
    25     28   MSG = ^
    26         -You will need to run vcvars32.bat from Developer Studio, first, to setup^
    27         -the environment.  Jump to this line to read the new instructions.
           29  +You need to run vcvars32.bat from Developer Studio or setenv.bat from the^
           30  +Platform SDK first to setup the environment.  Jump to this line to read^
           31  +the build instructions.
    28     32   !error $(MSG)
    29     33   !endif
    30     34   
    31     35   #------------------------------------------------------------------------------
    32     36   # HOW TO USE this makefile:
    33     37   #
    34     38   # 1)  It is now necessary to have %MSVCDir% set in the environment.  This is
................................................................................
    68     72   #		msvcrt  =  Effects the static option only to switch it from
    69     73   #			   using libcmt(d) as the C runtime [by default] to
    70     74   #			   msvcrt(d). This is useful for static embedding
    71     75   #			   support.
    72     76   #		staticpkg = Effects the static option only to switch
    73     77   #			   tclshXX.exe to have the dde and reg extension linked
    74     78   #			   inside it.
    75         -#		threads =  Turns on full multithreading support.
           79  +#		nothreads = Turns off multithreading support (not recommended)
    76     80   #		thrdalloc = Use the thread allocator (shared global free pool).
    77     81   #		symbols =  Adds symbols for step debugging.
    78     82   #		profile =  Adds profiling hooks.  Map file is assumed.
    79     83   #		loimpact =  Adds a flag for how NT treats the heap to keep memory
    80     84   #			   in use, low.  This is said to impact alloc performance.
    81     85   #
    82     86   #	STATS=memdbg,compdbg,none
................................................................................
    84     88   #		to the core.  The default is for none.  Any combination of the
    85     89   #		above may be used (comma separated).  'none' will over-ride
    86     90   #		everything to nothing.
    87     91   #
    88     92   #		memdbg   = Enables the debugging memory allocator.
    89     93   #		compdbg  = Enables byte compilation logging.
    90     94   #
    91         -#	MACHINE=(IX86|IA64|ALPHA)
           95  +#	MACHINE=(IX86|IA64|ALPHA|AMD64)
    92     96   #		Set the machine type used for the compiler, linker, and
    93     97   #		resource compiler.  This hook is needed to tell the tools
    94     98   #		when alternate platforms are requested.  IX86 is the default
    95         -#		when not specified.
           99  +#		when not specified. If the CPU environment variable has been
          100  +#		set (ie: recent Platform SDK) then MACHINE is set from CPU.
    96    101   #
    97    102   #	TMP_DIR=<path>
    98    103   #	OUT_DIR=<path>
    99    104   #		Hooks to allow the intermediate and output directories to be
   100    105   #		changed.  $(OUT_DIR) is assumed to be 
   101    106   #		$(BINROOT)\(Release|Debug) based on if symbols are requested.
   102    107   #		$(TMP_DIR) will de $(OUT_DIR)\<buildtype> by default.
................................................................................
   154    159   #-------------------------------------------------------------------------
   155    160   
   156    161   PROJECT = udp
   157    162   !include "rules.vc"
   158    163   
   159    164   DOTVERSION      = 1.0.11
   160    165   VERSION         = $(DOTVERSION:.=)
   161         -STUBPREFIX      = $(PROJECT)stub
   162    166   
   163    167   DLLOBJS = \
   164    168   	$(TMP_DIR)\udp_tcl.obj \
   165    169   	$(TMP_DIR)\tcludp.res
   166    170   
   167    171   PRJDOCS = \
   168    172   	$(OUT_DIR)\udp.html
................................................................................
   179    183   PRJLIB		= $(OUT_DIR)\$(PRJLIBNAME)
   180    184   
   181    185   PRJSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
   182    186   PRJSTUBLIB	= $(OUT_DIR)\$(PRJSTUBLIBNAME)
   183    187   
   184    188   ### Make sure we use backslash only.
   185    189   PRJ_INSTALL_DIR         = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
          190  +LIB_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
   186    191   BIN_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
   187    192   DOC_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
   188    193   SCRIPT_INSTALL_DIR	= $(PRJ_INSTALL_DIR)
   189    194   DEMO_INSTALL_DIR	= $(PRJ_INSTALL_DIR)\demos
   190    195   INCLUDE_INSTALL_DIR	= $(_TCLDIR)\include
   191         -LIB_INSTALL_DIR		= $(_TCLDIR)\lib
   192    196   
   193    197   ### The following paths CANNOT have spaces in them.
   194    198   GENERICDIR	= $(ROOT)\generic
   195    199   WINDIR		= $(ROOT)\win
   196    200   LIBDIR          = $(ROOT)\library
   197    201   DOCDIR		= $(ROOT)\doc
   198    202   DEMODIR		= $(ROOT)\demos
   199    203   TOOLSDIR	= $(ROOT)\tools
   200    204   COMPATDIR	= $(ROOT)\compat
          205  +EXPATDIR        = $(ROOT)\expat
          206  +
   201    207   
   202    208   #---------------------------------------------------------------------
   203    209   # Compile flags
   204    210   #---------------------------------------------------------------------
   205    211   
   206    212   !if !$(DEBUG)
   207    213   !if $(OPTIMIZING)
   208    214   ### This cranks the optimization level to maximize speed
   209         -cdebug	= -O2 -Op -Gs
          215  +cdebug	= $(OPTIMIZATIONS)
   210    216   !else
   211    217   cdebug	=
   212    218   !endif
   213         -!else if "$(MACHINE)" == "IA64"
          219  +!else if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
   214    220   ### Warnings are too many, can't support warnings into errors.
   215         -cdebug	= -Z7 -Od -GZ
          221  +cdebug	= -Zi -Od $(DEBUGFLAGS)
   216    222   !else
   217         -cdebug	= -Z7 -WX -Od -GZ
          223  +cdebug	= -Zi -WX $(DEBUGFLAGS)
   218    224   !endif
   219    225   
   220    226   ### Declarations common to all compiler options
   221         -cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\
   222         -
   223         -!if $(PENT_0F_ERRATA)
   224         -cflags = $(cflags) -QI0f
   225         -!endif
   226         -
   227         -!if $(ITAN_B_ERRATA)
   228         -cflags = $(cflags) -QIA64_Bx
   229         -!endif
          227  +cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE -D _WINSOCK_DEPRECATED_NO_WARNINGS
          228  +cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\
   230    229   
   231    230   !if $(MSVCRT)
   232         -!if $(DEBUG)
          231  +!if $(DEBUG) && !$(UNCHECKED)
   233    232   crt = -MDd
   234    233   !else
   235    234   crt = -MD
   236    235   !endif
   237    236   !else
   238         -!if $(DEBUG)
          237  +!if $(DEBUG) && !$(UNCHECKED)
   239    238   crt = -MTd
   240    239   !else
   241    240   crt = -MT
   242    241   !endif
   243    242   !endif
   244    243   
   245         -INCLUDES	= $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)"
   246         -BASE_CLFAGS	= $(cflags) $(cdebug) $(crt) $(INCLUDES)
          244  +!if !$(STATIC_BUILD)
          245  +cflags = $(cflags) -DUSE_TCL_STUBS
          246  +!if defined(TKSTUBLIB)
          247  +cflags = $(cflags) -DUSE_TK_STUBS
          248  +!endif
          249  +!endif
          250  +
          251  +DEFS            =-DHAVE_MEMMOVE=1 
          252  +DEFS_EXPAT	=-DXMLIMPORT=__declspec(dllexport)
          253  +INCLUDES	= -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(EXPATDIR)" $(TCL_INCLUDES)
          254  +BASE_CFLAGS	= $(cflags) $(cdebug) $(crt) $(INCLUDES)
   247    255   CON_CFLAGS	= $(cflags) $(cdebug) $(crt) -DCONSOLE
   248         -TCL_CFLAGS	= -DUSE_TCL_STUBS -DPACKAGE_NAME="\"$(PROJECT)\"" \
          256  +TCL_CFLAGS      = -DPACKAGE_NAME="\"$(PROJECT)\"" \
   249    257   		  -DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
   250         -		  $(BASE_CLFAGS) $(OPTDEFINES)
          258  +		  $(BASE_CFLAGS) $(OPTDEFINES) $(DEFS)
   251    259   
   252    260   #---------------------------------------------------------------------
   253    261   # Link flags
   254    262   #---------------------------------------------------------------------
   255    263   
   256    264   !if $(DEBUG)
   257    265   ldebug	= -debug:full -debugtype:cv
          266  +!if $(MSVCRT)
          267  +ldebug = $(ldebug) -nodefaultlib:msvcrt
          268  +!endif
   258    269   !else
   259    270   ldebug	= -release -opt:ref -opt:icf,3
   260    271   !endif
   261    272   
   262    273   ### Declarations common to all linker options
   263         -lflags	= -nologo -machine:$(MACHINE) $(ldebug) /verbose:lib
          274  +lflags	= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)
   264    275   
   265    276   !if $(PROFILE)
   266    277   lflags	= $(lflags) -profile
   267    278   !endif
   268    279   
   269    280   !if $(ALIGN98_HACK) && !$(STATIC_BUILD)
   270    281   ### Align sections for PE size savings.
................................................................................
   277    288   !if $(LOIMPACT)
   278    289   lflags	= $(lflags) -ws:aggressive
   279    290   !endif
   280    291   
   281    292   dlllflags = $(lflags) -dll
   282    293   conlflags = $(lflags) -subsystem:console
   283    294   guilflags = $(lflags) -subsystem:windows
   284         -baselibs   = $(TCLSTUBLIB) ws2_32.lib
          295  +!if !$(STATIC_BUILD)
          296  +baselibs  = $(TCLSTUBLIB)
          297  +!if defined(TKSTUBLIB)
          298  +baselibs  = $(baselibs) $(TKSTUBLIB)
          299  +!endif
          300  +!endif
          301  +
          302  +baselibs = $(baselibs) ws2_32.lib
          303  +
          304  +# Avoid 'unresolved external symbol __security_cookie' errors.
          305  +# c.f. http://support.microsoft.com/?id=894573
          306  +!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
          307  +baselibs   = $(baselibs) bufferoverflowU.lib
          308  +!endif
   285    309   
   286    310   #---------------------------------------------------------------------
   287    311   # TclTest flags
   288    312   #---------------------------------------------------------------------
   289    313   
   290    314   !IF "$(TESTPAT)" != ""
   291         -TESTFLAGS = -file $(TESTPAT)
          315  +TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)
   292    316   !ENDIF
   293    317   
   294    318   #---------------------------------------------------------------------
   295    319   # Project specific targets (EDIT)
   296    320   #---------------------------------------------------------------------
   297    321   
   298    322   all:	    setup $(PROJECT)
................................................................................
   325    349   !endif
   326    350   
   327    351   setup:
   328    352   	@if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
   329    353   	@if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
   330    354   
   331    355   $(PRJLIB): $(DLLOBJS)
   332         -	$(link32) $(dlllflags) -out:[email protected] $(baselibs) @<<
          356  +!if $(STATIC_BUILD)
          357  +	$(lib32) -nologo -out:[email protected] @<<
          358  +$**
          359  +<<
          360  +!else
          361  +	$(link32) $(dlllflags) -base:0x109E0000 -out:[email protected] $(baselibs) @<<
   333    362   $**
   334    363   <<
          364  +	$(_VC_MANIFEST_EMBED_DLL)
   335    365   	[email protected] $*.exp
   336         -
   337         -$(PRJSTUBLIB): $(PRJSTUBOBJS)
   338         -	$(lib32) -nologo -out:[email protected] $(PRJSTUBOBJS)
          366  +!endif
   339    367   
   340    368   #---------------------------------------------------------------------
   341    369   # Implicit rules
   342    370   #---------------------------------------------------------------------
   343    371   
   344    372   {$(WINDIR)}.c{$(TMP_DIR)}.obj::
   345    373       $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
................................................................................
   354    382   {$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
   355    383       $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
   356    384   $<
   357    385   <<
   358    386   
   359    387   {$(WINDIR)}.rc{$(TMP_DIR)}.res:
   360    388   	$(rc32) -fo [email protected] -r -i "$(GENERICDIR)" -D__WIN32__ \
   361         -		-DCOMMAVERSION=$(DOTVERSION:.=,),0 \
   362         -		-DDOTVERSION=\"$(DOTVERSION)\" \
   363         -		-DVERSION=\"$(VERSION)$(SUFX)\" \
          389  +                -DCOMMAVERSION=$(DOTVERSION:.=,),0 \
          390  +                -DDOTVERSION=\"$(DOTVERSION)\" \
          391  +                -DVERSION=\"$(VERSION)$(SUFX)\" \
   364    392   !if $(DEBUG)
   365    393   	-d DEBUG \
   366    394   !endif
   367    395   !if $(TCL_THREADS)
   368    396   	-d TCL_THREADS \
   369    397   !endif
   370    398   !if $(STATIC_BUILD)
................................................................................
   396    424   
   397    425   install-binaries:
   398    426   	@echo Installing binaries to '$(SCRIPT_INSTALL_DIR)'
   399    427   	@if not exist $(SCRIPT_INSTALL_DIR)\nul mkdir "$(SCRIPT_INSTALL_DIR)"
   400    428   	@$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL
   401    429   
   402    430   install-libraries:
   403         -	@echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'
   404         -#	@$(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)" >NUL
   405         -	@type << >"$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
   406         -# Handcrafted pkgIndex for tcludp.
   407         -if {[info exists ::tcl_platform(debug)]} {
   408         -    package ifneeded $(PROJECT) $(DOTVERSION) [list load [file join $$dir $(PROJECT)$(VERSION)g.$(EXT)]]
   409         -} else {
   410         -    package ifneeded $(PROJECT) $(DOTVERSION) [list load [file join $$dir $(PROJECT)$(VERSION).$(EXT)]]
   411         -}
          431  +        @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'
          432  +        @if exist $(LIBDIR)\NUL $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)" >NUL
          433  +        @echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
          434  +        @type << >"$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
          435  +    package ifneeded $(PROJECT) $(DOTVERSION) "[list load [file join $$dir $(PROJECT)$(VERSION)$(SUFX).$(EXT)] $(PROJECT)]"
   412    436   <<
   413    437   
   414    438   install-docs: $(PRJDOCS)
   415    439   	@echo Installing documentation to '$(DOC_INSTALL_DIR)'
   416    440   	@if not exist $(DOC_INSTALL_DIR)\NUL mkdir "$(DOC_INSTALL_DIR)"
   417    441   	@$(CPY) "$(DOCDIR)\manpage.css" "$(DOC_INSTALL_DIR)\" >NUL
   418    442   	@for %i in ($(PRJDOCS)) do @$(CPY) %i "$(DOC_INSTALL_DIR)\" > NUL
................................................................................
   424    448   
   425    449   #---------------------------------------------------------------------
   426    450   # Clean up
   427    451   #---------------------------------------------------------------------
   428    452   
   429    453   clean:
   430    454   	@if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
   431         -	@if exist $(WINDIR)\version.vc del $(WINDIR)\version.vc
          455  +	@if exist $(WINDIR)\versions.vc del $(WINDIR)\versions.vc
          456  +	@if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i
          457  +	@if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x
          458  +	@if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch
   432    459   
   433    460   realclean: clean
   434    461   	@if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR)
   435    462   
   436    463   distclean: realclean
   437    464   	@if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe
   438    465   	@if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj

Changes to win/nmakehlp.c.

     1         -/* ----------------------------------------------------------------------------
            1  +/*
            2  + * ----------------------------------------------------------------------------
     2      3    * nmakehlp.c --
     3      4    *
     4      5    *	This is used to fix limitations within nmake and the environment.
     5      6    *
     6      7    * Copyright (c) 2002 by David Gravereaux.
     7         - * Copyright (c) 2003 by Patrick Thoyts
            8  + * Copyright (c) 2006 by Pat Thoyts
     8      9    *
     9         - * See the file "license.terms" for information on usage and redistribution
    10         - * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    11         - *
    12         - * ----------------------------------------------------------------------------
    13         - * RCS: @(#) $Id: nmakehlp.c,v 1.2 2004/11/22 23:48:48 patthoyts Exp $
           10  + * See the file "license.terms" for information on usage and redistribution of
           11  + * this file, and for a DISCLAIMER OF ALL WARRANTIES.
    14     12    * ----------------------------------------------------------------------------
    15     13    */
           14  +
           15  +#define _CRT_SECURE_NO_DEPRECATE
    16     16   #include <windows.h>
    17         -#include <stdio.h>
           17  +#define NO_SHLWAPI_GDI
           18  +#define NO_SHLWAPI_STREAM
           19  +#define NO_SHLWAPI_REG
           20  +#include <shlwapi.h>
    18     21   #pragma comment (lib, "user32.lib")
    19     22   #pragma comment (lib, "kernel32.lib")
           23  +#pragma comment (lib, "shlwapi.lib")
           24  +#include <stdio.h>
           25  +#include <math.h>
           26  +
           27  +/*
           28  + * This library is required for x64 builds with _some_ versions of MSVC
           29  + */
           30  +#if defined(_M_IA64) || defined(_M_AMD64)
           31  +#if _MSC_VER >= 1400 && _MSC_VER < 1500
           32  +#pragma comment(lib, "bufferoverflowU")
           33  +#endif
           34  +#endif
           35  +
           36  +/* ISO hack for dumb VC++ */
           37  +#ifdef _MSC_VER
           38  +#define   snprintf	_snprintf
           39  +#endif
           40  +
           41  +
    20     42   
    21     43   /* protos */
    22         -int CheckForCompilerFeature (const char *option);
    23         -int CheckForLinkerFeature (const char *option);
    24         -int IsIn (const char *string, const char *substring);
    25         -DWORD WINAPI ReadFromPipe (LPVOID args);
    26         -int GetVersionFromHeader(const char *tclh, const char *tkh);
           44  +
           45  +static int CheckForCompilerFeature(const char *option);
           46  +static int CheckForLinkerFeature(const char **options, int count);
           47  +static int IsIn(const char *string, const char *substring);
           48  +static int SubstituteFile(const char *substs, const char *filename);
           49  +static int QualifyPath(const char *path);
           50  +static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
           51  +static DWORD WINAPI ReadFromPipe(LPVOID args);
    27     52   
    28     53   /* globals */
           54  +
           55  +#define CHUNK	25
           56  +#define STATICBUFFERSIZE    1000
    29     57   typedef struct {
    30     58       HANDLE pipe;
    31         -    char buffer[1000];
           59  +    char buffer[STATICBUFFERSIZE];
    32     60   } pipeinfo;
    33     61   
    34     62   pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
    35     63   pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
           64  +
           65  +/*
           66  + * exitcodes: 0 == no, 1 == yes, 2 == error
           67  + */
    36     68   
    37         -
    38         -
    39         -/* exitcodes: 0 == no, 1 == yes, 2 == error */
    40     69   int
    41         -main (int argc, char *argv[])
           70  +main(
           71  +    int argc,
           72  +    char *argv[])
    42     73   {
    43     74       char msg[300];
    44     75       DWORD dwWritten;
    45     76       int chars;
    46     77   
           78  +    /*
           79  +     * Make sure children (cl.exe and link.exe) are kept quiet.
           80  +     */
           81  +
           82  +    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
           83  +
           84  +    /*
           85  +     * Make sure the compiler and linker aren't effected by the outside world.
           86  +     */
           87  +
           88  +    SetEnvironmentVariable("CL", "");
           89  +    SetEnvironmentVariable("LINK", "");
           90  +
    47     91       if (argc > 1 && *argv[1] == '-') {
    48     92   	switch (*(argv[1]+1)) {
    49     93   	case 'c':
    50     94   	    if (argc != 3) {
    51         -		chars = wsprintf(msg, "usage: %s -c <compiler option>\n"
           95  +		chars = snprintf(msg, sizeof(msg) - 1,
           96  +		        "usage: %s -c <compiler option>\n"
    52     97   			"Tests for whether cl.exe supports an option\n"
    53     98   			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
    54         -		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
           99  +		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
          100  +			&dwWritten, NULL);
    55    101   		return 2;
    56    102   	    }
    57    103   	    return CheckForCompilerFeature(argv[2]);
    58    104   	case 'l':
    59         -	    if (argc != 3) {
    60         -		chars = wsprintf(msg, "usage: %s -l <linker option>\n"
          105  +	    if (argc < 3) {
          106  +		chars = snprintf(msg, sizeof(msg) - 1,
          107  +	       		"usage: %s -l <linker option> ?<mandatory option> ...?\n"
    61    108   			"Tests for whether link.exe supports an option\n"
    62    109   			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
    63         -		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
          110  +		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
          111  +			&dwWritten, NULL);
    64    112   		return 2;
    65    113   	    }
    66         -	    return CheckForLinkerFeature(argv[2]);
          114  +	    return CheckForLinkerFeature(&argv[2], argc-2);
    67    115   	case 'f':
    68    116   	    if (argc == 2) {
    69         -		chars = wsprintf(msg, "usage: %s -f <string> <substring>\n"
    70         -		    "Find a substring within another\n"
    71         -		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
    72         -		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
          117  +		chars = snprintf(msg, sizeof(msg) - 1,
          118  +			"usage: %s -f <string> <substring>\n"
          119  +			"Find a substring within another\n"
          120  +			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
          121  +		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
          122  +			&dwWritten, NULL);
    73    123   		return 2;
    74    124   	    } else if (argc == 3) {
    75         -		/* if the string is blank, there is no match */
          125  +		/*
          126  +		 * If the string is blank, there is no match.
          127  +		 */
          128  +
    76    129   		return 0;
    77    130   	    } else {
    78    131   		return IsIn(argv[2], argv[3]);
    79    132   	    }
    80         -	case 'v':
          133  +	case 's':
          134  +	    if (argc == 2) {
          135  +		chars = snprintf(msg, sizeof(msg) - 1,
          136  +			"usage: %s -s <substitutions file> <file>\n"
          137  +			"Perform a set of string map type substutitions on a file\n"
          138  +			"exitcodes: 0\n",
          139  +			argv[0]);
          140  +		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
          141  +			&dwWritten, NULL);
          142  +		return 2;
          143  +	    }
          144  +	    return SubstituteFile(argv[2], argv[3]);
          145  +	case 'V':
    81    146   	    if (argc != 4) {
    82         -		chars = wsprintf(msg, "usage: %s -v <tcl.h> <tk.h>\n"
    83         -		    "Search for versions from the tcl and tk headers.",
          147  +		chars = snprintf(msg, sizeof(msg) - 1,
          148  +		    "usage: %s -V filename matchstring\n"
          149  +		    "Extract a version from a file:\n"
          150  +		    "eg: pkgIndex.tcl \"package ifneeded http\"",
    84    151   		    argv[0]);
    85         -		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
          152  +		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
          153  +		    &dwWritten, NULL);
    86    154   		return 0;
    87    155   	    }
    88         -	    return GetVersionFromHeader(argv[2], argv[3]);
          156  +	    printf("%s\n", GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0'));
          157  +	    return 0;
          158  +	case 'Q':
          159  +	    if (argc != 3) {
          160  +		chars = snprintf(msg, sizeof(msg) - 1,
          161  +		    "usage: %s -Q path\n"
          162  +		    "Emit the fully qualified path\n"
          163  +		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
          164  +		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
          165  +		    &dwWritten, NULL);
          166  +		return 2;
          167  +	    }
          168  +	    return QualifyPath(argv[2]);
    89    169   	}
    90    170       }
    91         -    chars = wsprintf(msg, "usage: %s -c|-l|-f ...\n"
          171  +    chars = snprintf(msg, sizeof(msg) - 1,
          172  +	    "usage: %s -c|-f|-l|-Q|-s|-V ...\n"
    92    173   	    "This is a little helper app to equalize shell differences between WinNT and\n"
    93    174   	    "Win9x and get nmake.exe to accomplish its job.\n",
    94    175   	    argv[0]);
    95    176       WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
    96    177       return 2;
    97    178   }
    98         -
    99         -int
   100         -CheckForCompilerFeature (const char *option)
          179  +
          180  +static int
          181  +CheckForCompilerFeature(
          182  +    const char *option)
   101    183   {
   102    184       STARTUPINFO si;
   103    185       PROCESS_INFORMATION pi;
   104    186       SECURITY_ATTRIBUTES sa;
   105    187       DWORD threadID;
   106    188       char msg[300];
   107    189       BOOL ok;
................................................................................
   117    199       si.hStdInput = INVALID_HANDLE_VALUE;
   118    200   
   119    201       ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
   120    202       sa.nLength = sizeof(SECURITY_ATTRIBUTES);
   121    203       sa.lpSecurityDescriptor = NULL;
   122    204       sa.bInheritHandle = FALSE;
   123    205   
   124         -    /* create a non-inheritible pipe. */
          206  +    /*
          207  +     * Create a non-inheritible pipe.
          208  +     */
          209  +
   125    210       CreatePipe(&Out.pipe, &h, &sa, 0);
   126    211   
   127         -    /* dupe the write side, make it inheritible, and close the original. */
   128         -    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 
   129         -	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
          212  +    /*
          213  +     * Dupe the write side, make it inheritible, and close the original.
          214  +     */
   130    215   
   131         -    /* Same as above, but for the error side. */
          216  +    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
          217  +	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
          218  +
          219  +    /*
          220  +     * Same as above, but for the error side.
          221  +     */
          222  +
   132    223       CreatePipe(&Err.pipe, &h, &sa, 0);
   133         -    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
   134         -	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
          224  +    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
          225  +	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
   135    226   
   136         -    /* base command line */
   137         -    strcpy(cmdline, "cl.exe -nologo -c -TC -Fdtemp ");
   138         -    /* append our option for testing */
   139         -    strcat(cmdline, option);
   140         -    /* filename to compile, which exists, but is nothing and empty. */
   141         -    strcat(cmdline, " nul");
          227  +    /*
          228  +     * Base command line.
          229  +     */
          230  +
          231  +    lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch ");
          232  +
          233  +    /*
          234  +     * Append our option for testing
          235  +     */
          236  +
          237  +    lstrcat(cmdline, option);
          238  +
          239  +    /*
          240  +     * Filename to compile, which exists, but is nothing and empty.
          241  +     */
          242  +
          243  +    lstrcat(cmdline, " .\\nul");
   142    244   
   143    245       ok = CreateProcess(
   144    246   	    NULL,	    /* Module name. */
   145    247   	    cmdline,	    /* Command line. */
   146    248   	    NULL,	    /* Process handle not inheritable. */
   147    249   	    NULL,	    /* Thread handle not inheritable. */
   148    250   	    TRUE,	    /* yes, inherit handles. */
................................................................................
   150    252   	    NULL,	    /* Use parent's environment block. */
   151    253   	    NULL,	    /* Use parent's starting directory. */
   152    254   	    &si,	    /* Pointer to STARTUPINFO structure. */
   153    255   	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */
   154    256   
   155    257       if (!ok) {
   156    258   	DWORD err = GetLastError();
   157         -	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
          259  +	int chars = snprintf(msg, sizeof(msg) - 1,
          260  +		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
   158    261   
   159         -	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
   160         -		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
          262  +	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
          263  +		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
   161    264   		(300-chars), 0);
   162         -	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
          265  +	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
   163    266   	return 2;
   164    267       }
   165    268   
   166         -    /* close our references to the write handles that have now been inherited. */
          269  +    /*
          270  +     * Close our references to the write handles that have now been inherited.
          271  +     */
          272  +
   167    273       CloseHandle(si.hStdOutput);
   168    274       CloseHandle(si.hStdError);
   169    275   
   170    276       WaitForInputIdle(pi.hProcess, 5000);
   171    277       CloseHandle(pi.hThread);
   172    278   
   173         -    /* start the pipe reader threads. */
          279  +    /*
          280  +     * Start the pipe reader threads.
          281  +     */
          282  +
   174    283       pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
   175    284       pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
   176    285   
   177         -    /* block waiting for the process to end. */
          286  +    /*
          287  +     * Block waiting for the process to end.
          288  +     */
          289  +
   178    290       WaitForSingleObject(pi.hProcess, INFINITE);
   179    291       CloseHandle(pi.hProcess);
   180    292   
   181         -    /* clean up temporary files before returning */
   182         -    DeleteFile("temp.idb");
   183         -    DeleteFile("temp.pdb");
          293  +    /*
          294  +     * Wait for our pipe to get done reading, should it be a little slow.
          295  +     */
   184    296   
   185         -    /* wait for our pipe to get done reading, should it be a little slow. */
   186    297       WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
   187    298       CloseHandle(pipeThreads[0]);
   188    299       CloseHandle(pipeThreads[1]);
   189    300   
   190         -    /* look for the commandline warning code in both streams. */
   191         -    return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL);
          301  +    /*
          302  +     * Look for the commandline warning code in both streams.
          303  +     *  - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
          304  +     */
          305  +
          306  +    return !(strstr(Out.buffer, "D4002") != NULL
          307  +             || strstr(Err.buffer, "D4002") != NULL
          308  +             || strstr(Out.buffer, "D9002") != NULL
          309  +             || strstr(Err.buffer, "D9002") != NULL
          310  +             || strstr(Out.buffer, "D2021") != NULL
          311  +             || strstr(Err.buffer, "D2021") != NULL);
   192    312   }
   193         -
   194         -int
   195         -CheckForLinkerFeature (const char *option)
          313  +
          314  +static int
          315  +CheckForLinkerFeature(
          316  +    const char **options,
          317  +    int count)
   196    318   {
   197    319       STARTUPINFO si;
   198    320       PROCESS_INFORMATION pi;
   199    321       SECURITY_ATTRIBUTES sa;
   200    322       DWORD threadID;
   201    323       char msg[300];
   202    324       BOOL ok;
   203    325       HANDLE hProcess, h, pipeThreads[2];
   204         -    char cmdline[100];
          326  +    int i;
          327  +    char cmdline[255];
   205    328   
   206    329       hProcess = GetCurrentProcess();
   207    330   
   208    331       ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
   209    332       ZeroMemory(&si, sizeof(STARTUPINFO));
   210    333       si.cb = sizeof(STARTUPINFO);
   211    334       si.dwFlags   = STARTF_USESTDHANDLES;
................................................................................
   212    335       si.hStdInput = INVALID_HANDLE_VALUE;
   213    336   
   214    337       ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
   215    338       sa.nLength = sizeof(SECURITY_ATTRIBUTES);
   216    339       sa.lpSecurityDescriptor = NULL;
   217    340       sa.bInheritHandle = TRUE;
   218    341   
   219         -    /* create a non-inheritible pipe. */
          342  +    /*
          343  +     * Create a non-inheritible pipe.
          344  +     */
          345  +
   220    346       CreatePipe(&Out.pipe, &h, &sa, 0);
   221    347   
   222         -    /* dupe the write side, make it inheritible, and close the original. */
   223         -    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 
   224         -	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
          348  +    /*
          349  +     * Dupe the write side, make it inheritible, and close the original.
          350  +     */
   225    351   
   226         -    /* Same as above, but for the error side. */
          352  +    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
          353  +	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
          354  +
          355  +    /*
          356  +     * Same as above, but for the error side.
          357  +     */
          358  +
   227    359       CreatePipe(&Err.pipe, &h, &sa, 0);
   228         -    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
   229         -	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
          360  +    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
          361  +	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
   230    362   
   231         -    /* base command line */
   232         -    strcpy(cmdline, "link.exe -nologo ");
   233         -    /* append our option for testing */
   234         -    strcat(cmdline, option);
   235         -    /* filename to compile, which exists, but is nothing and empty. */
   236         -//    strcat(cmdline, " nul");
          363  +    /*
          364  +     * Base command line.
          365  +     */
          366  +
          367  +    lstrcpy(cmdline, "link.exe -nologo ");
          368  +
          369  +    /*
          370  +     * Append our option for testing.
          371  +     */
          372  +
          373  +    for (i = 0; i < count; i++) {
          374  +	lstrcat(cmdline, " \"");
          375  +	lstrcat(cmdline, options[i]);
          376  +	lstrcat(cmdline, "\"");
          377  +    }
   237    378   
   238    379       ok = CreateProcess(
   239    380   	    NULL,	    /* Module name. */
   240    381   	    cmdline,	    /* Command line. */
   241    382   	    NULL,	    /* Process handle not inheritable. */
   242    383   	    NULL,	    /* Thread handle not inheritable. */
   243    384   	    TRUE,	    /* yes, inherit handles. */
................................................................................
   245    386   	    NULL,	    /* Use parent's environment block. */
   246    387   	    NULL,	    /* Use parent's starting directory. */
   247    388   	    &si,	    /* Pointer to STARTUPINFO structure. */
   248    389   	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */
   249    390   
   250    391       if (!ok) {
   251    392   	DWORD err = GetLastError();
   252         -	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
          393  +	int chars = snprintf(msg, sizeof(msg) - 1,
          394  +		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
   253    395   
   254         -	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
   255         -		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
          396  +	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
          397  +		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
   256    398   		(300-chars), 0);
   257         -	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
          399  +	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
   258    400   	return 2;
   259    401       }
   260    402   
   261         -    /* close our references to the write handles that have now been inherited. */
          403  +    /*
          404  +     * Close our references to the write handles that have now been inherited.
          405  +     */
          406  +
   262    407       CloseHandle(si.hStdOutput);
   263    408       CloseHandle(si.hStdError);
   264    409   
   265    410       WaitForInputIdle(pi.hProcess, 5000);
   266    411       CloseHandle(pi.hThread);
   267    412   
   268         -    /* start the pipe reader threads. */
          413  +    /*
          414  +     * Start the pipe reader threads.
          415  +     */
          416  +
   269    417       pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
   270    418       pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
   271    419   
   272         -    /* block waiting for the process to end. */
          420  +    /*
          421  +     * Block waiting for the process to end.
          422  +     */
          423  +
   273    424       WaitForSingleObject(pi.hProcess, INFINITE);
   274    425       CloseHandle(pi.hProcess);
   275    426   
   276         -    /* wait for our pipe to get done reading, should it be a little slow. */
          427  +    /*
          428  +     * Wait for our pipe to get done reading, should it be a little slow.
          429  +     */
          430  +
   277    431       WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
   278    432       CloseHandle(pipeThreads[0]);
   279    433       CloseHandle(pipeThreads[1]);
   280    434   
   281         -    /* look for the commandline warning code in the stderr stream. */
   282         -    return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL);
          435  +    /*
          436  +     * Look for the commandline warning code in the stderr stream.
          437  +     */
          438  +
          439  +    return !(strstr(Out.buffer, "LNK1117") != NULL ||
          440  +	    strstr(Err.buffer, "LNK1117") != NULL ||
          441  +	    strstr(Out.buffer, "LNK4044") != NULL ||
          442  +	    strstr(Err.buffer, "LNK4044") != NULL ||
          443  +	    strstr(Out.buffer, "LNK4224") != NULL ||
          444  +	    strstr(Err.buffer, "LNK4224") != NULL);
   283    445   }
   284         -
   285         -DWORD WINAPI
   286         -ReadFromPipe (LPVOID args)
          446  +
          447  +static DWORD WINAPI
          448  +ReadFromPipe(
          449  +    LPVOID args)
   287    450   {
   288    451       pipeinfo *pi = (pipeinfo *) args;
   289    452       char *lastBuf = pi->buffer;
   290    453       DWORD dwRead;
   291    454       BOOL ok;
   292    455   
   293         -again:
   294         -    ok = ReadFile(pi->pipe, lastBuf, 25, &dwRead, 0L);
          456  +  again:
          457  +    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
          458  +	CloseHandle(pi->pipe);
          459  +	return (DWORD)-1;
          460  +    }
          461  +    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
   295    462       if (!ok || dwRead == 0) {
   296    463   	CloseHandle(pi->pipe);
   297    464   	return 0;
   298    465       }
   299    466       lastBuf += dwRead;
   300    467       goto again;
   301    468   
   302    469       return 0;  /* makes the compiler happy */
   303    470   }
   304         -
   305         -int
   306         -IsIn (const char *string, const char *substring)
          471  +
          472  +static int
          473  +IsIn(
          474  +    const char *string,
          475  +    const char *substring)
   307    476   {
   308    477       return (strstr(string, substring) != NULL);
   309    478   }
          479  +
          480  +/*
          481  + * GetVersionFromFile --
          482  + * 	Looks for a match string in a file and then returns the version
          483  + * 	following the match where a version is anything acceptable to
          484  + * 	package provide or package ifneeded.
          485  + */
   310    486   
   311         -	
   312         -static double
   313         -ReadVersionFromHeader(const char *file, const char *macro)
          487  +static const char *
          488  +GetVersionFromFile(
          489  +    const char *filename,
          490  +    const char *match,
          491  +    int numdots)
   314    492   {
   315         -    double d = 0.0;
   316         -    CHAR szBuffer[100];
   317         -    LPSTR p;
   318         -    DWORD cbBuffer = 100;
   319         -    FILE *fp = fopen(file, "r");
          493  +    size_t cbBuffer = 100;
          494  +    static char szBuffer[100];
          495  +    char *szResult = NULL;
          496  +    FILE *fp = fopen(filename, "rt");
          497  +
   320    498       if (fp != NULL) {
          499  +	/*
          500  +	 * Read data until we see our match string.
          501  +	 */
          502  +
   321    503   	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
   322         -	    if ((p = strstr(szBuffer, macro)) != NULL) {
   323         -		while (*p && !isdigit(*p)) ++p;
   324         -		d = strtod(p, NULL);
          504  +	    LPSTR p, q;
          505  +
          506  +	    p = strstr(szBuffer, match);
          507  +	    if (p != NULL) {
          508  +		/*
          509  +		 * Skip to first digit after the match.
          510  +		 */
          511  +
          512  +		p += strlen(match);
          513  +		while (*p && !isdigit(*p)) {
          514  +		    ++p;
          515  +		}
          516  +
          517  +		/*
          518  +		 * Find ending whitespace.
          519  +		 */
          520  +
          521  +		q = p;
          522  +		while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q)
          523  +			    && (!strchr("ab", q[-1])) || --numdots))) {
          524  +		    ++q;
          525  +		}
          526  +
          527  +		memcpy(szBuffer, p, q - p);
          528  +		szBuffer[q-p] = 0;
          529  +		szResult = szBuffer;
   325    530   		break;
   326    531   	    }
   327    532   	}
   328    533   	fclose(fp);
   329    534       }
   330         -    return d;
          535  +    return szResult;
          536  +}
          537  +
          538  +/*
          539  + * List helpers for the SubstituteFile function
          540  + */
          541  +
          542  +typedef struct list_item_t {
          543  +    struct list_item_t *nextPtr;
          544  +    char * key;
          545  +    char * value;
          546  +} list_item_t;
          547  +
          548  +/* insert a list item into the list (list may be null) */
          549  +static list_item_t *
          550  +list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
          551  +{
          552  +    list_item_t *itemPtr = malloc(sizeof(list_item_t));
          553  +    if (itemPtr) {
          554  +	itemPtr->key = strdup(key);
          555  +	itemPtr->value = strdup(value);
          556  +	itemPtr->nextPtr = NULL;
          557  +
          558  +	while(*listPtrPtr) {
          559  +	    listPtrPtr = &(*listPtrPtr)->nextPtr;
          560  +	}
          561  +	*listPtrPtr = itemPtr;
          562  +    }
          563  +    return itemPtr;
          564  +}
          565  +
          566  +static void
          567  +list_free(list_item_t **listPtrPtr)
          568  +{
          569  +    list_item_t *tmpPtr, *listPtr = *listPtrPtr;
          570  +    while (listPtr) {
          571  +	tmpPtr = listPtr;
          572  +	listPtr = listPtr->nextPtr;
          573  +	free(tmpPtr->key);
          574  +	free(tmpPtr->value);
          575  +	free(tmpPtr);
          576  +    }
          577  +}
          578  +
          579  +/*
          580  + * SubstituteFile --
          581  + *	As windows doesn't provide anything useful like sed and it's unreliable
          582  + *	to use the tclsh you are building against (consider x-platform builds -
          583  + *	eg compiling AMD64 target from IX86) we provide a simple substitution
          584  + *	option here to handle autoconf style substitutions.
          585  + *	The substitution file is whitespace and line delimited. The file should
          586  + *	consist of lines matching the regular expression:
          587  + *	  \s*\S+\s+\S*$
          588  + *
          589  + *	Usage is something like:
          590  + *	  nmakehlp -S << $** > [email protected]
          591  + *        @[email protected] $(PACKAGE_NAME)
          592  + *        @[email protected] $(PACKAGE_VERSION)
          593  + *        <<
          594  + */
          595  +
          596  +static int
          597  +SubstituteFile(
          598  +    const char *substitutions,
          599  +    const char *filename)
          600  +{
          601  +    size_t cbBuffer = 1024;
          602  +    static char szBuffer[1024], szCopy[1024];
          603  +    char *szResult = NULL;
          604  +    list_item_t *substPtr = NULL;
          605  +    FILE *fp, *sp;
          606  +
          607  +    fp = fopen(filename, "rt");
          608  +    if (fp != NULL) {
          609  +
          610  +	/*
          611  +	 * Build a list of substutitions from the first filename
          612  +	 */
          613  +
          614  +	sp = fopen(substitutions, "rt");
          615  +	if (sp != NULL) {
          616  +	    while (fgets(szBuffer, cbBuffer, sp) != NULL) {
          617  +		unsigned char *ks, *ke, *vs, *ve;
          618  +		ks = (unsigned char*)szBuffer;
          619  +		while (ks && *ks && isspace(*ks)) ++ks;
          620  +		ke = ks;
          621  +		while (ke && *ke && !isspace(*ke)) ++ke;
          622  +		vs = ke;
          623  +		while (vs && *vs && isspace(*vs)) ++vs;
          624  +		ve = vs;
          625  +		while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
          626  +		*ke = 0, *ve = 0;
          627  +		list_insert(&substPtr, (char*)ks, (char*)vs);
          628  +	    }
          629  +	    fclose(sp);
          630  +	}
          631  +
          632  +	/* debug: dump the list */
          633  +#ifdef _DEBUG
          634  +	{
          635  +	    int n = 0;
          636  +	    list_item_t *p = NULL;
          637  +	    for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
          638  +		fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
          639  +	    }
          640  +	}
          641  +#endif
          642  +
          643  +	/*
          644  +	 * Run the substitutions over each line of the input
          645  +	 */
          646  +
          647  +	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
          648  +	    list_item_t *p = NULL;
          649  +	    for (p = substPtr; p != NULL; p = p->nextPtr) {
          650  +		char *m = strstr(szBuffer, p->key);
          651  +		if (m) {
          652  +		    char *cp, *op, *sp;
          653  +		    cp = szCopy;
          654  +		    op = szBuffer;
          655  +		    while (op != m) *cp++ = *op++;
          656  +		    sp = p->value;
          657  +		    while (sp && *sp) *cp++ = *sp++;
          658  +		    op += strlen(p->key);
          659  +		    while (*op) *cp++ = *op++;
          660  +		    *cp = 0;
          661  +		    memcpy(szBuffer, szCopy, sizeof(szCopy));
          662  +		}
          663  +	    }
          664  +	    printf(szBuffer);
          665  +	}
          666  +
          667  +	list_free(&substPtr);
          668  +    }
          669  +    fclose(fp);
          670  +    return 0;
          671  +}
          672  +
          673  +/*
          674  + * QualifyPath --
          675  + *
          676  + *	This composes the current working directory with a provided path
          677  + *	and returns the fully qualified and normalized path.
          678  + *	Mostly needed to setup paths for testing.
          679  + */
          680  +
          681  +static int
          682  +QualifyPath(
          683  +    const char *szPath)
          684  +{
          685  +    char szCwd[MAX_PATH + 1];
          686  +    char szTmp[MAX_PATH + 1];
          687  +    char *p;
          688  +    GetCurrentDirectory(MAX_PATH, szCwd);
          689  +    while ((p = strchr(szPath, '/')) && *p)
          690  +	*p = '\\';
          691  +    PathCombine(szTmp, szCwd, szPath);
          692  +    PathCanonicalize(szCwd, szTmp);
          693  +    printf("%s\n", szCwd);
          694  +    return 0;
   331    695   }
   332    696   
   333         -int
   334         -GetVersionFromHeader(const char *tclh, const char *tkh)
   335         -{
   336         -    double dTcl = 0.0, dTk = 0.0;
   337         -    
   338         -    if (tclh != NULL)
   339         -	dTcl = ReadVersionFromHeader(tclh, "TCL_VERSION");
   340         -    if (tkh != NULL)
   341         -	dTk = ReadVersionFromHeader(tkh, "TK_VERSION");
   342         -
   343         -    if (dTcl > 0 || dTk > 0) {
   344         -	FILE *ofp = fopen("version.vc", "w");
   345         -	if (dTcl > 0)
   346         -	    fprintf(ofp, "TCL_DOTVERSION\t= %0.1f\nTCL_VERSION\t= %u\n",
   347         -		    dTcl, (int)(dTcl * 10.0));
   348         -	if (dTk > 0)
   349         -	    fprintf(ofp, "TK_DOTVERSION\t= %0.1f\nTK_VERSION\t= %u\n",
   350         -		    dTk, (int)(dTk * 10.0));
   351         -	fclose(ofp);
   352         -	return 0;
   353         -    }
   354         -    return 1;
   355         -}
          697  +/*
          698  + * Local variables:
          699  + *   mode: c
          700  + *   c-basic-offset: 4
          701  + *   fill-column: 78
          702  + *   indent-tabs-mode: t
          703  + *   tab-width: 8
          704  + * End:
          705  + */

Changes to win/rules.vc.

     1      1   #------------------------------------------------------------------------------
     2      2   # rules.vc --
     3      3   #
     4      4   #	Microsoft Visual C++ makefile include for decoding the commandline
     5      5   #	macros.  This file does not need editing to build Tcl.
     6      6   #
     7         -#	This version is modified from the Tcl source version to support
     8         -#	building extensions using nmake.
     9         -#
    10      7   # See the file "license.terms" for information on usage and redistribution
    11      8   # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    12         -# 
    13         -# Copyright (c) 2001-2002 David Gravereaux.
    14         -# Copyright (c) 2003 Patrick Thoyts
    15      9   #
    16         -#------------------------------------------------------------------------------
    17         -# RCS: @(#) $Id: rules.vc,v 1.3 2005/05/17 14:54:56 patthoyts Exp $
           10  +# Copyright (c) 2001-2003 David Gravereaux.
           11  +# Copyright (c) 2003-2008 Patrick Thoyts
    18     12   #------------------------------------------------------------------------------
    19     13   
    20     14   !ifndef _RULES_VC
    21     15   _RULES_VC = 1
    22     16   
    23     17   cc32		= $(CC)   # built-in default.
    24     18   link32		= link
................................................................................
    29     23   ### Assume the normal default.
    30     24   _INSTALLDIR	= C:\Program Files\Tcl
    31     25   !else
    32     26   ### Fix the path separators.
    33     27   _INSTALLDIR	= $(INSTALLDIR:/=\)
    34     28   !endif
    35     29   
    36         -!ifndef MACHINE
    37         -MACHINE		= IX86
    38         -!endif
    39         -
    40         -!ifndef CFG_ENCODING
    41         -CFG_ENCODING	= \"cp1252\"
    42         -!endif
    43         -
    44     30   #----------------------------------------------------------
    45     31   # Set the proper copy method to avoid overwrite questions
    46     32   # to the user when copying files and selecting the right
    47     33   # "delete all" method.
    48     34   #----------------------------------------------------------
    49     35   
    50     36   !if "$(OS)" == "Windows_NT"
    51     37   RMDIR	= rmdir /S /Q
           38  +ERRNULL  = 2>NUL
    52     39   !if ![ver | find "4.0" > nul]
    53         -CPY	= echo y | xcopy /i
    54         -!else
    55         -CPY	= xcopy /i /y
    56         -!endif
    57         -!else
    58         -CPY	= xcopy /i
    59         -RMDIR	= deltree /Y
    60         -!endif
    61         -
           40  +CPY	= echo y | xcopy /i >NUL
           41  +COPY	= copy >NUL
           42  +!else
           43  +CPY	= xcopy /i /y >NUL
           44  +COPY	= copy /y >NUL
           45  +!endif
           46  +!else # "$(OS)" != "Windows_NT"
           47  +CPY	= xcopy /i >_JUNK.OUT # On Win98 NUL does not work here.
           48  +COPY	= copy >_JUNK.OUT # On Win98 NUL does not work here.
           49  +RMDIR	= deltree /Y
           50  +NULL    = \NUL # Used in testing directory existence
           51  +ERRNULL = >NUL # Win9x shell cannot redirect stderr
           52  +!endif
           53  +MKDIR   = mkdir
           54  +
           55  +#------------------------------------------------------------------------------
           56  +# Determine the host and target architectures and compiler version.
           57  +#------------------------------------------------------------------------------
           58  +
           59  +_HASH=^#
           60  +_VC_MANIFEST_EMBED_EXE=
           61  +_VC_MANIFEST_EMBED_DLL=
           62  +VCVER=0
           63  +!if ![echo VCVERSION=_MSC_VER > vercl.x] \
           64  +    && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \
           65  +    && ![echo ARCH=IX86 >> vercl.x] \
           66  +    && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
           67  +    && ![echo ARCH=AMD64 >> vercl.x] \
           68  +    && ![echo $(_HASH)endif >> vercl.x] \
           69  +    && ![cl -nologo -TC -P vercl.x $(ERRNULL)]
           70  +!include vercl.i
           71  +!if ![echo VCVER= ^\> vercl.vc] \
           72  +    && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]
           73  +!include vercl.vc
           74  +!endif
           75  +!endif
           76  +!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc]
           77  +!endif
           78  +
           79  +!if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86]
           80  +NATIVE_ARCH=IX86
           81  +!else
           82  +NATIVE_ARCH=AMD64
           83  +!endif
           84  +
           85  +# Since MSVC8 we must deal with manifest resources.
           86  +!if $(VCVERSION) >= 1400
           87  +_VC_MANIFEST_EMBED_EXE=if exist [email protected] mt -nologo -manifest [email protected] -outputresource:[email protected];1
           88  +_VC_MANIFEST_EMBED_DLL=if exist [email protected] mt -nologo -manifest [email protected] -outputresource:[email protected];2
           89  +!endif
           90  +
           91  +!ifndef MACHINE
           92  +MACHINE=$(ARCH)
           93  +!endif
           94  +
           95  +!ifndef CFG_ENCODING
           96  +CFG_ENCODING	= \"cp1252\"
           97  +!endif
    62     98   
    63     99   !message ===============================================================================
    64    100   
    65    101   #----------------------------------------------------------
    66    102   # build the helper app we need to overcome nmake's limiting
    67    103   # environment.
    68    104   #----------------------------------------------------------
    69    105   
    70    106   !if !exist(nmakehlp.exe)
    71         -!if [$(cc32) -nologo -ML nmakehlp.c -link -subsystem:console > nul]
          107  +!if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul]
    72    108   !endif
    73    109   !endif
    74    110   
    75    111   #----------------------------------------------------------
    76    112   # Test for compiler features
    77    113   #----------------------------------------------------------
    78    114   
    79    115   ### test for optimizations
    80         -!if [nmakehlp -c -Otip]
          116  +!if [nmakehlp -c -Ot]
    81    117   !message *** Compiler has 'Optimizations'
    82    118   OPTIMIZING	= 1
    83    119   !else
    84         -!message *** Compiler doesn't have 'Optimizations'
          120  +!message *** Compiler does not have 'Optimizations'
    85    121   OPTIMIZING	= 0
    86    122   !endif
          123  +
          124  +OPTIMIZATIONS   =
          125  +
          126  +!if [nmakehlp -c -Ot]
          127  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -Ot
          128  +!endif
          129  +
          130  +!if [nmakehlp -c -Oi]
          131  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -Oi
          132  +!endif
          133  +
          134  +!if [nmakehlp -c -Op]
          135  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -Op
          136  +!endif
          137  +
          138  +!if [nmakehlp -c -fp:strict]
          139  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -fp:strict
          140  +!endif
          141  +
          142  +!if [nmakehlp -c -Gs]
          143  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -Gs
          144  +!endif
          145  +
          146  +!if [nmakehlp -c -GS]
          147  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -GS
          148  +!endif
          149  +
          150  +!if [nmakehlp -c -GL]
          151  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -GL
          152  +!endif
          153  +
          154  +DEBUGFLAGS     =
          155  +
          156  +!if [nmakehlp -c -RTC1]
          157  +DEBUGFLAGS     = $(DEBUGFLAGS) -RTC1
          158  +!elseif [nmakehlp -c -GZ]
          159  +DEBUGFLAGS     = $(DEBUGFLAGS) -GZ
          160  +!endif
          161  +
          162  +COMPILERFLAGS  =-W3 /DUNICODE /D_UNICODE /D_ATL_XP_TARGETING
          163  +
          164  +# In v13 -GL and -YX are incompatible.
          165  +!if [nmakehlp -c -YX]
          166  +!if ![nmakehlp -c -GL]
          167  +OPTIMIZATIONS  = $(OPTIMIZATIONS) -YX
          168  +!endif
          169  +!endif
    87    170   
    88    171   !if "$(MACHINE)" == "IX86"
    89    172   ### test for pentium errata
    90    173   !if [nmakehlp -c -QI0f]
    91    174   !message *** Compiler has 'Pentium 0x0f fix'
    92         -PENT_0F_ERRATA	= 1
          175  +COMPILERFLAGS  = $(COMPILERFLAGS) -QI0f
    93    176   !else
    94         -!message *** Compiler doesn't have 'Pentium 0x0f fix'
    95         -PENT_0F_ERRATA	= 0
          177  +!message *** Compiler does not have 'Pentium 0x0f fix'
    96    178   !endif
    97         -### test for -align:4096, when align:512 will do.
    98         -!if [nmakehlp -l -opt:nowin98]
    99         -!message *** Linker has 'Win98 alignment problem'
   100         -ALIGN98_HACK	= 1
   101         -!else
   102         -!message *** Linker doesn't have 'Win98 alignment problem'
   103         -ALIGN98_HACK	= 0
   104         -!endif
   105         -!else
   106         -PENT_0F_ERRATA	= 0
   107         -ALIGN98_HACK	= 0
   108    179   !endif
   109    180   
   110    181   !if "$(MACHINE)" == "IA64"
   111    182   ### test for Itanium errata
   112    183   !if [nmakehlp -c -QIA64_Bx]
   113    184   !message *** Compiler has 'B-stepping errata workarounds'
   114         -ITAN_B_ERRATA	= 1
          185  +COMPILERFLAGS   = $(COMPILERFLAGS) -QIA64_Bx
   115    186   !else
   116         -!message *** Compiler doesn't have 'B-stepping errata workarounds'
   117         -ITAN_B_ERRATA	= 0
          187  +!message *** Compiler does not have 'B-stepping errata workarounds'
          188  +!endif
          189  +!endif
          190  +
          191  +# Prevents "LNK1561: entry point must be defined" error compiling from VS-IDE:
          192  +!ifndef LINKER_TESTFLAGS
          193  +LINKER_TESTFLAGS = /DLL /NOENTRY /OUT:nmhlp-out.txt
          194  +!endif
          195  +
          196  +!if "$(MACHINE)" == "IX86"
          197  +### test for -align:4096, when align:512 will do.
          198  +!if [nmakehlp -l -opt:nowin98 $(LINKER_TESTFLAGS)]
          199  +!message *** Linker has 'Win98 alignment problem'
          200  +ALIGN98_HACK	= 1
          201  +!else
          202  +!message *** Linker does not have 'Win98 alignment problem'
          203  +ALIGN98_HACK	= 0
   118    204   !endif
   119    205   !else
   120         -ITAN_B_ERRATA	= 0
          206  +ALIGN98_HACK	= 0
          207  +!endif
          208  +
          209  +LINKERFLAGS     =
          210  +
          211  +!if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)]
          212  +LINKERFLAGS     =-ltcg
   121    213   !endif
   122    214   
   123    215   #----------------------------------------------------------
   124    216   # Decode the options requested.
   125    217   #----------------------------------------------------------
   126    218   
   127    219   !if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"]
   128    220   STATIC_BUILD	= 0
   129         -TCL_THREADS	= 0
          221  +TCL_THREADS	= 1
   130    222   DEBUG		= 0
          223  +SYMBOLS		= 0
   131    224   PROFILE		= 0
   132         -MSVCRT		= 0
          225  +PGO		= 0
          226  +MSVCRT		= 1
   133    227   LOIMPACT	= 0
   134    228   TCL_USE_STATIC_PACKAGES	= 0
   135         -USE_THREAD_ALLOC = 0
          229  +USE_THREAD_ALLOC = 1
          230  +UNCHECKED	= 0
   136    231   !else
   137    232   !if [nmakehlp -f $(OPTS) "static"]
   138    233   !message *** Doing static
   139    234   STATIC_BUILD	= 1
   140    235   !else
   141    236   STATIC_BUILD	= 0
   142    237   !endif
          238  +!if [nmakehlp -f $(OPTS) "nomsvcrt"]
          239  +!message *** Doing nomsvcrt
          240  +MSVCRT		= 0
          241  +!else
   143    242   !if [nmakehlp -f $(OPTS) "msvcrt"]
   144    243   !message *** Doing msvcrt
   145    244   MSVCRT		= 1
   146    245   !else
          246  +!if !$(STATIC_BUILD)
          247  +MSVCRT		= 1
          248  +!else
   147    249   MSVCRT		= 0
   148    250   !endif
   149         -!if [nmakehlp -f $(OPTS) "staticpkg"]
          251  +!endif
          252  +!endif
          253  +!if [nmakehlp -f $(OPTS) "staticpkg"] && $(STATIC_BUILD)
   150    254   !message *** Doing staticpkg
   151    255   TCL_USE_STATIC_PACKAGES	= 1
   152    256   !else
   153    257   TCL_USE_STATIC_PACKAGES	= 0
   154    258   !endif
   155         -!if [nmakehlp -f $(OPTS) "threads"]
   156         -!message *** Doing threads
          259  +!if [nmakehlp -f $(OPTS) "nothreads"]
          260  +!message *** Compile explicitly for non-threaded tcl
          261  +TCL_THREADS	= 0
          262  +USE_THREAD_ALLOC= 0
          263  +!else
   157    264   TCL_THREADS	= 1
   158         -!else
   159         -TCL_THREADS	= 0
          265  +USE_THREAD_ALLOC= 1
   160    266   !endif
   161    267   !if [nmakehlp -f $(OPTS) "symbols"]
   162    268   !message *** Doing symbols
   163    269   DEBUG		= 1
   164    270   !else
   165    271   DEBUG		= 0
          272  +!endif
          273  +!if [nmakehlp -f $(OPTS) "pdbs"]
          274  +!message *** Doing pdbs
          275  +SYMBOLS		= 1
          276  +!else
          277  +SYMBOLS		= 0
   166    278   !endif
   167    279   !if [nmakehlp -f $(OPTS) "profile"]
   168    280   !message *** Doing profile
   169    281   PROFILE		= 1
   170    282   !else
   171    283   PROFILE		= 0
          284  +!endif
          285  +!if [nmakehlp -f $(OPTS) "pgi"]
          286  +!message *** Doing profile guided optimization instrumentation
          287  +PGO		= 1
          288  +!elseif [nmakehlp -f $(OPTS) "pgo"]
          289  +!message *** Doing profile guided optimization
          290  +PGO		= 2
          291  +!else
          292  +PGO		= 0
   172    293   !endif
   173    294   !if [nmakehlp -f $(OPTS) "loimpact"]
   174    295   !message *** Doing loimpact
   175    296   LOIMPACT	= 1
   176    297   !else
   177    298   LOIMPACT	= 0
   178    299   !endif
   179    300   !if [nmakehlp -f $(OPTS) "thrdalloc"]
   180    301   !message *** Doing thrdalloc
   181    302   USE_THREAD_ALLOC = 1
   182         -!else
          303  +!endif
          304  +!if [nmakehlp -f $(OPTS) "tclalloc"]
          305  +!message *** Doing tclalloc
   183    306   USE_THREAD_ALLOC = 0
   184    307   !endif
          308  +!if [nmakehlp -f $(OPTS) "unchecked"]
          309  +!message *** Doing unchecked
          310  +UNCHECKED = 1
          311  +!else
          312  +UNCHECKED = 0
   185    313   !endif
   186         -
   187         -
   188         -!if !$(STATIC_BUILD)
   189         -# Make sure we don't build overly fat DLLs.
   190         -MSVCRT		= 1
   191         -# We shouldn't statically put the extensions inside the shell when dynamic.
   192         -TCL_USE_STATIC_PACKAGES = 0
   193    314   !endif
   194         -
   195    315   
   196    316   #----------------------------------------------------------
   197    317   # Figure-out how to name our intermediate and output directories.
   198    318   # We wouldn't want different builds to use the same .obj files
   199    319   # by accident.
   200    320   #----------------------------------------------------------
   201    321   
          322  +#----------------------------------------
          323  +# Naming convention:
          324  +#   t = full thread support.
          325  +#   s = static library (as opposed to an
          326  +#	import library)
          327  +#   g = linked to the debug enabled C
          328  +#	run-time.
          329  +#   x = special static build when it
          330  +#	links to the dynamic C run-time.
          331  +#----------------------------------------
   202    332   SUFX	    = tsgx
   203    333   
   204    334   !if $(DEBUG)
   205    335   BUILDDIRTOP = Debug
   206         -DBGX	    = g
   207    336   !else
   208    337   BUILDDIRTOP = Release
   209         -DBGX	    =
          338  +!endif
          339  +
          340  +!if "$(MACHINE)" != "IX86"
          341  +BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)
          342  +!endif
          343  +!if $(VCVER) > 6
          344  +BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)
          345  +!endif
          346  +
          347  +!if !$(DEBUG) || $(DEBUG) && $(UNCHECKED)
   210    348   SUFX	    = $(SUFX:g=)
   211    349   !endif
   212    350   
   213    351   TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX
   214    352   
   215    353   !if !$(STATIC_BUILD)
   216    354   TMP_DIRFULL = $(TMP_DIRFULL:Static=)
   217    355   SUFX	    = $(SUFX:s=)
   218    356   EXT	    = dll
   219         -!if $(MSVCRT)
   220    357   TMP_DIRFULL = $(TMP_DIRFULL:X=)
   221    358   SUFX	    = $(SUFX:x=)
   222         -!endif
   223    359   !else
   224    360   TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
   225    361   EXT	    = lib
   226    362   !if !$(MSVCRT)
   227    363   TMP_DIRFULL = $(TMP_DIRFULL:X=)
   228    364   SUFX	    = $(SUFX:x=)
   229    365   !endif
................................................................................
   264    400   !message *** Doing compdbg
   265    401   TCL_COMPILE_DEBUG   = 1
   266    402   !else
   267    403   TCL_COMPILE_DEBUG   = 0
   268    404   !endif
   269    405   !endif
   270    406   
          407  +
          408  +#----------------------------------------------------------
          409  +# Decode the checks requested.
          410  +#----------------------------------------------------------
          411  +
          412  +!if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"]
          413  +TCL_NO_DEPRECATED	    = 0
          414  +WARNINGS		    = -W3
          415  +!else
          416  +!if [nmakehlp -f $(CHECKS) "nodep"]
          417  +!message *** Doing nodep check
          418  +TCL_NO_DEPRECATED	    = 1
          419  +!else
          420  +TCL_NO_DEPRECATED	    = 0
          421  +!endif
          422  +!if [nmakehlp -f $(CHECKS) "fullwarn"]
          423  +!message *** Doing full warnings check
          424  +WARNINGS		    = -W4
          425  +!if [nmakehlp -l -warn:3 $(LINKER_TESTFLAGS)]
          426  +LINKERFLAGS		    = $(LINKERFLAGS) -warn:3
          427  +!endif
          428  +!else
          429  +WARNINGS		    = -W3
          430  +!endif
          431  +!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
          432  +!message *** Doing 64bit portability warnings
          433  +WARNINGS		    = $(WARNINGS) -Wp64
          434  +!endif
          435  +!endif
          436  +
          437  +!if $(PGO) > 1
          438  +!if [nmakehlp -l -ltcg:pgoptimize $(LINKER_TESTFLAGS)]
          439  +LINKERFLAGS	= $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize
          440  +!else
          441  +MSG=^
          442  +This compiler does not support profile guided optimization.
          443  +!error $(MSG)
          444  +!endif
          445  +!elseif $(PGO) > 0
          446  +!if [nmakehlp -l -ltcg:pginstrument $(LINKER_TESTFLAGS)]
          447  +LINKERFLAGS	= $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument
          448  +!else
          449  +MSG=^
          450  +This compiler does not support profile guided optimization.
          451  +!error $(MSG)
          452  +!endif
          453  +!endif
   271    454   
   272    455   #----------------------------------------------------------
   273    456   # Set our defines now armed with our options.
   274    457   #----------------------------------------------------------
   275    458   
   276         -OPTDEFINES	= -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING)
          459  +OPTDEFINES	= -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS
   277    460   
   278    461   !if $(TCL_MEM_DEBUG)
   279         -OPTDEFINES	= -DTCL_MEM_DEBUG
          462  +OPTDEFINES	= $(OPTDEFINES) -DTCL_MEM_DEBUG
   280    463   !endif
   281    464   !if $(TCL_COMPILE_DEBUG)
   282    465   OPTDEFINES	= $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
   283    466   !endif
   284    467   !if $(TCL_THREADS)
   285    468   OPTDEFINES	= $(OPTDEFINES) -DTCL_THREADS=1
   286    469   !if $(USE_THREAD_ALLOC)
   287    470   OPTDEFINES	= $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
   288    471   !endif
   289    472   !endif
   290    473   !if $(STATIC_BUILD)
   291    474   OPTDEFINES	= $(OPTDEFINES) -DSTATIC_BUILD
   292    475   !endif
          476  +!if $(TCL_NO_DEPRECATED)
          477  +OPTDEFINES	= $(OPTDEFINES) -DTCL_NO_DEPRECATED
          478  +!endif
   293    479   
   294         -!if $(DEBUG)
   295         -OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_DEBUG
   296         -!elseif $(OPTIMIZING)
          480  +!if !$(DEBUG)
          481  +OPTDEFINES	= $(OPTDEFINES) -DNDEBUG
          482  +!if $(OPTIMIZING)
   297    483   OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_OPTIMIZED
          484  +!endif
   298    485   !endif
   299    486   !if $(PROFILE)
   300    487   OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_PROFILED
   301    488   !endif
   302         -!if "$(MACHINE)" == "IA64"
          489  +!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
   303    490   OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_DO64BIT
   304    491   !endif
   305         -
          492  +!if $(VCVERSION) < 1300
          493  +OPTDEFINES	= $(OPTDEFINES) -DNO_STRTOI64
          494  +!endif
   306    495   
   307    496   #----------------------------------------------------------
   308         -# Get common info used when building extensions.
          497  +# Locate the Tcl headers to build against
   309    498   #----------------------------------------------------------
   310    499   
   311         -!if "$(PROJECT)" != "tcl"
          500  +!if "$(PROJECT)" == "tcl"
          501  +
          502  +_TCL_H          = ..\generic\tcl.h
          503  +
          504  +!else
   312    505   
   313    506   # If INSTALLDIR set to tcl root dir then reset to the lib dir.
   314    507   !if exist("$(_INSTALLDIR)\include\tcl.h")
   315    508   _INSTALLDIR=$(_INSTALLDIR)\lib
   316    509   !endif
   317    510   
   318    511   !if !defined(TCLDIR)
................................................................................
   336    529   _TCL_H          = $(_TCLDIR)\generic\tcl.h
   337    530   !else
   338    531   MSG =^
   339    532   Failed to find tcl.h.  The TCLDIR macro does not appear correct.
   340    533   !error $(MSG)
   341    534   !endif
   342    535   !endif
          536  +!endif
   343    537   
   344         -!if [nmakehlp -v "$(_TCL_H)" ""] == 0
   345         -!include version.vc
   346         -!else
   347         -TCL_DOTVERSION  = 8.5
   348         -TCL_VERSION	= $(TCL_DOTVERSION:.=)
          538  +#--------------------------------------------------------------
          539  +# Extract various version numbers from tcl headers
          540  +# The generated file is then included in the makefile.
          541  +#--------------------------------------------------------------
          542  +
          543  +!if [echo REM = This file is generated from rules.vc > versions.vc]
   349    544   !endif
          545  +!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
          546  +   && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc]
          547  +!endif
          548  +!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
          549  +   && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
          550  +!endif
          551  +!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
          552  +   && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
          553  +!endif
          554  +
          555  +# If building the tcl core then we need additional package versions
          556  +!if "$(PROJECT)" == "tcl"
          557  +!if [echo PKG_HTTP_VER = \>> versions.vc] \
          558  +   && [nmakehlp -V ..\library\http\pkgIndex.tcl http >> versions.vc]
          559  +!endif
          560  +!if [echo PKG_TCLTEST_VER = \>> versions.vc] \
          561  +   && [nmakehlp -V ..\library\tcltest\pkgIndex.tcl tcltest >> versions.vc]
          562  +!endif
          563  +!if [echo PKG_MSGCAT_VER = \>> versions.vc] \
          564  +   && [nmakehlp -V ..\library\msgcat\pkgIndex.tcl msgcat >> versions.vc]
          565  +!endif
          566  +!if [echo PKG_PLATFORM_VER = \>> versions.vc] \
          567  +   && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform " >> versions.vc]
          568  +!endif
          569  +!if [echo PKG_SHELL_VER = \>> versions.vc] \
          570  +   && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform::shell" >> versions.vc]
          571  +!endif
          572  +!if [echo PKG_DDE_VER = \>> versions.vc] \
          573  +   && [nmakehlp -V ..\library\dde\pkgIndex.tcl "dde " >> versions.vc]
          574  +!endif
          575  +!if [echo PKG_REG_VER =\>> versions.vc] \
          576  +   && [nmakehlp -V ..\library\reg\pkgIndex.tcl registry >> versions.vc]
          577  +!endif
          578  +!endif
          579  +
          580  +!include versions.vc
          581  +
          582  +#--------------------------------------------------------------
          583  +# Setup tcl version dependent stuff headers
          584  +#--------------------------------------------------------------
          585  +
          586  +!if "$(PROJECT)" != "tcl"
          587  +
          588  +TCL_VERSION	= $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
   350    589   
   351    590   !if $(TCLINSTALL)
   352    591   TCLSH		= "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
          592  +!if !exist($(TCLSH)) && $(TCL_THREADS)
          593  +TCLSH           = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION).exe"
          594  +!endif
   353    595   TCLSTUBLIB	= "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib"
   354    596   TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
   355    597   TCL_LIBRARY	= $(_TCLDIR)\lib
          598  +TCLREGLIB	= "$(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib"
          599  +TCLDDELIB	= "$(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib"
          600  +COFFBASE	= \must\have\tcl\sources\to\build\this\target
          601  +TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
   356    602   TCL_INCLUDES    = -I"$(_TCLDIR)\include"
   357    603   !else
   358    604   TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
          605  +!if !exist($(TCLSH)) && $(TCL_THREADS)
          606  +TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION).exe"
          607  +!endif
   359    608   TCLSTUBLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib"
   360    609   TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
   361    610   TCL_LIBRARY	= $(_TCLDIR)\library
          611  +TCLREGLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib"
          612  +TCLDDELIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib"
          613  +COFFBASE	= "$(_TCLDIR)\win\coffbase.txt"
          614  +TCLTOOLSDIR	= $(_TCLDIR)\tools
   362    615   TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
   363    616   !endif
   364    617   
   365    618   !endif
   366    619   
   367         -#----------------------------------------------------------
   368         -# Get Tk info for building extensions.
   369         -#----------------------------------------------------------
          620  +#-------------------------------------------------------------------------
          621  +# Locate the Tk headers to build against
          622  +#-------------------------------------------------------------------------
          623  +
          624  +!if "$(PROJECT)" == "tk"
          625  +_TK_H          = ..\generic\tk.h
          626  +_INSTALLDIR    = $(_INSTALLDIR)\..
          627  +!endif
   370    628   
   371         -!if "$(PROJECT)" != "tcl" && "$(PROJECT)" != "tk"
   372         -
          629  +!ifdef PROJECT_REQUIRES_TK
   373    630   !if !defined(TKDIR)
   374    631   !if exist("$(_INSTALLDIR)\..\include\tk.h")
   375    632   TKINSTALL      = 1
   376    633   _TKDIR         = $(_INSTALLDIR)\..
   377    634   _TK_H          = $(_TKDIR)\include\tk.h
   378    635   TKDIR          = $(_TKDIR)
   379    636   !elseif exist("$(_TCLDIR)\include\tk.h")
   380    637   TKINSTALL      = 1
   381    638   _TKDIR         = $(_TCLDIR)
   382    639   _TK_H          = $(_TKDIR)\include\tk.h
   383    640   TKDIR          = $(_TKDIR)
   384         -!else
   385         -MSG =^
   386         -Failed to find tk.h. Set the TKDIR macro.
   387         -!error $(MSG)
   388    641   !endif
   389    642   !else
   390    643   _TKDIR = $(TKDIR:/=\)
   391    644   !if exist("$(_TKDIR)\include\tk.h")
   392    645   TKINSTALL      = 1
   393    646   _TK_H          = $(_TKDIR)\include\tk.h
   394    647   !elseif exist("$(_TKDIR)\generic\tk.h")
................................................................................
   396    649   _TK_H          = $(_TKDIR)\generic\tk.h
   397    650   !else
   398    651   MSG =^
   399    652   Failed to find tk.h. The TKDIR macro does not appear correct.
   400    653   !error $(MSG)
   401    654   !endif
   402    655   !endif
          656  +!endif
          657  +
          658  +#-------------------------------------------------------------------------
          659  +# Extract Tk version numbers
          660  +#-------------------------------------------------------------------------
          661  +
          662  +!if defined(PROJECT_REQUIRES_TK) || "$(PROJECT)" == "tk"
   403    663   
   404         -!if [nmakehlp -v "$(_TCL_H)" "$(_TK_H)"] == 0
   405         -!include version.vc
   406         -!else
   407         -TK_DOTVERSION	= 8.5
   408         -TK_VERSION	= $(TK_DOTVERSION:.=)
          664  +!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
          665  +   && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc]
          666  +!endif
          667  +!if [echo TK_MINOR_VERSION = \>> versions.vc] \
          668  +   && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
          669  +!endif
          670  +!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
          671  +   && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
   409    672   !endif
   410    673   
          674  +!include versions.vc
          675  +
          676  +TK_DOTVERSION	= $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
          677  +TK_VERSION	= $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
          678  +
          679  +!if "$(PROJECT)" != "tk"
   411    680   !if $(TKINSTALL)
   412    681   WISH		= "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe"
   413    682   TKSTUBLIB	= "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib"
   414    683   TKIMPLIB	= "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib"
   415    684   TK_INCLUDES     = -I"$(_TKDIR)\include"
   416    685   !else
   417    686   WISH		= "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe"
   418    687   TKSTUBLIB	= "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib"
   419    688   TKIMPLIB	= "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib"
   420    689   TK_INCLUDES     = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
   421    690   !endif
   422         -
   423    691   !endif
   424    692   
   425         -
          693  +!endif
   426    694   
   427    695   #----------------------------------------------------------
   428    696   # Display stats being used.
   429    697   #----------------------------------------------------------
   430    698   
   431    699   !message *** Intermediate directory will be '$(TMP_DIR)'
   432    700   !message *** Output directory will be '$(OUT_DIR)'
   433    701   !message *** Suffix for binaries will be '$(SUFX)'
   434    702   !message *** Optional defines are '$(OPTDEFINES)'
          703  +!message *** Compiler version $(VCVER). Target machine is $(MACHINE)
          704  +!message *** Host architecture is $(NATIVE_ARCH)
          705  +!message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)'
          706  +!message *** Link options '$(LINKERFLAGS)'
   435    707   
   436    708   !endif