head	1.12;
access;
symbols
	core-8-5-9:1.11
	core-8-5-8:1.11
	macosx-cocoa-merge:1.12
	macosx-cocoa-premerge:1.12
	macosx-carbon-freeze:1.12
	core-8-5-7:1.11
	core-8-5-6:1.11
	core-8-6-b1:1.12
	core-8-6-a3:1.11
	core-8-5-5:1.11
	core-8-6-a2:1.11
	core-8-5-4:1.11
	core-8-5-3:1.11
	core-8-6-a1:1.11
	core-8-4-19:1.1.6.5
	core-8-5-branch:1.11.0.2
	core-8-5-2:1.11
	core-8-4-18:1.1.6.5
	core-8-5-1:1.11
	core-8-4-17:1.1.6.5
	core-8-5-0:1.11
	core-8-5-b3:1.9
	core-8-5-b2:1.9
	core-8-4-16:1.1.6.5
	core-8-5-b1:1.8
	core-stablilizer-merge:1.8
	core-stabilizer-branch:1.8.0.2
	core-stabilizer-merge:1.11
	core-8-4-15:1.1.6.5
	core-8-5-a6:1.7
	core-8-5-a5:1.6
	core-8-4-14:1.1.6.5
	core-8-5-a4:1.5
	core-8-4-13:1.1.6.1
	core-8-4-12:1.1.6.1
	core-8-4-11:1.1.6.1
	core-8-5-a3:1.5
	core-8-4-10:1.1.6.1
	core-8-4-9-branch:1.1.6.1.0.2
	core-8-5-a2:1.5
	core-8-4-9:1.1.6.1
	core-8-4-8:1.1.6.1
	core-8-4-7:1.1
	core-8-5-a1:1.5
	core-8-4-6:1.1
	core-8-4-5:1.1
	mistachkin-dev-branch:1.1.0.8
	core-8-4-4:1.1
	core-8-4-3:1.1
	core-8-4-branch:1.1.0.6
	core-8-4-2:1.1
	core-8-4-1:1.1
	core-8-4-0:1.1
	macosx-8-4-merge-2002-08-31-trunk:1.1
	macosx-8-4-premerge-2002-08-31-branch:1.1.4.2
	macosx-8-4-premerge-2002-08-31-trunk:1.1
	macosx-8-4-merge-2002-08-30-branch:1.1.4.2
	macosx-8-4-merge-2002-08-30-trunk:1.1
	macosx-8-4-merge-2002-08-20-branch:1.1.4.2
	macosx-8-4-merge-2002-08-20-trunk:1.1
	core-8-4-b2:1.1
	core-8-4-b1:1.1
	macosx-8-4-branch:1.1.0.4
	core-8-4-win-speedup:1.1.0.2;
locks; strict;
comment	@ * @;


1.12
date	2008.11.08.18.44.40;	author dkf;	state Exp;
branches;
next	1.11;

1.11
date	2007.12.14.02.19.43;	author patthoyts;	state Exp;
branches;
next	1.10;

1.10
date	2007.12.13.15.28.52;	author dgp;	state Exp;
branches;
next	1.9;

1.9
date	2007.10.12.14.14.54;	author patthoyts;	state Exp;
branches;
next	1.8;

1.8
date	2007.05.04.18.20.45;	author patthoyts;	state Exp;
branches
	1.8.2.1;
next	1.7;

1.7
date	2007.02.09.06.54.33;	author mistachkin;	state Exp;
branches;
next	1.6;

1.6
date	2006.10.19.00.48.25;	author patthoyts;	state Exp;
branches;
next	1.5;

1.5
date	2004.02.01.10.40.07;	author davygrvy;	state Exp;
branches;
next	1.4;

1.4
date	2003.12.23.04.01.02;	author davygrvy;	state Exp;
branches;
next	1.3;

1.3
date	2003.12.23.03.52.45;	author davygrvy;	state Exp;
branches;
next	1.2;

1.2
date	2003.12.23.02.48.29;	author davygrvy;	state Exp;
branches;
next	1.1;

1.1
date	2002.03.28.23.23.03;	author davygrvy;	state Exp;
branches
	1.1.2.1
	1.1.4.1
	1.1.6.1;
next	;

1.1.2.1
date	2002.04.02.21.17.03;	author hobbs;	state Exp;
branches;
next	;

1.1.4.1
date	2002.06.10.05.08.00;	author wolfsuit;	state Exp;
branches;
next	1.1.4.2;

1.1.4.2
date	2002.06.10.05.38.27;	author wolfsuit;	state Exp;
branches;
next	;

1.1.6.1
date	2004.10.27.00.36.34;	author davygrvy;	state Exp;
branches;
next	1.1.6.2;

1.1.6.2
date	2006.06.14.23.52.01;	author patthoyts;	state Exp;
branches;
next	1.1.6.3;

1.1.6.3
date	2006.09.26.23.55.50;	author patthoyts;	state Exp;
branches;
next	1.1.6.4;

1.1.6.4
date	2006.10.06.18.10.41;	author patthoyts;	state Exp;
branches;
next	1.1.6.5;

1.1.6.5
date	2006.10.18.08.56.21;	author patthoyts;	state Exp;
branches;
next	;

1.8.2.1
date	2007.10.15.18.38.41;	author dgp;	state Exp;
branches;
next	1.8.2.2;

1.8.2.2
date	2008.01.23.16.39.14;	author dgp;	state Exp;
branches;
next	;


desc
@@


1.12
log
@Lots of small changes to make code more pretty and C89-like.
@
text
@/*
 * ----------------------------------------------------------------------------
 * 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.
 *
 * ----------------------------------------------------------------------------
 * RCS: @@(#) $Id: nmakehlp.c,v 1.11 2007/12/14 02:19:43 patthoyts Exp $
 * ----------------------------------------------------------------------------
 */

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

/*
 * This library is required for x64 builds with _some_ versions
 */
#if defined(_M_IA64) || defined(_M_AMD64)
#if _MSC_FULL_VER > 140000000 && _MSC_FULL_VER <= 140040310
#pragma comment(lib, "bufferoverflowU")
#endif
#endif

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



/* 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);
int		SubstituteFile(const char *substs, const char *filename);
const char *    GetVersionFromFile(const char *filename, const char *match);
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 'g':
	    if (argc == 2) {
		chars = snprintf(msg, sizeof(msg) - 1,
			"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]);
	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]));
	    return 0;
	}
    }
    chars = snprintf(msg, sizeof(msg) - 1,
	    "usage: %s -c|-l|-f|-g|-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;
}

int
CheckForCompilerFeature(
    const char *option)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];
    char cmdline[100];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

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

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

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

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

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

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

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

    /*
     * Base command line.
     */

    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);
}

int
CheckForLinkerFeature(
    const char *option)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];
    char cmdline[100];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

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

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

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

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

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

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

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

    /*
     * Base command line.
     */

    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);
}

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 */
}

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)
{
    char s1[51], s2[51], s3[51];
    FILE *f = fopen(file, "rt");

    if (f == NULL) {
	return 0;
    }

    do {
	int 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)) {
		double d1;

		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;
}

/*
 * 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.
 */

const char *
GetVersionFromFile(
    const char *filename,
    const char *match)
{
    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.
		 */

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

		/*
		 * Find ending whitespace.
		 */

		q = p;
		while (*q && (isalnum(*q) || *q == '.')) {
		    ++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)
 *        <<
 */

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;
}

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


1.11
log
@Support compilation with MSVC9 on AMD64
@
text
@d14 1
a14 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.20 2007/12/13 15:28:43 dgp Exp $
d595 4
a598 1
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
d615 2
a616 1
list_free(list_item_t **listPtrPtr)
@


1.10
log
@merge stable branch onto HEAD
@
text
@d14 1
a14 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.8.2.1 2007/10/15 18:38:41 dgp Exp $
d24 4
d29 1
d32 1
@


1.9
log
@Mine all version information from headers.  Sync tcl and tk and bring
extension versions closer together. Try and avoid using tclsh to do
substitutions as we may cross compile.
@
text
@d14 1
a14 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.18 2007/09/12 14:23:08 patthoyts Exp $
@


1.8
log
@Sync with tcl version
@
text
@d14 1
a14 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.17 2007/05/04 18:04:18 patthoyts Exp $
d41 1
d137 12
d302 3
a304 1
             || strstr(Err.buffer, "D9002") != NULL);
d576 135
@


1.8.2.1
log
@merge updates from HEAD
@
text
@d14 1
a14 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.8 2007/05/04 18:20:45 patthoyts Exp $
a40 1
int		SubstituteFile(const char *substs, const char *filename);
a135 12
	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]);
d289 1
a289 3
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
a560 135

/*
 * 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)
 *        <<
 */

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;
}
@


1.8.2.2
log
@merge updates from HEAD
@
text
@d14 1
a14 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.20 2007/12/13 15:28:43 dgp Exp $
a23 4

/*
 * This library is required for x64 builds with _some_ versions
 */
a24 1
#if _MSC_FULL_VER > 140000000 && _MSC_FULL_VER <= 140040310
a26 1
#endif
@


1.7
log
@Windows build fixes
@
text
@d8 1
d10 2
a11 2
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
d14 1
a14 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.6 2006/10/19 00:48:25 patthoyts Exp $
d41 1
d136 13
d245 1
a245 1
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
d371 1
a371 1
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
d412 3
a414 3
             strstr(Err.buffer, "LNK1117") != NULL ||
             strstr(Out.buffer, "LNK4044") != NULL ||
             strstr(Err.buffer, "LNK4044") != NULL);
a460 1
    FILE *f;
d462 1
a462 2
    int r = 0;
    double d1;
a463 1
    f = fopen(file, "rt");
d469 2
a470 1
	r = fscanf(f, "%50s", s1);
d486 2
d506 65
@


1.6
log
@generic/tkImgBmap.c: Fixed line endings.
win/makefile.vc:  Patched up build system to manage
win/rules.vc:     AMD64 with MSVC8
win/nmakehlp.c:   Ensure operation without Platform SDK.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.12 2006/10/12 07:18:32 davygrvy Exp $
d137 1
a137 1
	    "usage: %s -c|-l|-f ...\n"
d196 1
a196 1
    lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");
@


1.5
log
@sync'd to Tcl.
@
text
@d1 2
a2 1
/* ----------------------------------------------------------------------------
d13 1
a13 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.6 2004/02/01 10:28:18 davygrvy Exp $
d16 2
d22 11
d35 6
a40 5
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);
d43 1
d53 4
a57 3


/* exitcodes: 0 == no, 1 == yes, 2 == error */
d59 3
a61 1
main (int argc, char *argv[])
d67 4
a70 1
    /* make sure children (cl.exe and link.exe) are kept quiet. */
d73 4
a76 1
    /* Make sure the compiler and linker aren't effected by the outside world. */
d84 2
a85 1
		chars = wsprintf(msg, "usage: %s -c <compiler option>\n"
d88 2
a89 1
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
d95 2
a96 1
		chars = wsprintf(msg, "usage: %s -l <linker option>\n"
d99 2
a100 1
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
d106 6
a111 4
		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);
d114 4
a117 1
		/* if the string is blank, there is no match */
d124 7
a130 4
		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);
d136 2
a137 1
    chars = wsprintf(msg, "usage: %s -c|-l|-f ...\n"
d144 1
a144 1

d146 2
a147 1
CheckForCompilerFeature (const char *option)
d171 4
a174 1
    /* create a non-inheritible pipe. */
d177 10
a186 3
    /* 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);
a187 1
    /* Same as above, but for the error side. */
d189 18
a206 2
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
d208 1
a208 6
    /* 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");
d224 2
a225 1
	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
d227 2
a228 2
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
d230 1
a230 1
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
d234 4
a237 1
    /* close our references to the write handles that have now been inherited. */
d244 4
a247 1
    /* start the pipe reader threads. */
d251 4
a254 1
    /* block waiting for the process to end. */
d258 4
a261 1
    /* wait for our pipe to get done reading, should it be a little slow. */
d266 9
a274 2
    /* look for the commandline warning code in both streams. */
    return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL);
d276 1
a276 1

d278 2
a279 1
CheckForLinkerFeature (const char *option)
d303 4
a306 1
    /* create a non-inheritible pipe. */
d309 10
a318 3
    /* 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);
a319 1
    /* Same as above, but for the error side. */
d321 2
a322 2
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 
	    0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
d324 11
a334 4
    /* base command line */
    strcpy(cmdline, "link.exe -nologo ");
    /* append our option for testing */
    strcat(cmdline, option);
d350 2
a351 1
	int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
d353 2
a354 2
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
d356 1
a356 1
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
d360 4
a363 1
    /* close our references to the write handles that have now been inherited. */
d370 4
a373 1
    /* start the pipe reader threads. */
d377 4
a380 1
    /* block waiting for the process to end. */
d384 4
a387 1
    /* wait for our pipe to get done reading, should it be a little slow. */
d392 8
a399 2
    /* look for the commandline warning code in the stderr stream. */
    return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL);
d401 1
a401 1

d403 2
a404 1
ReadFromPipe (LPVOID args)
d411 1
a411 1
again:
d414 1
a414 1
	return -1;
d426 1
a426 1

d428 3
a430 1
IsIn (const char *string, const char *substring)
d434 1
a434 1

d436 1
a436 1
 *  Find a specified #define by name.
d438 1
a438 2
 *  If the line is '#define TCL_VERSION "8.5"', it returns
 *  85 as the result.
d442 3
a444 1
GrepForDefine (const char *file, const char *string)
d459 4
a462 1
	    /* get next two words */
d464 8
a471 2
	    if (r != 2) continue;
	    /* is the first word what we're looking for? */
d474 5
a478 1
		/* add 1 past first double quote char. "8.5" */
d480 4
a483 1
		return ((int) (d1 * 10) & 0xFF);  /*    85   */
@


1.4
log
@prevent static buffer overflow (Doh!)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.4 2003/12/23 03:58:58 davygrvy Exp $
d28 2
d32 1
a32 1
    char buffer[1000];
d48 7
d145 1
a145 1
    strcpy(cmdline, "cl.exe -nologo -c -TC -Fdtemp ");
d149 1
a149 1
    strcat(cmdline, " nul");
a188 4
    /* clean up temporary files before returning */
    DeleteFile("temp.idb");
    DeleteFile("temp.pdb");

a238 2
    /* filename to compile, which exists, but is nothing and empty. */
//    strcat(cmdline, " nul");
d296 5
a300 1
    ok = ReadFile(pi->pipe, lastBuf, 25, &dwRead, 0L);
d346 3
a348 3
		/* add 1 past double quote char.     "8.5" */
		d1 = atof(s3 + 1);		  /*  8.5  */
		return ((int) (d1 * 10) & 0xFF);  /*  85   */
@


1.3
log
@fixed static buffer overflow
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.3 2003/12/23 03:48:01 davygrvy Exp $
d321 1
a321 1
    char s1[250], s2[50], s3[50];
d331 1
a331 1
	r = fscanf(f, "%s", s1);
d334 1
a334 1
	    r = fscanf(f, "%s %s", s2, s3);
@


1.2
log
@sync'd to Tcl.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.2 2003/12/23 02:19:13 davygrvy Exp $
d321 1
a321 1
    char s1[50], s2[50], s3[50];
@


1.1
log
@	* win/.cvsignore (new):
	* win/lamp.bmp (new):
	* win/makefile.vc:
	* win/nmakehlp.c (new):
	* win/rules.vc:  Brought the makefile up-to-date with Tcl's one.
	This now has support for Win9x issues and the winhelp target now
	exists.  Color scheme can be changed.  I'm just imparting a first
	suggestion using orange :)  I'll have to think about the install
	portion of the helpfile as I'll need to do some tricks to insert
	tk's contents file into Tcl's using some special winhlp32.exe
	switches.  [Bug 533862 527941]
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.1 2002/03/27 21:15:43 davygrvy Exp $
d18 1
d24 1
d79 9
d308 40
@


1.1.6.1
log
@* win/makefile.vc:  Backport to the most recent
* win/rules.vc:     changes on the HEAD.
* win/nmakehlp.c:
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.5 2004/02/01 10:40:07 davygrvy Exp $
a17 1
#include <stdio.h>
a22 1
int GrepForDefine (const char *file, const char *string);
a25 2
#define CHUNK	25
#define STATICBUFFERSIZE    1000
d28 1
a28 1
    char buffer[STATICBUFFERSIZE];
a43 7
    /* 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", "");

a76 9
	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]);
d125 1
a125 1
    strcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");
d129 1
a129 1
    strcat(cmdline, " .\\nul");
d169 4
d223 2
d282 1
a282 5
    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
	CloseHandle(pi->pipe);
	return -1;
    }
    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
a297 40

/*
 *  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  */
		return ((int) (d1 * 10) & 0xFF);  /*    85   */
	    }
	}
    } while (!feof(f));

    fclose(f);
    return 0;
}
@


1.1.6.2
log
@Sync with tcl to enable building with VC8 (VS2005 C compiler)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.1.4.1 2006/06/14 15:21:15 patthoyts Exp $
a14 2

#define _CRT_SECURE_NO_DEPRECATE
d18 1
d24 1
d28 2
d32 1
a32 1
    char buffer[1000];
d48 1
a48 4
    /*
     * Make sure children (cl.exe and link.exe) are kept quiet.
     */

d51 1
a51 4
    /*
     * Make sure the compiler and linker aren't affected by the outside world.
     */

d88 9
d113 1
a113 1
    DWORD threadID, n;
d117 1
a117 1
    char cmdline[256];
d145 1
a145 6
    n = GetEnvironmentVariable("CC", cmdline, 255);
    cmdline[n] = 0;
    if (n == 0)
	strcpy(cmdline, "cl.exe");
    strncat(cmdline, " -nologo -c -TC -Zs -X ", 255);

a188 4
    /* clean up temporary files before returning */
    DeleteFile("temp.idb");
    DeleteFile("temp.pdb");

d194 2
a195 22
#ifdef _DEBUG
    {
	DWORD err = 0;
	strcat(cmdline, "\n");
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), cmdline, 
	    strlen(cmdline), &err, NULL);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), Out.buffer, 
	    strlen(Out.buffer), &err,NULL);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), Err.buffer,
	    strlen(Err.buffer), &err,NULL);
    }
#endif

    /*
     * 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);
a238 2
    /* filename to compile, which exists, but is nothing and empty. */
//    strcat(cmdline, " nul");
d296 5
a300 1
    ok = ReadFile(pi->pipe, lastBuf, 25, &dwRead, 0L);
d316 40
@


1.1.6.3
log
@	* win/makefile.vc:  Support MSVC8 and AMD64 target. Also try using
	* win/rules.vc:     sed to generate the manifest (cross-compile cannot
	* win/nmakehlp.c:   execute tclsh). If no sed, use the tclsh exe.
@
text
@d1 1
a1 2
/*
 * ----------------------------------------------------------------------------
d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.1.4.2 2006/09/26 21:40:37 patthoyts Exp $
a17 1
#include <shlwapi.h>
a19 7
#pragma comment (lib, "shlwapi.lib")
#include <stdio.h>
#include <math.h>
#if defined(_M_IA64) || defined(_M_AMD64)
#pragma comment(lib, "bufferoverflowU")
#endif

d22 4
a25 6

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);
a27 3

#define CHUNK	25
#define STATICBUFFERSIZE    1000
d30 1
a30 1
    char buffer[STATICBUFFERSIZE];
a34 4

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */
d36 3
d40 1
a40 3
main(
    int argc,
    char *argv[])
d53 1
a53 1
     * Make sure the compiler and linker aren't effected by the outside world.
d63 1
a63 2
		chars = wnsprintf(msg, sizeof(msg)-1,
		        "usage: %s -c <compiler option>\n"
d66 1
a66 2
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
d72 1
a72 2
		chars = wnsprintf(msg, sizeof(msg) - 1,
	       		"usage: %s -l <linker option>\n"
d75 1
a75 2
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
d81 4
a84 6
		chars = wnsprintf(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);
d87 1
a87 4
		/*
		 * If the string is blank, there is no match.
		 */

a91 12
	case 'g':
	    if (argc == 2) {
		chars = wnsprintf(msg, sizeof(msg) - 1,
			"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]);
d94 1
a94 2
    chars = wnsprintf(msg, sizeof(msg) - 1,
	    "usage: %s -c|-l|-f ...\n"
d101 1
a101 1

d103 1
a103 2
CheckForCompilerFeature(
    const char *option)
d108 1
a108 1
    DWORD threadID;
d112 1
a112 1
    char cmdline[100];
d127 1
a127 4
    /*
     * Create a non-inheritible pipe.
     */

d130 3
a132 10
    /*
     * 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.
     */
d134 1
d136 2
a137 2
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
d139 11
a149 17
    /*
     * Base command line.
     */

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

    /*
     * Append our option for testing
     */

    lstrcat(cmdline, option);

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

    lstrcat(cmdline, " .\\nul");
d165 1
a165 2
	int chars = wsprintf(msg,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
d167 2
a168 2
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
d170 1
a170 1
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
d174 1
a174 4
    /*
     * Close our references to the write handles that have now been inherited.
     */

d181 1
a181 4
    /*
     * Start the pipe reader threads.
     */

d185 1
a185 4
    /*
     * Block waiting for the process to end.
     */

d189 3
a191 3
    /*
     * Wait for our pipe to get done reading, should it be a little slow.
     */
d193 1
d198 13
d215 1
a215 1

d221 1
a221 1

d223 1
a223 2
CheckForLinkerFeature(
    const char *option)
d247 1
a247 4
    /*
     * Create a non-inheritible pipe.
     */

d250 3
a252 10
    /*
     * 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.
     */
d254 1
d256 2
a257 6
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Base command line.
     */
d259 6
a264 7
    lstrcpy(cmdline, "link.exe -nologo ");

    /*
     * Append our option for testing.
     */

    lstrcat(cmdline, option);
d280 1
a280 2
	int chars = wnsprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
d282 2
a283 2
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
d285 1
a285 1
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
d289 1
a289 4
    /*
     * Close our references to the write handles that have now been inherited.
     */

d296 1
a296 4
    /*
     * Start the pipe reader threads.
     */

d300 1
a300 4
    /*
     * Block waiting for the process to end.
     */

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

d309 3
a311 3
    /*
     * Look for the commandline warning code in the stderr stream.
     */
a312 6
    return !(strstr(Out.buffer, "LNK1117") != NULL ||
             strstr(Err.buffer, "LNK1117") != NULL ||
             strstr(Out.buffer, "LNK4044") != NULL ||
             strstr(Err.buffer, "LNK4044") != NULL);
}

d314 1
a314 2
ReadFromPipe(
    LPVOID args)
d321 2
a322 6
  again:
    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
	CloseHandle(pi->pipe);
	return -1;
    }
    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
d332 1
a332 1

d334 1
a334 3
IsIn(
    const char *string,
    const char *substring)
a337 57

/*
 * 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;
}
@


1.1.6.4
log
@Remove the /RTCc flag
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.1.4.3 2006/10/06 14:04:49 patthoyts Exp $
d410 1
a410 1
	return (DWORD)-1;
@


1.1.6.5
log
@Ensure builds with VC6 without Platform SDK and pickup MACHINE from environment
to make life easier on Windows non-x86 platforms.
@
text
@d19 1
d22 1
a28 6
/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
#define   snprintf	_snprintf
#endif


d80 1
a80 1
		chars = snprintf(msg, sizeof(msg) - 1,
d91 1
a91 1
		chars = snprintf(msg, sizeof(msg) - 1,
d102 1
a102 1
		chars = snprintf(msg, sizeof(msg) - 1,
d120 1
a120 1
		chars = snprintf(msg, sizeof(msg) - 1,
d132 1
a132 1
    chars = snprintf(msg, sizeof(msg) - 1,
d220 1
a220 1
	int chars = snprintf(msg, sizeof(msg) - 1,
d346 1
a346 1
	int chars = snprintf(msg, sizeof(msg) - 1,
@


1.1.4.1
log
@Adding missing files from TOT merge.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id$
@


1.1.4.2
log
@Merging with TOT as of 06/09/2002.
@
text
@@


1.1.2.1
log
@sync with head
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: nmakehlp.c,v 1.1 2002/03/28 23:23:03 davygrvy Exp $
@

