Itk - the [incr Tk] extension

Check-in [c8e108e7ab]
Login

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

Overview
Comment:Fixes for building with Visual C++ compilers. Tested with VC++ 6 (32-bit) and 2003 SDK compiler (64-bit).

C sources changed to conform to C89 (instead of C99). makefile.vc and nmakehlp.c updated (too many changes to list) Build expects Itcl to reside in a directory called itcl that is the sibling of the itk directory. nmake install also works but nmake winhelp (docs) does not as it relies on an external program hrtf.exe which I do not have.

Only verified with the demo itkedit script after modifying the Iwidgets package to use Itk 4 instead of Itk 3. The test scripts fail with errors that I believe are not related to Windows.

Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | apn-itk-vc-fixes
Files: files | file ages | folders
SHA1: c8e108e7abe7d653a9e60a25614c839ec8d629f2
User & Date: apnadkarni 2016-08-20 15:16:39.100
Context
2016-08-20
16:22
Added some comments about building check-in: 578b11705d user: apnadkarni tags: apn-itk-vc-fixes
15:16
Fixes for building with Visual C++ compilers. Tested with VC++ 6 (32-bit) and 2003 SDK compiler (64-bit).

C sources changed to conform to C89 (instead of C99). makefile.vc and nmakehlp.c updated (too many changes to list) Build expects Itcl to reside in a directory called itcl that is the sibling of the itk directory. nmake install also works but nmake winhelp (docs) does not as it relies on an external program hrtf.exe which I do not have.

Only verified with the demo itkedit script after modifying the Iwidgets package to use Itk 4 instead of Itk 3. The test scripts fail with errors that I believe are not related to Windows. check-in: c8e108e7ab user: apnadkarni tags: apn-itk-vc-fixes

2016-03-01
15:43
merge release check-in: 3f7b7e2865 user: dgp tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/itk.h.
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#ifndef TCL_FINAL_RELEASE
#   define TCL_FINAL_RELEASE	2
#endif


#define ITK_MAJOR_VERSION	4
#define ITK_MINOR_VERSION	0
#define ITK_RELEASE_LEVEL	TCL_RELEASE
#define ITK_RELEASE_SERIAL	2

#define ITK_VERSION		"4.0"
#define ITK_PATCH_LEVEL		"4.0.2"


/*







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#ifndef TCL_FINAL_RELEASE
#   define TCL_FINAL_RELEASE	2
#endif


#define ITK_MAJOR_VERSION	4
#define ITK_MINOR_VERSION	0
#define ITK_RELEASE_LEVEL	TCL_FINAL_RELEASE
#define ITK_RELEASE_SERIAL	2

#define ITK_VERSION		"4.0"
#define ITK_PATCH_LEVEL		"4.0.2"


/*
Changes to generic/itkArchBase.c.
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

203

204
205
206
207
208
209
210
    ArchMergeInfo *mergeInfo = NULL;
    Tcl_Obj *objNamePtr = NULL;
    Tcl_Obj *tmpNamePtr = NULL;
    Tcl_Obj *winNamePtr = NULL;
    Tcl_Obj *hullNamePtr = NULL;
    int pLevel = ITCL_PUBLIC;

    ItclShowArgs(1, "Itk_ArchCompAddCmd", objc, objv);
    int newEntry;
    int result;
    CONST char *cmd;
    CONST char *token;
    CONST char *resultStr;
    Tcl_CallFrame frame;
    char *name;
    Tcl_Namespace *parserNs;
    ItclClass *contextClass;
    ItclClass *ownerClass;
    ItclObject *contextObj;
    ArchInfo *info;
    Tcl_Command accessCmd;
    Tcl_Obj *objPtr;
    Tcl_DString buffer;
    Tcl_CallFrame *uplevelFramePtr;
    Tcl_CallFrame *oldFramePtr = NULL;
    ItclObjectInfo *infoPtr;
    ItclCallContext *callContextPtr;



    /*
     *  Get the Archetype info associated with this widget.
     */
    contextClass = NULL;
    if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
        !contextObj) {








<



















>

>







176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    ArchMergeInfo *mergeInfo = NULL;
    Tcl_Obj *objNamePtr = NULL;
    Tcl_Obj *tmpNamePtr = NULL;
    Tcl_Obj *winNamePtr = NULL;
    Tcl_Obj *hullNamePtr = NULL;
    int pLevel = ITCL_PUBLIC;


    int newEntry;
    int result;
    CONST char *cmd;
    CONST char *token;
    CONST char *resultStr;
    Tcl_CallFrame frame;
    char *name;
    Tcl_Namespace *parserNs;
    ItclClass *contextClass;
    ItclClass *ownerClass;
    ItclObject *contextObj;
    ArchInfo *info;
    Tcl_Command accessCmd;
    Tcl_Obj *objPtr;
    Tcl_DString buffer;
    Tcl_CallFrame *uplevelFramePtr;
    Tcl_CallFrame *oldFramePtr = NULL;
    ItclObjectInfo *infoPtr;
    ItclCallContext *callContextPtr;
    Tcl_Namespace *ownerNsPtr;

    ItclShowArgs(1, "Itk_ArchCompAddCmd", objc, objv);
    /*
     *  Get the Archetype info associated with this widget.
     */
    contextClass = NULL;
    if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
        !contextObj) {

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361


    /*
     *  Create the component record.  Set the protection level
     *  according to the "-protected" or "-private" option.
     */
    ownerClass = contextClass;
    Tcl_Namespace *ownerNsPtr;
    callContextPtr = Itcl_PeekStack(&infoPtr->contextStack);
    ownerNsPtr = callContextPtr->nsPtr;
    if (ownerNsPtr != NULL) {
        Tcl_HashEntry *hPtr;
	int idx = 2;
	if (Itcl_GetStackSize(&infoPtr->contextStack) == 1) {
	   idx = 1;







<







348
349
350
351
352
353
354

355
356
357
358
359
360
361


    /*
     *  Create the component record.  Set the protection level
     *  according to the "-protected" or "-private" option.
     */
    ownerClass = contextClass;

    callContextPtr = Itcl_PeekStack(&infoPtr->contextStack);
    ownerNsPtr = callContextPtr->nsPtr;
    if (ownerNsPtr != NULL) {
        Tcl_HashEntry *hPtr;
	int idx = 2;
	if (Itcl_GetStackSize(&infoPtr->contextStack) == 1) {
	   idx = 1;
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
     *  If this variable has some "config" code, invoke it now.
     *
     *  NOTE:  Invoke the "config" code in the class scope
     *    containing the data member.
     */
    mcode = ivPtr->codePtr;
    if (mcode && mcode->bodyPtr) {

        Itcl_SetCallFrameResolver(interp, ivPtr->iclsPtr->resolvePtr);
        Tcl_Namespace *saveNsPtr = Tcl_GetCurrentNamespace(interp);
        Itcl_SetCallFrameNamespace(interp, ivPtr->iclsPtr->nsPtr);
        result = Tcl_EvalObjEx(interp, mcode->bodyPtr, 0);
        Itcl_SetCallFrameNamespace(interp, saveNsPtr);

        if (result == TCL_OK) {
            Tcl_ResetResult(interp);
        } else {







|

|







1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
     *  If this variable has some "config" code, invoke it now.
     *
     *  NOTE:  Invoke the "config" code in the class scope
     *    containing the data member.
     */
    mcode = ivPtr->codePtr;
    if (mcode && mcode->bodyPtr) {
        Tcl_Namespace *saveNsPtr;
        Itcl_SetCallFrameResolver(interp, ivPtr->iclsPtr->resolvePtr);
        saveNsPtr = Tcl_GetCurrentNamespace(interp);
        Itcl_SetCallFrameNamespace(interp, ivPtr->iclsPtr->nsPtr);
        result = Tcl_EvalObjEx(interp, mcode->bodyPtr, 0);
        Itcl_SetCallFrameNamespace(interp, saveNsPtr);

        if (result == TCL_OK) {
            Tcl_ResetResult(interp);
        } else {
Changes to generic/itkArchetype.c.
262
263
264
265
266
267
268

269
270
271
272
273
274
275
    int newEntry;
    int result;
    ArchInfo *info;
    ItclClass *contextClass;
    ItclObject *contextObj;
    Tcl_HashTable *objsWithArchInfo;
    Tcl_HashEntry *entry;


    ItclShowArgs(2, "Itk_ArchInitOptsCmd", objc, objv);
    if (objc != 1) {
        Tcl_WrongNumArgs(interp, 1, objv, "");
        return TCL_ERROR;
    }








>







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
    int newEntry;
    int result;
    ArchInfo *info;
    ItclClass *contextClass;
    ItclObject *contextObj;
    Tcl_HashTable *objsWithArchInfo;
    Tcl_HashEntry *entry;
    Tcl_CmdInfo cmdInfo;

    ItclShowArgs(2, "Itk_ArchInitOptsCmd", objc, objv);
    if (objc != 1) {
        Tcl_WrongNumArgs(interp, 1, objv, "");
        return TCL_ERROR;
    }

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
    /*
     *  Make sure that the access command for this object
     *  resides in the global namespace.  If need be, move
     *  the command.
     */
    result = TCL_OK;

    Tcl_CmdInfo cmdInfo;
    Tcl_GetCommandInfoFromToken(contextObj->accessCmd, &cmdInfo);
    if (cmdInfo.namespacePtr != Tcl_GetGlobalNamespace(interp)) {
        Tcl_Obj *oldNamePtr, *newNamePtr;

        oldNamePtr = Tcl_NewStringObj((char*)NULL, 0);
        Tcl_GetCommandFullName(interp, contextObj->accessCmd, oldNamePtr);
        Tcl_IncrRefCount(oldNamePtr);







<







308
309
310
311
312
313
314

315
316
317
318
319
320
321
    /*
     *  Make sure that the access command for this object
     *  resides in the global namespace.  If need be, move
     *  the command.
     */
    result = TCL_OK;


    Tcl_GetCommandInfoFromToken(contextObj->accessCmd, &cmdInfo);
    if (cmdInfo.namespacePtr != Tcl_GetGlobalNamespace(interp)) {
        Tcl_Obj *oldNamePtr, *newNamePtr;

        oldNamePtr = Tcl_NewStringObj((char*)NULL, 0);
        Tcl_GetCommandFullName(interp, contextObj->accessCmd, oldNamePtr);
        Tcl_IncrRefCount(oldNamePtr);
412
413
414
415
416
417
418



419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
    int objc,                /* number of arguments */
    Tcl_Obj *CONST objv[])   /* argument objects */
{
    char *cmd;
    char *token;
    char c;
    int length;




    ItclShowArgs(2, "Itk_ArchComponentCmd", objc, objv);
    /*
     *  Check arguments and handle the various options...
     */
    Tcl_DString buffer;
    const char *head;
    const char *tail;
    cmd = Tcl_GetString(objv[0]);
    Itcl_ParseNamespPath(cmd, &buffer, &head, &tail);
    Tcl_DStringFree(&buffer);
    if (objc < 2) {
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
            "wrong # args: should be one of...\n",
            "  ", tail, " add ?-protected? ?-private? ?--? name createCmds ?optionCmds?\n",







>
>
>





<
<
<







412
413
414
415
416
417
418
419
420
421
422
423
424
425
426



427
428
429
430
431
432
433
    int objc,                /* number of arguments */
    Tcl_Obj *CONST objv[])   /* argument objects */
{
    char *cmd;
    char *token;
    char c;
    int length;
    Tcl_DString buffer;
    const char *head;
    const char *tail;

    ItclShowArgs(2, "Itk_ArchComponentCmd", objc, objv);
    /*
     *  Check arguments and handle the various options...
     */



    cmd = Tcl_GetString(objv[0]);
    Itcl_ParseNamespPath(cmd, &buffer, &head, &tail);
    Tcl_DStringFree(&buffer);
    if (objc < 2) {
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
            "wrong # args: should be one of...\n",
            "  ", tail, " add ?-protected? ?-private? ?--? name createCmds ?optionCmds?\n",
863
864
865
866
867
868
869

870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
    Tcl_HashSearch place;
    ArchInfo *info;
    ArchComponent *archComp;
    int cmdlinec;
    Tcl_Obj *objPtr;
    Tcl_Obj *cmdlinePtr;
    Tcl_Obj **cmdlinev;


    ItclShowArgs(2, "Itk_ArchCompAccessCmd", objc, objv);
    contextClass = NULL;
    if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
        !contextObj) {

        token = Tcl_GetString(objv[0]);
        Tcl_ResetResult(interp);
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
            "improper usage: should be \"object ",
            token, " ?name option arg arg...?\"",
            (char*)NULL);
        return TCL_ERROR;
    }

    if (Itk_GetArchInfo(interp, contextObj, &info) != TCL_OK) {
        return TCL_ERROR;
    }

    ItclObjectInfo *infoPtr;
    infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
            ITCL_INTERP_DATA, NULL);
    if (Itcl_GetStackSize(&infoPtr->contextStack) == 1) {
        callingNs = Tcl_GetGlobalNamespace(interp);
    } else {
	ItclCallContext *callContextPtr;
	callContextPtr = Itcl_GetStackValue(&infoPtr->contextStack,







>



















<







863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889

890
891
892
893
894
895
896
    Tcl_HashSearch place;
    ArchInfo *info;
    ArchComponent *archComp;
    int cmdlinec;
    Tcl_Obj *objPtr;
    Tcl_Obj *cmdlinePtr;
    Tcl_Obj **cmdlinev;
    ItclObjectInfo *infoPtr;

    ItclShowArgs(2, "Itk_ArchCompAccessCmd", objc, objv);
    contextClass = NULL;
    if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
        !contextObj) {

        token = Tcl_GetString(objv[0]);
        Tcl_ResetResult(interp);
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
            "improper usage: should be \"object ",
            token, " ?name option arg arg...?\"",
            (char*)NULL);
        return TCL_ERROR;
    }

    if (Itk_GetArchInfo(interp, contextObj, &info) != TCL_OK) {
        return TCL_ERROR;
    }


    infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
            ITCL_INTERP_DATA, NULL);
    if (Itcl_GetStackSize(&infoPtr->contextStack) == 1) {
        callingNs = Tcl_GetGlobalNamespace(interp);
    } else {
	ItclCallContext *callContextPtr;
	callContextPtr = Itcl_GetStackValue(&infoPtr->contextStack,
958
959
960
961
962
963
964



965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982

    /*
     *  If only the component name is specified, then return the
     *  window name for this component.
     */
    if (objc == 2) {
	Tcl_Obj *objPtr;



	objPtr = Tcl_NewObj();
	Tcl_GetCommandFullName(interp, archComp->accessCmd, objPtr);
	Tcl_IncrRefCount(objPtr);
	Tcl_DString buffer;
	Tcl_DStringInit(&buffer);
	Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
	Tcl_DStringAppend(&buffer, Tcl_GetString(objPtr), -1);
	Tcl_DecrRefCount(objPtr);
	Tcl_DStringAppend(&buffer, archComp->iclsPtr->nsPtr->fullName, -1);
	Tcl_Namespace *nsPtr;
	Tcl_CallFrame frame;
	nsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL, 0);
	Itcl_PushCallFrame(interp, &frame, nsPtr, /*isProcCallFrame*/0);
        val = Tcl_GetVar2(interp, "itk_component", token, 0);
	Tcl_DStringFree(&buffer);
	Itcl_PopCallFrame(interp);
        if (!val) {
            Tcl_ResetResult(interp);







>
>
>



<





<
<







958
959
960
961
962
963
964
965
966
967
968
969
970

971
972
973
974
975


976
977
978
979
980
981
982

    /*
     *  If only the component name is specified, then return the
     *  window name for this component.
     */
    if (objc == 2) {
	Tcl_Obj *objPtr;
	Tcl_DString buffer;
	Tcl_Namespace *nsPtr;
	Tcl_CallFrame frame;
	objPtr = Tcl_NewObj();
	Tcl_GetCommandFullName(interp, archComp->accessCmd, objPtr);
	Tcl_IncrRefCount(objPtr);

	Tcl_DStringInit(&buffer);
	Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
	Tcl_DStringAppend(&buffer, Tcl_GetString(objPtr), -1);
	Tcl_DecrRefCount(objPtr);
	Tcl_DStringAppend(&buffer, archComp->iclsPtr->nsPtr->fullName, -1);


	nsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL, 0);
	Itcl_PushCallFrame(interp, &frame, nsPtr, /*isProcCallFrame*/0);
        val = Tcl_GetVar2(interp, "itk_component", token, 0);
	Tcl_DStringFree(&buffer);
	Itcl_PopCallFrame(interp);
        if (!val) {
            Tcl_ResetResult(interp);
Changes to generic/itkOption.c.
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236

    /*
     *  If the option has any config code, execute it now.
     *  Make sure that the namespace context is set up correctly.
     */
    mcode = opt->codePtr;
    if (mcode && mcode->bodyPtr) {

//fprintf(stderr, "EXE!%s!\n", Tcl_GetString(mcode->bodyPtr));
        Itcl_SetCallFrameResolver(interp, opt->iclsPtr->resolvePtr);
        Tcl_Namespace *saveNsPtr = Tcl_GetCurrentNamespace(interp);
//fprintf(stderr, "MCNS!%s!\n", saveNsPtr->fullName);
        Itcl_SetCallFrameNamespace(interp, opt->iclsPtr->nsPtr);
        result = Tcl_EvalObjEx(interp, mcode->bodyPtr, 0);
        Itcl_SetCallFrameNamespace(interp, saveNsPtr);
#ifdef NOTDEF
        result = Itcl_EvalMemberCode(interp, (ItclMemberFunc*)NULL,
            opt->member, contextObj, 0, (Tcl_Obj**)NULL);







>


|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

    /*
     *  If the option has any config code, execute it now.
     *  Make sure that the namespace context is set up correctly.
     */
    mcode = opt->codePtr;
    if (mcode && mcode->bodyPtr) {
        Tcl_Namespace *saveNsPtr;
//fprintf(stderr, "EXE!%s!\n", Tcl_GetString(mcode->bodyPtr));
        Itcl_SetCallFrameResolver(interp, opt->iclsPtr->resolvePtr);
        saveNsPtr = Tcl_GetCurrentNamespace(interp);
//fprintf(stderr, "MCNS!%s!\n", saveNsPtr->fullName);
        Itcl_SetCallFrameNamespace(interp, opt->iclsPtr->nsPtr);
        result = Tcl_EvalObjEx(interp, mcode->bodyPtr, 0);
        Itcl_SetCallFrameNamespace(interp, saveNsPtr);
#ifdef NOTDEF
        result = Itcl_EvalMemberCode(interp, (ItclMemberFunc*)NULL,
            opt->member, contextObj, 0, (Tcl_Obj**)NULL);
Changes to win/makefile.vc.
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36

37
38
39
40
41
42
43
44
45

46
47

48
49
50
51
52
53
54
55


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115


116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
MSG = ^
You must run this makefile only from the directory it is in.^
Please `cd` to its location first.
!error $(MSG) 
!endif

PROJECT	= itk

!include "..\..\rules.vc"


!if $(TCLINSTALL)
!message *** Warning: [Incr Tk] requires the source distribution of Tcl to build from,
!message ***    at this time, sorry.  Please set the TCLDIR and TKDIR macros to point
!message ***    to the sources.
!endif

ITCLDIR		= ..\..\itcl


!if [nmakehlp -g $(ITCLDIR)\generic\itcl.h ITCL_VERSION] == 33
ITCL_DOTVERSION	= 3.3
!elseif [nmakehlp -g $(ITCLDIR)\generic\itcl.h ITCL_VERSION] == 34

ITCL_DOTVERSION	= 3.4
!elseif [nmakehlp -g $(ITCLDIR)\generic\itcl.h ITCL_VERSION] == 35

ITCL_DOTVERSION	= 3.5
!elseif [nmakehlp -g $(ITCLDIR)\generic\itcl.h ITCL_VERSION] == 0
MSG =^
Can't get version string from ..\generic\itcl.h
!error $(MSG)
!endif
ITCL_VERSION	= $(ITCL_DOTVERSION:.=)

!if [nmakehlp -g ..\generic\itk.h ITK_VERSION] == 33

ITK_DOTVERSION	= 3.3
!elseif [nmakehlp -g ..\generic\itk.h ITK_VERSION] == 34

ITK_DOTVERSION	= 3.4
!elseif [nmakehlp -g ..\generic\itk.h ITK_VERSION] == 35
ITK_DOTVERSION	= 3.5
!elseif [nmakehlp -g ..\generic\itk.h ITK_VERSION] == 0
MSG =^
Can't get version string from ..\generic\itk.h
!error $(MSG)
!endif


ITK_VERSION	= $(ITK_DOTVERSION:.=)


BINROOT		= .
ROOT		= ..
STUBPREFIX	= $(PROJECT)stub

PKGINDEX	= "$(TMP_DIR)\pkgIndex.tcl"

ITCLLIBNAME	= itcl$(ITCL_VERSION)$(SUFX).$(EXT)
ITCLLIB		= "$(ITCLDIR)\win\$(OUT_DIR)\$(ITCLLIBNAME)"
ITKIMPLIB	= "$(OUT_DIR)\$(PROJECT)$(ITK_VERSION)$(SUFX).lib"
ITKSTUBLIBNAME	= $(STUBPREFIX)$(ITK_VERSION).lib
ITKSTUBLIB	= "$(OUT_DIR)\$(ITKSTUBLIBNAME)"

!if $(TCL_DOES_STUBS)
ITKLIBNAME	= $(PROJECT)$(ITK_VERSION)$(SUFX).$(EXT)
ITCLIMPLIBNAME	= itcl$(ITCL_VERSION)$(SUFX).$(EXT)
!else
ITKLIBNAME	= $(PROJECT)$(ITK_VERSION)80$(SUFX).$(EXT)
ITCLIMPLIBNAME	= itcl$(ITCL_VERSION)80$(SUFX).lib
!endif
ITKLIB		= "$(OUT_DIR)\$(ITKLIBNAME)"
ITCLIMPLIB	= "$(ITCLDIR)\win\Release\$(ITCLIMPLIBNAME)"


!if $(TCLINSTALL)
TKSTUBLIB	= "$(TCLDIR)\lib\tkstub$(TCL_VERSION).lib"
TKIMPLIB	= "$(TCLDIR)\lib\tk$(TCL_VERSION)$(DBGX).lib"
WISH		= "$(TCLDIR)\bin\wish$(TCL_VERSION)$(DBGX).exe"
TCL_LIBRARY	= 
TK_LIBRARY	= 
!else
TKSTUBLIB	= "$(TKDIR)\win\Release\tkstub$(TCL_VERSION).lib"
TKIMPLIB	= "$(TKDIR)\win\$(OUT_DIR)\tk$(TCL_VERSION)$(DBGX).lib"
WISH		= "$(TKDIR)\win\$(OUT_DIR)\wish$(TCL_VERSION)$(DBGX).exe"
TCL_LIBRARY	= "$(TCLDIR)\library"
TK_LIBRARY	= "$(TKDIR)\library"
!endif
ITCL_LIBRARY	= "$(ITCLDIR:\=/)/library"
ITK_LIBRARY	= "$(ROOT)/library

ITCLSTUBLIBNAME	= itclstub$(ITCL_VERSION).lib
ITCLSTUBLIB	= "$(ITCLDIR)\win\Release\$(ITCLSTUBLIBNAME)"

### For Tcl 8.0
!if !$(TCL_DOES_STUBS)
TCLSTUBLIB	= $(TCLIMPLIB)
TKSTUBLIB	= $(TKIMPLIB)
ITCLSTUBLIB	= $(ITCLIMPLIB)
!endif


BIN_INSTALL_DIR		= $(_INSTALLDIR)\bin
DOC_INSTALL_DIR		= $(_INSTALLDIR)\doc
LIB_INSTALL_DIR		= $(_INSTALLDIR)\lib
SCRIPT_INSTALL_DIR	= $(_INSTALLDIR)\lib\itk$(ITK_DOTVERSION)
INCLUDE_INSTALL_DIR	= $(_INSTALLDIR)\include

ITKOBJS = \


	$(TMP_DIR)\itk_archetype.obj \
	$(TMP_DIR)\itk_cmds.obj \

	$(TMP_DIR)\itk_option.obj \
	$(TMP_DIR)\itk_util.obj \
!if !$(STATIC_BUILD)
	$(TMP_DIR)\dllEntryPoint.obj \
	$(TMP_DIR)\itk.res \
!endif
!if $(TCL_DOES_STUBS)
	$(TMP_DIR)\itkStubInit.obj
!endif

ITKSTUBOBJS = \
!if $(TCL_DOES_STUBS)
    $(TMP_DIR)\itkStubLib.obj
!endif

GENERICDIR	= $(ROOT)\generic
DOCDIR		= $(ROOT)\doc
WINDIR		= $(ROOT)\win
RCDIR		= $(ROOT)\win\rc
TOOLSDIR	= ..\..\tools








>
|
|







<
|
|
<
|
|
>
|
|
>
|
|
<
<
<

<
|
|
>
|
|
>
|
|
<
<
<
<
<

>
>
|
|













<


<
<
<
<

|


<
|
|
|
<
<
<
<
<
<


<




|

<
<
<
<
<
<
<
<
|
|
|
|
|


>
>
|
|
>
|
|




<

<


<

<







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31

32
33
34
35
36
37
38
39



40

41
42
43
44
45
46
47
48





49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68




69
70
71
72

73
74
75






76
77

78
79
80
81
82
83








84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102

103
104

105

106
107
108
109
110
111
112
MSG = ^
You must run this makefile only from the directory it is in.^
Please `cd` to its location first.
!error $(MSG) 
!endif

PROJECT	= itk
PROJECT_REQUIRES_TK = 1
ITCLDIR		= ..\..\itcl
!include "$(ITCLDIR)\win\rules.vc"

!if $(TCLINSTALL)
!message *** Warning: [Incr Tk] requires the source distribution of Tcl to build from,
!message ***    at this time, sorry.  Please set the TCLDIR and TKDIR macros to point
!message ***    to the sources.
!endif


!if [echo REM = This file is generated from rules.vc > versions.vc]
!endif

!if [echo ITCL_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(ITCLDIR)\generic\itcl.h ITCL_MAJOR_VERSION >> versions.vc]
!endif
!if [echo ITCL_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(ITCLDIR)\generic\itcl.h ITCL_MINOR_VERSION >> versions.vc]
!endif
!if [echo ITCL_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V $(ITCLDIR)\generic\itcl.h ITCL_PATCH_LEVEL >> versions.vc]



!endif

!if [echo ITK_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V ..\generic\itk.h ITK_MAJOR_VERSION >> versions.vc]
!endif
!if [echo ITK_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V ..\generic\itk.h ITK_MINOR_VERSION >> versions.vc]
!endif
!if [echo ITK_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V ..\generic\itk.h ITK_PATCH_LEVEL >> versions.vc]





!endif
!include "versions.vc"
ITCL_VERSION   = $(ITCL_MAJOR_VERSION)$(ITCL_MINOR_VERSION)
ITK_VERSION    = $(ITK_MAJOR_VERSION)$(ITK_MINOR_VERSION)
DOTVERSION = $(ITK_PATCH_LEVEL)

BINROOT		= .
ROOT		= ..
STUBPREFIX	= $(PROJECT)stub

PKGINDEX	= "$(TMP_DIR)\pkgIndex.tcl"

ITCLLIBNAME	= itcl$(ITCL_VERSION)$(SUFX).$(EXT)
ITCLLIB		= "$(ITCLDIR)\win\$(OUT_DIR)\$(ITCLLIBNAME)"
ITKIMPLIB	= "$(OUT_DIR)\$(PROJECT)$(ITK_VERSION)$(SUFX).lib"
ITKSTUBLIBNAME	= $(STUBPREFIX)$(ITK_VERSION).lib
ITKSTUBLIB	= "$(OUT_DIR)\$(ITKSTUBLIBNAME)"


ITKLIBNAME	= $(PROJECT)$(ITK_VERSION)$(SUFX).$(EXT)
ITCLIMPLIBNAME	= itcl$(ITCL_VERSION)$(SUFX).$(EXT)




ITKLIB		= "$(OUT_DIR)\$(ITKLIBNAME)"
ITCLIMPLIB	= "$(ITCLDIR)\win\$(BUILDDIRTOP)\$(ITCLIMPLIBNAME)"



TKSTUBLIB	= "$(TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib"
TKIMPLIB	= "$(TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(DBGX).lib"
WISH		= "$(TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(DBGX).exe"






TCL_LIBRARY	= "$(TCLDIR)\library"
TK_LIBRARY	= "$(TKDIR)\library"

ITCL_LIBRARY	= "$(ITCLDIR:\=/)/library"
ITK_LIBRARY	= "$(ROOT)/library

ITCLSTUBLIBNAME	= itclstub$(ITCL_VERSION).lib
ITCLSTUBLIB	= "$(ITCLDIR)\win\$(BUILDDIRTOP)\$(ITCLSTUBLIBNAME)"









BIN_INSTALL_DIR		= $(_INSTALLDIR)\..\bin
DOC_INSTALL_DIR		= $(_INSTALLDIR)\..\doc
LIB_INSTALL_DIR		= $(_INSTALLDIR)
SCRIPT_INSTALL_DIR	= $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
INCLUDE_INSTALL_DIR	= $(_INSTALLDIR)\..\include

ITKOBJS = \
	$(TMP_DIR)\itkArchBase.obj \
	$(TMP_DIR)\itkArchetype.obj \
	$(TMP_DIR)\itkBase.obj \
	$(TMP_DIR)\itkCmd.obj \
	$(TMP_DIR)\itkHelpers.obj \
	$(TMP_DIR)\itkOption.obj \
	$(TMP_DIR)\itkUtil.obj \
!if !$(STATIC_BUILD)
	$(TMP_DIR)\dllEntryPoint.obj \
	$(TMP_DIR)\itk.res \
!endif

	$(TMP_DIR)\itkStubInit.obj


ITKSTUBOBJS = \

    $(TMP_DIR)\itkStubLib.obj


GENERICDIR	= $(ROOT)\generic
DOCDIR		= $(ROOT)\doc
WINDIR		= $(ROOT)\win
RCDIR		= $(ROOT)\win\rc
TOOLSDIR	= ..\..\tools

169
170
171
172
173
174
175
176









177
178
179
180
181
182

183
184
185
186






187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

204
205




206



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
ITK_LLIBS	= $(TCLSTUBLIB) $(TKSTUBLIB) $(ITCLSTUBLIB)

!if exist("$(TCLDIR)\win\coffbase.txt")
ITK_DLLBASE	= -base:@$(TCLDIR)\win\coffbase.txt,itk
!else
ITK_DLLBASE	=
!endif










#---------------------------------------------------------------------
# Compile flags
#---------------------------------------------------------------------

!if $(DEBUG)
!if "$(MACHINE)" == "IA64"

cdebug = -Od -Zi
!else
cdebug = -Z7 -Od -WX
!endif






!else
# This cranks the optimization level up to max.
cdebug = -O2
!endif

# declarations common to all compiler options
cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\

!if $(PENT_0F_ERRATA)
cflags = $(cflags) -QI0f
!endif

!if $(ITAN_B_ERRATA)
cflags = $(cflags) -QIA64_Bx
!endif

!if $(MSVCRT)

crt = -MD$(DBGX)
!else




crt = -MT$(DBGX)



!endif

!if $(TCLINSTALL)
TCL_INCLUDES	= -I"$(TCLDIR)\include"
TK_INCLUDES	= 
!else
TCL_INCLUDES	= -I"$(TCLDIR)\generic" -I"$(TCLDIR)\win"
TK_INCLUDES	= -I"$(TKDIR)\generic" -I"$(TKDIR)\xlib"
!endif

ITK_INCLUDES	= -I$(WINDIR) -I$(GENERICDIR)
ITCL_INCLUDES	= -I"$(ITCLDIR)\generic"
ITK_DEFINES	= -DBUILD_itk -DTCL_THREADS=1
ITK_EXE_CFLAGS	= $(cdebug) $(cflags) $(crt) $(ITCL_INCLUDES) $(ITK_INCLUDES) \
		$(TCL_INCLUDES) $(TK_INCLUDES) $(ITK_DEFINES)

### By convention, static builds do not use Stubs.  This is just a practice,
### not a technical limitation.
!if $(STATIC_BUILD)
ITK_CFLAGS	= $(ITK_EXE_CFLAGS) -DSTATIC_BUILD $(OPTDEFINES)
!elseif $(TCL_DOES_STUBS)
ITK_CFLAGS	= $(ITK_EXE_CFLAGS) -DUSE_TCL_STUBS -DUSE_TK_STUBS -DUSE_ITCL_STUBS $(OPTDEFINES)
!else
ITK_CFLAGS	= $(ITK_EXE_CFLAGS) $(OPTDEFINES)
!endif

#---------------------------------------------------------------------
# Project specific targets
#---------------------------------------------------------------------

all :     setup $(ITKLIB) $(ITKSTUBLIB)








>
>
>
>
>
>
>
>
>




|
|
>
|

|

>
>
>
>
>
>

<
|


|
<
|
<
<
<
|
<
<
<


>
|

>
>
>
>
|
>
>
>




















<
<

|







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

178
179
180
181

182



183



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216


217
218
219
220
221
222
223
224
225
ITK_LLIBS	= $(TCLSTUBLIB) $(TKSTUBLIB) $(ITCLSTUBLIB)

!if exist("$(TCLDIR)\win\coffbase.txt")
ITK_DLLBASE	= -base:@$(TCLDIR)\win\coffbase.txt,itk
!else
ITK_DLLBASE	=
!endif

baselibs   = 
# Avoid 'unresolved external symbol __security_cookie' errors.
# c.f. http://support.microsoft.com/?id=894573
!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
!if $(VCVERSION) > 1399 && $(VCVERSION) < 1500
baselibs   = $(baselibs) bufferoverflowU.lib
!endif
!endif

#---------------------------------------------------------------------
# Compile flags
#---------------------------------------------------------------------

!if !$(DEBUG)
!if $(OPTIMIZING)
### This cranks the optimization level to maximize speed
cdebug	= -O2 $(OPTIMIZATIONS)
!else
cdebug	= 
!endif
!if $(SYMBOLS)
cdebug	= $(cdebug) -Zi
!endif
!else if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
### Warnings are too many, can't support warnings into errors.
cdebug	= -Zi -Od $(DEBUGFLAGS)
!else

cdebug	= -Zi -WX $(DEBUGFLAGS)
!endif

### Declarations common to all compiler options

cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE



cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\




!if $(MSVCRT)
!if $(DEBUG) && !$(UNCHECKED)
crt = -MDd
!else
crt = -MD
!endif
!else
!if $(DEBUG) && !$(UNCHECKED)
crt = -MTd
!else
crt = -MT
!endif
!endif

!if $(TCLINSTALL)
TCL_INCLUDES	= -I"$(TCLDIR)\include"
TK_INCLUDES	= 
!else
TCL_INCLUDES	= -I"$(TCLDIR)\generic" -I"$(TCLDIR)\win"
TK_INCLUDES	= -I"$(TKDIR)\generic" -I"$(TKDIR)\xlib"
!endif

ITK_INCLUDES	= -I$(WINDIR) -I$(GENERICDIR)
ITCL_INCLUDES	= -I"$(ITCLDIR)\generic"
ITK_DEFINES	= -DBUILD_itk -DTCL_THREADS=1
ITK_EXE_CFLAGS	= $(cdebug) $(cflags) $(crt) $(ITCL_INCLUDES) $(ITK_INCLUDES) \
		$(TCL_INCLUDES) $(TK_INCLUDES) $(ITK_DEFINES)

### By convention, static builds do not use Stubs.  This is just a practice,
### not a technical limitation.
!if $(STATIC_BUILD)
ITK_CFLAGS	= $(ITK_EXE_CFLAGS) -DSTATIC_BUILD $(OPTDEFINES)


!else
ITK_CFLAGS	= $(ITK_EXE_CFLAGS) -DUSE_TCL_STUBS -DUSE_TK_STUBS -DUSE_ITCL_STUBS $(OPTDEFINES)
!endif

#---------------------------------------------------------------------
# Project specific targets
#---------------------------------------------------------------------

all :     setup $(ITKLIB) $(ITKSTUBLIB)
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
	@if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
	@if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)

$(ITKLIB): $(ITKOBJS)
!if $(STATIC_BUILD)
	$(lib32) -nologo -machine:$(MACHINE) -out:$@ @<<
!else
	$(link32) $(ITK_LFLAGS) $(ITK_DLLBASE) -out:$@ $(ITK_LLIBS) @<<
!endif
		$(ITKOBJS)
<<


!if $(TCL_DOES_STUBS)
$(ITKSTUBLIB) : $(ITKSTUBOBJS)
	$(lib32) -nologo -out:$@ $(ITKSTUBOBJS)
!endif

install-binaries:
	if not exist "$(_INSTALLDIR)" mkdir "$(_INSTALLDIR)"
	if not exist "$(BIN_INSTALL_DIR)" mkdir "$(BIN_INSTALL_DIR)"
	if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
	if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
	if not exist "$(INCLUDE_INSTALL_DIR)" mkdir "$(INCLUDE_INSTALL_DIR)"
	copy $(ITKLIB) "$(SCRIPT_INSTALL_DIR)"
!if $(ITKSTUBLIB) != ""
	copy $(ITKSTUBLIB) "$(LIB_INSTALL_DIR)"
!endif
	copy $(ROOT)\generic\itk.h "$(INCLUDE_INSTALL_DIR)"
	copy $(ROOT)\generic\itkDecls.h "$(INCLUDE_INSTALL_DIR)"
	copy $(ROOT)\library\*.* "$(SCRIPT_INSTALL_DIR)"
	echo if {[package vsatisfies 8.0 [package provide Tcl]]} {\
		> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ set add 80>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo } else {>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ set add {}>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo }>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo if {[info exists ::tcl_platform(debug)] ^&^&\
		$$::tcl_platform(debug)	^&^& \>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ ^ ^ ^ ^ [file exists [file join $$dir\
		$(PROJECT)$(ITK_VERSION)$${add}g.dll]]}\
		{>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ package ifneeded Itk $(ITK_DOTVERSION) [list load\
		[file join $$dir $(PROJECT)$(ITK_VERSION)$${add}g.dll]\
		Itk]>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo } else {>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ package ifneeded Itk $(ITK_DOTVERSION) [list load\
		[file join $$dir $(PROJECT)$(ITK_VERSION)$${add}.dll]\
		Itk]>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo }>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo unset add>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"


#---------------------------------------------------------------------







|





<


<


















|






|



|







245
246
247
248
249
250
251
252
253
254
255
256
257

258
259

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
	@if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
	@if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)

$(ITKLIB): $(ITKOBJS)
!if $(STATIC_BUILD)
	$(lib32) -nologo -machine:$(MACHINE) -out:$@ @<<
!else
	$(link32) $(ITK_LFLAGS) $(ITK_DLLBASE) -out:$@ $(ITK_LLIBS) $(baselibs) @<<
!endif
		$(ITKOBJS)
<<



$(ITKSTUBLIB) : $(ITKSTUBOBJS)
	$(lib32) -nologo -out:$@ $(ITKSTUBOBJS)


install-binaries:
	if not exist "$(_INSTALLDIR)" mkdir "$(_INSTALLDIR)"
	if not exist "$(BIN_INSTALL_DIR)" mkdir "$(BIN_INSTALL_DIR)"
	if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
	if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
	if not exist "$(INCLUDE_INSTALL_DIR)" mkdir "$(INCLUDE_INSTALL_DIR)"
	copy $(ITKLIB) "$(SCRIPT_INSTALL_DIR)"
!if $(ITKSTUBLIB) != ""
	copy $(ITKSTUBLIB) "$(LIB_INSTALL_DIR)"
!endif
	copy $(ROOT)\generic\itk.h "$(INCLUDE_INSTALL_DIR)"
	copy $(ROOT)\generic\itkDecls.h "$(INCLUDE_INSTALL_DIR)"
	copy $(ROOT)\library\*.* "$(SCRIPT_INSTALL_DIR)"
	echo if {[package vsatisfies 8.0 [package provide Tcl]]} {\
		> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ set add 80>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo } else {>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ set add {$(SUFX:g=)}>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo }>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo if {[info exists ::tcl_platform(debug)] ^&^&\
		$$::tcl_platform(debug)	^&^& \>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ ^ ^ ^ ^ [file exists [file join $$dir\
		$(PROJECT)$(ITK_VERSION)$${add}g.dll]]}\
		{>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ package ifneeded Itk $(DOTVERSION) [list load\
		[file join $$dir $(PROJECT)$(ITK_VERSION)$${add}g.dll]\
		Itk]>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo } else {>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo ^ ^ ^ ^ package ifneeded Itk $(DOTVERSION) [list load\
		[file join $$dir $(PROJECT)$(ITK_VERSION)$${add}.dll]\
		Itk]>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo }>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
	echo unset add>> "$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"


#---------------------------------------------------------------------
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
CreateButton(4, "FAQ", ExecFile("http://www.purl.org/NET/Tcl-FAQ/"))
<<
	cd $(MAKEDIR)
	copy "$(DOCTMP_DIR)\$(@B).hlp" "$(OUT_DIR)"
	copy "$(DOCTMP_DIR)\$(@B).cnt" "$(OUT_DIR)"

$(MAN2TCL): $(TCLTOOLSDIR)\$$(@B).c
	$(cc32) -nologo -G4 -ML -O2 -Fo$(@D)\ $(TCLTOOLSDIR)\$(@B).c -link -out:$@

$(HELPRTF): $(MAN2TCL) $(MAN2HELP) $(MAN2HELP2) $(INDEX)
	$(TCLSH) $(MAN2HELP) -bitmap $(BMP_NOPATH) $(PROJECT) $(ITK_VERSION) $(DOCDIR:\=/)

install-docs:
!if exist($(HELPFILE))
	@xcopy /i /y "$(HELPFILE)" "$(DOC_INSTALL_DIR)\"
	@xcopy /i /y "$(HELPCNT)" "$(DOC_INSTALL_DIR)\"
	$(TCLSH) <<
puts "Installing $(PROJECT)'s helpfile contents into Tcl's ..."
set f [open {$(DOC_INSTALL_DIR:\=/)/tcl$(TCL_VERSION).cnt} r]







|



|







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
CreateButton(4, "FAQ", ExecFile("http://www.purl.org/NET/Tcl-FAQ/"))
<<
	cd $(MAKEDIR)
	copy "$(DOCTMP_DIR)\$(@B).hlp" "$(OUT_DIR)"
	copy "$(DOCTMP_DIR)\$(@B).cnt" "$(OUT_DIR)"

$(MAN2TCL): $(TCLTOOLSDIR)\$$(@B).c
	$(cc32) -nologo -G4 -ML -O2 -Fo$(@D)\ $(TCLTOOLSDIR)\$(@B).c $(baselibs) -link -out:$@

$(HELPRTF): $(MAN2TCL) $(MAN2HELP) $(MAN2HELP2) $(INDEX)
	$(TCLSH) $(MAN2HELP) -bitmap $(BMP_NOPATH) $(PROJECT) $(ITK_VERSION) $(DOCDIR:\=/)
	
install-docs:
!if exist($(HELPFILE))
	@xcopy /i /y "$(HELPFILE)" "$(DOC_INSTALL_DIR)\"
	@xcopy /i /y "$(HELPCNT)" "$(DOC_INSTALL_DIR)\"
	$(TCLSH) <<
puts "Installing $(PROJECT)'s helpfile contents into Tcl's ..."
set f [open {$(DOC_INSTALL_DIR:\=/)/tcl$(TCL_VERSION).cnt} r]
Changes to win/nmakehlp.c.

1
2
3
4
5
6

7
8
9
10
11


12




13
14

15
16
17
















18

19
20
21

22

23
24
25

26
27
28
29
30
31
32
33
34
35
36


37
38
39


40
41
42
43
44
45

46


47
48

49


50
51
52
53
54
55
56

57
58
59
60

61
62
63
64
65

66
67
68
69

70
71
72
73
74

75
76
77
78

79
80

81


82
83
84
85
86
87
88
89

90

91

92
93
94










95











96




97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113

/* ----------------------------------------------------------------------------
 * nmakehlp.c --
 *
 *	This is used to fix limitations within nmake and the environment.
 *
 * Copyright (c) 2002 by David Gravereaux.

 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * ----------------------------------------------------------------------------
 */


#include <windows.h>




#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")

#include <stdio.h>
#include <math.h>

















/* protos */

int CheckForCompilerFeature (const char *option);
int CheckForLinkerFeature (const char *option);
int IsIn (const char *string, const char *substring);

int GrepForDefine (const char *file, const char *string);

DWORD WINAPI ReadFromPipe (LPVOID args);

/* globals */

#define CHUNK	25
#define STATICBUFFERSIZE    1000
typedef struct {
    HANDLE pipe;
    char buffer[STATICBUFFERSIZE];
} pipeinfo;

pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};





/* exitcodes: 0 == no, 1 == yes, 2 == error */
int


main (int argc, char *argv[])
{
    char msg[300];
    DWORD dwWritten;
    int chars;


    /* make sure children (cl.exe and link.exe) are kept quiet. */


    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);


    /* Make sure the compiler and linker aren't effected by the outside world. */


    SetEnvironmentVariable("CL", "");
    SetEnvironmentVariable("LINK", "");

    if (argc > 1 && *argv[1] == '-') {
	switch (*(argv[1]+1)) {
	case 'c':
	    if (argc != 3) {

		chars = wsprintf(msg, "usage: %s -c <compiler option>\n"
			"Tests for whether cl.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);

		return 2;
	    }
	    return CheckForCompilerFeature(argv[2]);
	case 'l':
	    if (argc != 3) {

		chars = wsprintf(msg, "usage: %s -l <linker option>\n"
			"Tests for whether link.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);

		return 2;
	    }
	    return CheckForLinkerFeature(argv[2]);
	case 'f':
	    if (argc == 2) {

		chars = wsprintf(msg, "usage: %s -f <string> <substring>\n"
		    "Find a substring within another\n"
		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);

		return 2;
	    } else if (argc == 3) {

		/* if the string is blank, there is no match */


		return 0;
	    } else {
		return IsIn(argv[2], argv[3]);
	    }
	case 'g':
	    if (argc == 2) {
		chars = wsprintf(msg, "usage: %s -g <file> <string>\n"
		    "grep for a #define\n"

		    "exitcodes: integer of the found string (no decimals)\n", argv[0]);

		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);

		return 2;
	    }
	    return GrepForDefine(argv[2], argv[3]);










	}











    }




    chars = wsprintf(msg, "usage: %s -c|-l|-f ...\n"
	    "This is a little helper app to equalize shell differences between WinNT and\n"
	    "Win9x and get nmake.exe to accomplish its job.\n",
	    argv[0]);
    WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
    return 2;
}

int
CheckForCompilerFeature (const char *option)

{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
>
|





>

|
|


>
>

>
>
>
>


>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
|
|
>
|
>
|


>









|
|
>
>

<

>
>
|





>
|
>
>


>
|
>
>







>
|


|
>





>
|


|
>





>
|
|
|
|
>


>
|
>
>




|

|
|
>
|
>
|
>


|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|






|
|
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
 * ----------------------------------------------------------------------------
 * nmakehlp.c --
 *
 *	This is used to fix limitations within nmake and the environment.
 *
 * Copyright (c) 2002 by David Gravereaux.
 * Copyright (c) 2006 by Pat Thoyts
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * ----------------------------------------------------------------------------
 */

#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#define NO_SHLWAPI_GDI
#define NO_SHLWAPI_STREAM
#define NO_SHLWAPI_REG
#include <shlwapi.h>
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
#pragma comment (lib, "shlwapi.lib")
#include <stdio.h>
#include <math.h>

/*
 * This library is required for x64 builds with _some_ versions of MSVC
 */
#if defined(_M_IA64) || defined(_M_AMD64)
#if _MSC_VER >= 1400 && _MSC_VER < 1500
#pragma comment(lib, "bufferoverflowU")
#endif
#endif

/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
#define   snprintf	_snprintf
#endif



/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char *option);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);

/* globals */

#define CHUNK	25
#define STATICBUFFERSIZE    1000
typedef struct {
    HANDLE pipe;
    char buffer[STATICBUFFERSIZE];
} pipeinfo;

pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */


int
main(
    int argc,
    char *argv[])
{
    char msg[300];
    DWORD dwWritten;
    int chars;

    /*
     * Make sure children (cl.exe and link.exe) are kept quiet.
     */

    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);

    /*
     * Make sure the compiler and linker aren't effected by the outside world.
     */

    SetEnvironmentVariable("CL", "");
    SetEnvironmentVariable("LINK", "");

    if (argc > 1 && *argv[1] == '-') {
	switch (*(argv[1]+1)) {
	case 'c':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		        "usage: %s -c <compiler option>\n"
			"Tests for whether cl.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForCompilerFeature(argv[2]);
	case 'l':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
	       		"usage: %s -l <linker option>\n"
			"Tests for whether link.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForLinkerFeature(argv[2]);
	case 'f':
	    if (argc == 2) {
		chars = snprintf(msg, sizeof(msg) - 1,
			"usage: %s -f <string> <substring>\n"
			"Find a substring within another\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    } else if (argc == 3) {
		/*
		 * If the string is blank, there is no match.
		 */

		return 0;
	    } else {
		return IsIn(argv[2], argv[3]);
	    }
	case 's':
	    if (argc == 2) {
		chars = snprintf(msg, sizeof(msg) - 1,
			"usage: %s -s <substitutions file> <file>\n"
			"Perform a set of string map type substutitions on a file\n"
			"exitcodes: 0\n",
			argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return SubstituteFile(argv[2], argv[3]);
	case 'V':
	    if (argc != 4) {
		chars = snprintf(msg, sizeof(msg) - 1,
		    "usage: %s -V filename matchstring\n"
		    "Extract a version from a file:\n"
		    "eg: pkgIndex.tcl \"package ifneeded http\"",
		    argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 0;
	    }
	    printf("%s\n", GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0'));
	    return 0;
	case 'Q':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		    "usage: %s -Q path\n"
		    "Emit the fully qualified path\n"
		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 2;
	    }
	    return QualifyPath(argv[2]);
	}
    }
    chars = snprintf(msg, sizeof(msg) - 1,
	    "usage: %s -c|-f|-l|-Q|-s|-V ...\n"
	    "This is a little helper app to equalize shell differences between WinNT and\n"
	    "Win9x and get nmake.exe to accomplish its job.\n",
	    argv[0]);
    WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
    return 2;
}

static int
CheckForCompilerFeature(
    const char *option)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
123
124
125
126
127
128
129

130


131
132

133


134
135
136

137


138
139
140
141

142


143


144


145


146


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171

172


173
174
175
176
177
178

179


180
181
182

183


184
185
186

187


188
189
190
191

192



193





194
195
196
197

198
199
200
201
202
203
204
    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = FALSE;


    /* create a non-inheritible pipe. */


    CreatePipe(&Out.pipe, &h, &sa, 0);


    /* dupe the write side, make it inheritible, and close the original. */


    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 
	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);


    /* Same as above, but for the error side. */


    CreatePipe(&Err.pipe, &h, &sa, 0);
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);


    /* base command line */


    strcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");


    /* append our option for testing */


    strcat(cmdline, option);


    /* filename to compile, which exists, but is nothing and empty. */


    strcat(cmdline, " .\\nul");

    ok = CreateProcess(
	    NULL,	    /* Module name. */
	    cmdline,	    /* Command line. */
	    NULL,	    /* Process handle not inheritable. */
	    NULL,	    /* Thread handle not inheritable. */
	    TRUE,	    /* yes, inherit handles. */
	    DETACHED_PROCESS, /* No console for you. */
	    NULL,	    /* Use parent's environment block. */
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    if (!ok) {
	DWORD err = GetLastError();

	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
	return 2;
    }


    /* close our references to the write handles that have now been inherited. */


    CloseHandle(si.hStdOutput);
    CloseHandle(si.hStdError);

    WaitForInputIdle(pi.hProcess, 5000);
    CloseHandle(pi.hThread);


    /* start the pipe reader threads. */


    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);


    /* block waiting for the process to end. */


    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);


    /* wait for our pipe to get done reading, should it be a little slow. */


    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
    CloseHandle(pipeThreads[0]);
    CloseHandle(pipeThreads[1]);


    /* look for the commandline warning code in both streams. */



    return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL);





}

int
CheckForLinkerFeature (const char *option)

{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;







>
|
>
>


>
|
>
>
|
|

>
|
>
>

|
|

>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|















>
|

|
|

|



>
|
>
>






>
|
>
>



>
|
>
>



>
|
>
>




>
|
>
>
>
|
>
>
>
>
>

|
|
|
>







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = FALSE;

    /*
     * Create a non-inheritible pipe.
     */

    CreatePipe(&Out.pipe, &h, &sa, 0);

    /*
     * Dupe the write side, make it inheritible, and close the original.
     */

    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Same as above, but for the error side.
     */

    CreatePipe(&Err.pipe, &h, &sa, 0);
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Base command line.
     */

    lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch ");

    /*
     * Append our option for testing
     */

    lstrcat(cmdline, option);

    /*
     * Filename to compile, which exists, but is nothing and empty.
     */

    lstrcat(cmdline, " .\\nul");

    ok = CreateProcess(
	    NULL,	    /* Module name. */
	    cmdline,	    /* Command line. */
	    NULL,	    /* Process handle not inheritable. */
	    NULL,	    /* Thread handle not inheritable. */
	    TRUE,	    /* yes, inherit handles. */
	    DETACHED_PROCESS, /* No console for you. */
	    NULL,	    /* Use parent's environment block. */
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
     */

    CloseHandle(si.hStdOutput);
    CloseHandle(si.hStdError);

    WaitForInputIdle(pi.hProcess, 5000);
    CloseHandle(pi.hThread);

    /*
     * Start the pipe reader threads.
     */

    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);

    /*
     * Block waiting for the process to end.
     */

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);

    /*
     * Wait for our pipe to get done reading, should it be a little slow.
     */

    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
    CloseHandle(pipeThreads[0]);
    CloseHandle(pipeThreads[1]);

    /*
     * Look for the commandline warning code in both streams.
     *  - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
     */

    return !(strstr(Out.buffer, "D4002") != NULL
             || strstr(Err.buffer, "D4002") != NULL
             || strstr(Out.buffer, "D9002") != NULL
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}

static int
CheckForLinkerFeature(
    const char *option)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
214
215
216
217
218
219
220

221


222
223

224


225
226
227

228


229
230
231
232

233


234


235


236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260

261


262
263
264
265
266
267

268


269
270
271

272


273
274
275

276


277
278
279
280

281


282



283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309


310
311
312
313
314
315
316



317
318










319



320
321


322





323




324


325
326
327
328



329
330






331

332
333


























































334
335




336




337
338
339
340
341



342















343

344
345


346
347


348
349
350

351



352















353






354
355
356


































    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;


    /* create a non-inheritible pipe. */


    CreatePipe(&Out.pipe, &h, &sa, 0);


    /* dupe the write side, make it inheritible, and close the original. */


    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 
	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);


    /* Same as above, but for the error side. */


    CreatePipe(&Err.pipe, &h, &sa, 0);
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);


    /* base command line */


    strcpy(cmdline, "link.exe -nologo ");


    /* append our option for testing */


    strcat(cmdline, option);

    ok = CreateProcess(
	    NULL,	    /* Module name. */
	    cmdline,	    /* Command line. */
	    NULL,	    /* Process handle not inheritable. */
	    NULL,	    /* Thread handle not inheritable. */
	    TRUE,	    /* yes, inherit handles. */
	    DETACHED_PROCESS, /* No console for you. */
	    NULL,	    /* Use parent's environment block. */
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    if (!ok) {
	DWORD err = GetLastError();

	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
	return 2;
    }


    /* close our references to the write handles that have now been inherited. */


    CloseHandle(si.hStdOutput);
    CloseHandle(si.hStdError);

    WaitForInputIdle(pi.hProcess, 5000);
    CloseHandle(pi.hThread);


    /* start the pipe reader threads. */


    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);


    /* block waiting for the process to end. */


    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);


    /* wait for our pipe to get done reading, should it be a little slow. */


    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
    CloseHandle(pipeThreads[0]);
    CloseHandle(pipeThreads[1]);


    /* look for the commandline warning code in the stderr stream. */


    return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL);



}

DWORD WINAPI
ReadFromPipe (LPVOID args)

{
    pipeinfo *pi = (pipeinfo *) args;
    char *lastBuf = pi->buffer;
    DWORD dwRead;
    BOOL ok;

again:
    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
	CloseHandle(pi->pipe);
	return -1;
    }
    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
    if (!ok || dwRead == 0) {
	CloseHandle(pi->pipe);
	return 0;
    }
    lastBuf += dwRead;
    goto again;

    return 0;  /* makes the compiler happy */
}

int


IsIn (const char *string, const char *substring)
{
    return (strstr(string, substring) != NULL);
}

/*
 *  Find a specified #define by name.



 *
 *  If the line is '#define TCL_VERSION "8.5"', it returns










 *  85 as the result.



 */



int





GrepForDefine (const char *file, const char *string)




{


    FILE *f;
    char s1[51], s2[51], s3[51];
    int r = 0;
    double d1;




    f = fopen(file, "rt");






    if (f == NULL) {

	return 0;
    }



























































    do {




	r = fscanf(f, "%50s", s1);




	if (r == 1 && !strcmp(s1, "#define")) {
	    /* get next two words */
	    r = fscanf(f, "%50s %50s", s2, s3);
	    if (r != 2) continue;
	    /* is the first word what we're looking for? */



	    if (!strcmp(s2, string)) {















		fclose(f);

		/* add 1 past first double quote char. "8.5" */
		d1 = atof(s3 + 1);		  /*    8.5  */


		while (floor(d1) != d1) {
		    d1 *= 10.0;


		}
		return ((int) d1);		  /*    85   */
	    }

	}



    } while (!feof(f));






















    fclose(f);
    return 0;
}









































>
|
>
>


>
|
>
>
|
|

>
|
>
>

|
|

>
|
>
>
|
>
>
|
>
>
|















>
|

|
|

|



>
|
>
>






>
|
>
>



>
|
>
>



>
|
>
>




>
|
>
>
|
>
>
>

|
|
|
>






|


|











|
|
>
>
|



|

|
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|

>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
|
|
|
<
>
>
>
|
|
>
>
>
>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
|
>
>
>
>
|
<
|
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>
|
|
>
>
|
<
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    /*
     * Create a non-inheritible pipe.
     */

    CreatePipe(&Out.pipe, &h, &sa, 0);

    /*
     * Dupe the write side, make it inheritible, and close the original.
     */

    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Same as above, but for the error side.
     */

    CreatePipe(&Err.pipe, &h, &sa, 0);
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Base command line.
     */

    lstrcpy(cmdline, "link.exe -nologo ");

    /*
     * Append our option for testing.
     */

    lstrcat(cmdline, option);

    ok = CreateProcess(
	    NULL,	    /* Module name. */
	    cmdline,	    /* Command line. */
	    NULL,	    /* Process handle not inheritable. */
	    NULL,	    /* Thread handle not inheritable. */
	    TRUE,	    /* yes, inherit handles. */
	    DETACHED_PROCESS, /* No console for you. */
	    NULL,	    /* Use parent's environment block. */
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
     */

    CloseHandle(si.hStdOutput);
    CloseHandle(si.hStdError);

    WaitForInputIdle(pi.hProcess, 5000);
    CloseHandle(pi.hThread);

    /*
     * Start the pipe reader threads.
     */

    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);

    /*
     * Block waiting for the process to end.
     */

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);

    /*
     * Wait for our pipe to get done reading, should it be a little slow.
     */

    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
    CloseHandle(pipeThreads[0]);
    CloseHandle(pipeThreads[1]);

    /*
     * Look for the commandline warning code in the stderr stream.
     */

    return !(strstr(Out.buffer, "LNK1117") != NULL ||
	    strstr(Err.buffer, "LNK1117") != NULL ||
	    strstr(Out.buffer, "LNK4044") != NULL ||
	    strstr(Err.buffer, "LNK4044") != NULL);
}

static DWORD WINAPI
ReadFromPipe(
    LPVOID args)
{
    pipeinfo *pi = (pipeinfo *) args;
    char *lastBuf = pi->buffer;
    DWORD dwRead;
    BOOL ok;

  again:
    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
	CloseHandle(pi->pipe);
	return (DWORD)-1;
    }
    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
    if (!ok || dwRead == 0) {
	CloseHandle(pi->pipe);
	return 0;
    }
    lastBuf += dwRead;
    goto again;

    return 0;  /* makes the compiler happy */
}

static int
IsIn(
    const char *string,
    const char *substring)
{
    return (strstr(string, substring) != NULL);
}

/*
 * GetVersionFromFile --
 * 	Looks for a match string in a file and then returns the version
 * 	following the match where a version is anything acceptable to
 * 	package provide or package ifneeded.
 */

static const char *
GetVersionFromFile(
    const char *filename,
    const char *match,
    int numdots)
{
    size_t cbBuffer = 100;
    static char szBuffer[100];
    char *szResult = NULL;
    FILE *fp = fopen(filename, "rt");

    if (fp != NULL) {
	/*
	 * Read data until we see our match string.
	 */

	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
	    LPSTR p, q;

	    p = strstr(szBuffer, match);
	    if (p != NULL) {
		/*
		 * Skip to first digit after the match.
		 */

		p += strlen(match);
		while (*p && !isdigit(*p)) {
		    ++p;
		}

		/*
		 * Find ending whitespace.
		 */

		q = p;

		while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q)
			    && (!strchr("ab", q[-1])) || --numdots))) {
		    ++q;
		}

		memcpy(szBuffer, p, q - p);
		szBuffer[q-p] = 0;
		szResult = szBuffer;
		break;
	    }
	}
	fclose(fp);
    }
    return szResult;
}

/*
 * List helpers for the SubstituteFile function
 */

typedef struct list_item_t {
    struct list_item_t *nextPtr;
    char * key;
    char * value;
} list_item_t;

/* insert a list item into the list (list may be null) */
static list_item_t *
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
{
    list_item_t *itemPtr = malloc(sizeof(list_item_t));
    if (itemPtr) {
	itemPtr->key = strdup(key);
	itemPtr->value = strdup(value);
	itemPtr->nextPtr = NULL;

	while(*listPtrPtr) {
	    listPtrPtr = &(*listPtrPtr)->nextPtr;
	}
	*listPtrPtr = itemPtr;
    }
    return itemPtr;
}

static void
list_free(list_item_t **listPtrPtr)
{
    list_item_t *tmpPtr, *listPtr = *listPtrPtr;
    while (listPtr) {
	tmpPtr = listPtr;
	listPtr = listPtr->nextPtr;
	free(tmpPtr->key);
	free(tmpPtr->value);
	free(tmpPtr);
    }
}

/*
 * SubstituteFile --
 *	As windows doesn't provide anything useful like sed and it's unreliable
 *	to use the tclsh you are building against (consider x-platform builds -
 *	eg compiling AMD64 target from IX86) we provide a simple substitution
 *	option here to handle autoconf style substitutions.
 *	The substitution file is whitespace and line delimited. The file should
 *	consist of lines matching the regular expression:
 *	  \s*\S+\s+\S*$
 *
 *	Usage is something like:
 *	  nmakehlp -S << $** > $@
 *        @PACKAGE_NAME@ $(PACKAGE_NAME)
 *        @PACKAGE_VERSION@ $(PACKAGE_VERSION)
 *        <<
 */

static int
SubstituteFile(
    const char *substitutions,
    const char *filename)
{
    size_t cbBuffer = 1024;
    static char szBuffer[1024], szCopy[1024];
    char *szResult = NULL;
    list_item_t *substPtr = NULL;
    FILE *fp, *sp;


    fp = fopen(filename, "rt");
    if (fp != NULL) {

	/*
	 * Build a list of substutitions from the first filename
	 */

	sp = fopen(substitutions, "rt");
	if (sp != NULL) {
	    while (fgets(szBuffer, cbBuffer, sp) != NULL) {
		char *ks, *ke, *vs, *ve;
		ks = szBuffer;
		while (ks && *ks && isspace(*ks)) ++ks;
		ke = ks;
		while (ke && *ke && !isspace(*ke)) ++ke;
		vs = ke;
		while (vs && *vs && isspace(*vs)) ++vs;
		ve = vs;
		while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
		*ke = 0, *ve = 0;
		list_insert(&substPtr, ks, vs);
	    }
	    fclose(sp);
	}

	/* debug: dump the list */
#ifdef _DEBUG
	{
	    int n = 0;
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
		fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
	    }

	}
#endif

	/*
	 * Run the substitutions over each line of the input
	 */

	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr) {
		char *m = strstr(szBuffer, p->key);
		if (m) {
		    char *cp, *op, *sp;
		    cp = szCopy;
		    op = szBuffer;
		    while (op != m) *cp++ = *op++;
		    sp = p->value;
		    while (sp && *sp) *cp++ = *sp++;
		    op += strlen(p->key);
		    while (*op) *cp++ = *op++;
		    *cp = 0;
		    memcpy(szBuffer, szCopy, sizeof(szCopy));
		}
	    }
	    printf(szBuffer);
	}

	list_free(&substPtr);
    }
    fclose(fp);
    return 0;
}

/*
 * QualifyPath --
 *
 *	This composes the current working directory with a provided path
 *	and returns the fully qualified and normalized path.
 *	Mostly needed to setup paths for testing.
 */

static int
QualifyPath(
    const char *szPath)
{
    char szCwd[MAX_PATH + 1];
    char szTmp[MAX_PATH + 1];
    char *p;
    GetCurrentDirectory(MAX_PATH, szCwd);
    while ((p = strchr(szPath, '/')) && *p)
	*p = '\\';
    PathCombine(szTmp, szCwd, szPath);
    PathCanonicalize(szCwd, szTmp);
    printf("%s\n", szCwd);
    return 0;
}

/*
 * Local variables:
 *   mode: c
 *   c-basic-offset: 4
 *   fill-column: 78
 *   indent-tabs-mode: t
 *   tab-width: 8
 * End:
 */