os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/win/nmakehlp.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/win/nmakehlp.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,490 @@
1.4 +/*
1.5 + * ----------------------------------------------------------------------------
1.6 + * nmakehlp.c --
1.7 + *
1.8 + * This is used to fix limitations within nmake and the environment.
1.9 + *
1.10 + * Copyright (c) 2002 by David Gravereaux.
1.11 + *
1.12 + * See the file "license.terms" for information on usage and redistribution
1.13 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
1.14 + *
1.15 + * ----------------------------------------------------------------------------
1.16 + * RCS: @(#) $Id: nmakehlp.c,v 1.1.4.4 2006/10/18 08:49:33 patthoyts Exp $
1.17 + * ----------------------------------------------------------------------------
1.18 + */
1.19 +
1.20 +#define _CRT_SECURE_NO_DEPRECATE
1.21 +#include <windows.h>
1.22 +#pragma comment (lib, "user32.lib")
1.23 +#pragma comment (lib, "kernel32.lib")
1.24 +#include <stdio.h>
1.25 +#include <math.h>
1.26 +#if defined(_M_IA64) || defined(_M_AMD64)
1.27 +#pragma comment(lib, "bufferoverflowU")
1.28 +#endif
1.29 +
1.30 +/* ISO hack for dumb VC++ */
1.31 +#ifdef _MSC_VER
1.32 +#define snprintf _snprintf
1.33 +#endif
1.34 +
1.35 +
1.36 +
1.37 +/* protos */
1.38 +
1.39 +int CheckForCompilerFeature(const char *option);
1.40 +int CheckForLinkerFeature(const char *option);
1.41 +int IsIn(const char *string, const char *substring);
1.42 +int GrepForDefine(const char *file, const char *string);
1.43 +DWORD WINAPI ReadFromPipe(LPVOID args);
1.44 +
1.45 +/* globals */
1.46 +
1.47 +#define CHUNK 25
1.48 +#define STATICBUFFERSIZE 1000
1.49 +typedef struct {
1.50 + HANDLE pipe;
1.51 + char buffer[STATICBUFFERSIZE];
1.52 +} pipeinfo;
1.53 +
1.54 +pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
1.55 +pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
1.56 +
1.57 +/*
1.58 + * exitcodes: 0 == no, 1 == yes, 2 == error
1.59 + */
1.60 +
1.61 +int
1.62 +main(
1.63 + int argc,
1.64 + char *argv[])
1.65 +{
1.66 + char msg[300];
1.67 + DWORD dwWritten;
1.68 + int chars;
1.69 +
1.70 + /*
1.71 + * Make sure children (cl.exe and link.exe) are kept quiet.
1.72 + */
1.73 +
1.74 + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1.75 +
1.76 + /*
1.77 + * Make sure the compiler and linker aren't effected by the outside world.
1.78 + */
1.79 +
1.80 + SetEnvironmentVariable("CL", "");
1.81 + SetEnvironmentVariable("LINK", "");
1.82 +
1.83 + if (argc > 1 && *argv[1] == '-') {
1.84 + switch (*(argv[1]+1)) {
1.85 + case 'c':
1.86 + if (argc != 3) {
1.87 + chars = snprintf(msg, sizeof(msg) - 1,
1.88 + "usage: %s -c <compiler option>\n"
1.89 + "Tests for whether cl.exe supports an option\n"
1.90 + "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
1.91 + WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
1.92 + &dwWritten, NULL);
1.93 + return 2;
1.94 + }
1.95 + return CheckForCompilerFeature(argv[2]);
1.96 + case 'l':
1.97 + if (argc != 3) {
1.98 + chars = snprintf(msg, sizeof(msg) - 1,
1.99 + "usage: %s -l <linker option>\n"
1.100 + "Tests for whether link.exe supports an option\n"
1.101 + "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
1.102 + WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
1.103 + &dwWritten, NULL);
1.104 + return 2;
1.105 + }
1.106 + return CheckForLinkerFeature(argv[2]);
1.107 + case 'f':
1.108 + if (argc == 2) {
1.109 + chars = snprintf(msg, sizeof(msg) - 1,
1.110 + "usage: %s -f <string> <substring>\n"
1.111 + "Find a substring within another\n"
1.112 + "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
1.113 + WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
1.114 + &dwWritten, NULL);
1.115 + return 2;
1.116 + } else if (argc == 3) {
1.117 + /*
1.118 + * If the string is blank, there is no match.
1.119 + */
1.120 +
1.121 + return 0;
1.122 + } else {
1.123 + return IsIn(argv[2], argv[3]);
1.124 + }
1.125 + case 'g':
1.126 + if (argc == 2) {
1.127 + chars = snprintf(msg, sizeof(msg) - 1,
1.128 + "usage: %s -g <file> <string>\n"
1.129 + "grep for a #define\n"
1.130 + "exitcodes: integer of the found string (no decimals)\n",
1.131 + argv[0]);
1.132 + WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
1.133 + &dwWritten, NULL);
1.134 + return 2;
1.135 + }
1.136 + return GrepForDefine(argv[2], argv[3]);
1.137 + }
1.138 + }
1.139 + chars = snprintf(msg, sizeof(msg) - 1,
1.140 + "usage: %s -c|-l|-f ...\n"
1.141 + "This is a little helper app to equalize shell differences between WinNT and\n"
1.142 + "Win9x and get nmake.exe to accomplish its job.\n",
1.143 + argv[0]);
1.144 + WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
1.145 + return 2;
1.146 +}
1.147 +
1.148 +int
1.149 +CheckForCompilerFeature(
1.150 + const char *option)
1.151 +{
1.152 + STARTUPINFO si;
1.153 + PROCESS_INFORMATION pi;
1.154 + SECURITY_ATTRIBUTES sa;
1.155 + DWORD threadID;
1.156 + char msg[300];
1.157 + BOOL ok;
1.158 + HANDLE hProcess, h, pipeThreads[2];
1.159 + char cmdline[100];
1.160 +
1.161 + hProcess = GetCurrentProcess();
1.162 +
1.163 + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
1.164 + ZeroMemory(&si, sizeof(STARTUPINFO));
1.165 + si.cb = sizeof(STARTUPINFO);
1.166 + si.dwFlags = STARTF_USESTDHANDLES;
1.167 + si.hStdInput = INVALID_HANDLE_VALUE;
1.168 +
1.169 + ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
1.170 + sa.nLength = sizeof(SECURITY_ATTRIBUTES);
1.171 + sa.lpSecurityDescriptor = NULL;
1.172 + sa.bInheritHandle = FALSE;
1.173 +
1.174 + /*
1.175 + * Create a non-inheritible pipe.
1.176 + */
1.177 +
1.178 + CreatePipe(&Out.pipe, &h, &sa, 0);
1.179 +
1.180 + /*
1.181 + * Dupe the write side, make it inheritible, and close the original.
1.182 + */
1.183 +
1.184 + DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
1.185 + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
1.186 +
1.187 + /*
1.188 + * Same as above, but for the error side.
1.189 + */
1.190 +
1.191 + CreatePipe(&Err.pipe, &h, &sa, 0);
1.192 + DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
1.193 + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
1.194 +
1.195 + /*
1.196 + * Base command line.
1.197 + */
1.198 +
1.199 + lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");
1.200 +
1.201 + /*
1.202 + * Append our option for testing
1.203 + */
1.204 +
1.205 + lstrcat(cmdline, option);
1.206 +
1.207 + /*
1.208 + * Filename to compile, which exists, but is nothing and empty.
1.209 + */
1.210 +
1.211 + lstrcat(cmdline, " .\\nul");
1.212 +
1.213 + ok = CreateProcess(
1.214 + NULL, /* Module name. */
1.215 + cmdline, /* Command line. */
1.216 + NULL, /* Process handle not inheritable. */
1.217 + NULL, /* Thread handle not inheritable. */
1.218 + TRUE, /* yes, inherit handles. */
1.219 + DETACHED_PROCESS, /* No console for you. */
1.220 + NULL, /* Use parent's environment block. */
1.221 + NULL, /* Use parent's starting directory. */
1.222 + &si, /* Pointer to STARTUPINFO structure. */
1.223 + &pi); /* Pointer to PROCESS_INFORMATION structure. */
1.224 +
1.225 + if (!ok) {
1.226 + DWORD err = GetLastError();
1.227 + int chars = snprintf(msg, sizeof(msg) - 1,
1.228 + "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
1.229 +
1.230 + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
1.231 + FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
1.232 + (300-chars), 0);
1.233 + WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
1.234 + return 2;
1.235 + }
1.236 +
1.237 + /*
1.238 + * Close our references to the write handles that have now been inherited.
1.239 + */
1.240 +
1.241 + CloseHandle(si.hStdOutput);
1.242 + CloseHandle(si.hStdError);
1.243 +
1.244 + WaitForInputIdle(pi.hProcess, 5000);
1.245 + CloseHandle(pi.hThread);
1.246 +
1.247 + /*
1.248 + * Start the pipe reader threads.
1.249 + */
1.250 +
1.251 + pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
1.252 + pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
1.253 +
1.254 + /*
1.255 + * Block waiting for the process to end.
1.256 + */
1.257 +
1.258 + WaitForSingleObject(pi.hProcess, INFINITE);
1.259 + CloseHandle(pi.hProcess);
1.260 +
1.261 + /*
1.262 + * Wait for our pipe to get done reading, should it be a little slow.
1.263 + */
1.264 +
1.265 + WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
1.266 + CloseHandle(pipeThreads[0]);
1.267 + CloseHandle(pipeThreads[1]);
1.268 +
1.269 + /*
1.270 + * Look for the commandline warning code in both streams.
1.271 + * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
1.272 + */
1.273 +
1.274 + return !(strstr(Out.buffer, "D4002") != NULL
1.275 + || strstr(Err.buffer, "D4002") != NULL
1.276 + || strstr(Out.buffer, "D9002") != NULL
1.277 + || strstr(Err.buffer, "D9002") != NULL);
1.278 +}
1.279 +
1.280 +int
1.281 +CheckForLinkerFeature(
1.282 + const char *option)
1.283 +{
1.284 + STARTUPINFO si;
1.285 + PROCESS_INFORMATION pi;
1.286 + SECURITY_ATTRIBUTES sa;
1.287 + DWORD threadID;
1.288 + char msg[300];
1.289 + BOOL ok;
1.290 + HANDLE hProcess, h, pipeThreads[2];
1.291 + char cmdline[100];
1.292 +
1.293 + hProcess = GetCurrentProcess();
1.294 +
1.295 + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
1.296 + ZeroMemory(&si, sizeof(STARTUPINFO));
1.297 + si.cb = sizeof(STARTUPINFO);
1.298 + si.dwFlags = STARTF_USESTDHANDLES;
1.299 + si.hStdInput = INVALID_HANDLE_VALUE;
1.300 +
1.301 + ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
1.302 + sa.nLength = sizeof(SECURITY_ATTRIBUTES);
1.303 + sa.lpSecurityDescriptor = NULL;
1.304 + sa.bInheritHandle = TRUE;
1.305 +
1.306 + /*
1.307 + * Create a non-inheritible pipe.
1.308 + */
1.309 +
1.310 + CreatePipe(&Out.pipe, &h, &sa, 0);
1.311 +
1.312 + /*
1.313 + * Dupe the write side, make it inheritible, and close the original.
1.314 + */
1.315 +
1.316 + DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
1.317 + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
1.318 +
1.319 + /*
1.320 + * Same as above, but for the error side.
1.321 + */
1.322 +
1.323 + CreatePipe(&Err.pipe, &h, &sa, 0);
1.324 + DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
1.325 + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
1.326 +
1.327 + /*
1.328 + * Base command line.
1.329 + */
1.330 +
1.331 + lstrcpy(cmdline, "link.exe -nologo ");
1.332 +
1.333 + /*
1.334 + * Append our option for testing.
1.335 + */
1.336 +
1.337 + lstrcat(cmdline, option);
1.338 +
1.339 + ok = CreateProcess(
1.340 + NULL, /* Module name. */
1.341 + cmdline, /* Command line. */
1.342 + NULL, /* Process handle not inheritable. */
1.343 + NULL, /* Thread handle not inheritable. */
1.344 + TRUE, /* yes, inherit handles. */
1.345 + DETACHED_PROCESS, /* No console for you. */
1.346 + NULL, /* Use parent's environment block. */
1.347 + NULL, /* Use parent's starting directory. */
1.348 + &si, /* Pointer to STARTUPINFO structure. */
1.349 + &pi); /* Pointer to PROCESS_INFORMATION structure. */
1.350 +
1.351 + if (!ok) {
1.352 + DWORD err = GetLastError();
1.353 + int chars = snprintf(msg, sizeof(msg) - 1,
1.354 + "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
1.355 +
1.356 + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
1.357 + FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
1.358 + (300-chars), 0);
1.359 + WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
1.360 + return 2;
1.361 + }
1.362 +
1.363 + /*
1.364 + * Close our references to the write handles that have now been inherited.
1.365 + */
1.366 +
1.367 + CloseHandle(si.hStdOutput);
1.368 + CloseHandle(si.hStdError);
1.369 +
1.370 + WaitForInputIdle(pi.hProcess, 5000);
1.371 + CloseHandle(pi.hThread);
1.372 +
1.373 + /*
1.374 + * Start the pipe reader threads.
1.375 + */
1.376 +
1.377 + pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
1.378 + pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
1.379 +
1.380 + /*
1.381 + * Block waiting for the process to end.
1.382 + */
1.383 +
1.384 + WaitForSingleObject(pi.hProcess, INFINITE);
1.385 + CloseHandle(pi.hProcess);
1.386 +
1.387 + /*
1.388 + * Wait for our pipe to get done reading, should it be a little slow.
1.389 + */
1.390 +
1.391 + WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
1.392 + CloseHandle(pipeThreads[0]);
1.393 + CloseHandle(pipeThreads[1]);
1.394 +
1.395 + /*
1.396 + * Look for the commandline warning code in the stderr stream.
1.397 + */
1.398 +
1.399 + return !(strstr(Out.buffer, "LNK1117") != NULL ||
1.400 + strstr(Err.buffer, "LNK1117") != NULL ||
1.401 + strstr(Out.buffer, "LNK4044") != NULL ||
1.402 + strstr(Err.buffer, "LNK4044") != NULL);
1.403 +}
1.404 +
1.405 +DWORD WINAPI
1.406 +ReadFromPipe(
1.407 + LPVOID args)
1.408 +{
1.409 + pipeinfo *pi = (pipeinfo *) args;
1.410 + char *lastBuf = pi->buffer;
1.411 + DWORD dwRead;
1.412 + BOOL ok;
1.413 +
1.414 + again:
1.415 + if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
1.416 + CloseHandle(pi->pipe);
1.417 + return (DWORD)-1;
1.418 + }
1.419 + ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
1.420 + if (!ok || dwRead == 0) {
1.421 + CloseHandle(pi->pipe);
1.422 + return 0;
1.423 + }
1.424 + lastBuf += dwRead;
1.425 + goto again;
1.426 +
1.427 + return 0; /* makes the compiler happy */
1.428 +}
1.429 +
1.430 +int
1.431 +IsIn(
1.432 + const char *string,
1.433 + const char *substring)
1.434 +{
1.435 + return (strstr(string, substring) != NULL);
1.436 +}
1.437 +
1.438 +/*
1.439 + * Find a specified #define by name.
1.440 + *
1.441 + * If the line is '#define TCL_VERSION "8.5"', it returns 85 as the result.
1.442 + */
1.443 +
1.444 +int
1.445 +GrepForDefine(
1.446 + const char *file,
1.447 + const char *string)
1.448 +{
1.449 + FILE *f;
1.450 + char s1[51], s2[51], s3[51];
1.451 + int r = 0;
1.452 + double d1;
1.453 +
1.454 + f = fopen(file, "rt");
1.455 + if (f == NULL) {
1.456 + return 0;
1.457 + }
1.458 +
1.459 + do {
1.460 + r = fscanf(f, "%50s", s1);
1.461 + if (r == 1 && !strcmp(s1, "#define")) {
1.462 + /*
1.463 + * Get next two words.
1.464 + */
1.465 +
1.466 + r = fscanf(f, "%50s %50s", s2, s3);
1.467 + if (r != 2) {
1.468 + continue;
1.469 + }
1.470 +
1.471 + /*
1.472 + * Is the first word what we're looking for?
1.473 + */
1.474 +
1.475 + if (!strcmp(s2, string)) {
1.476 + fclose(f);
1.477 +
1.478 + /*
1.479 + * Add 1 past first double quote char. "8.5"
1.480 + */
1.481 +
1.482 + d1 = atof(s3 + 1); /* 8.5 */
1.483 + while (floor(d1) != d1) {
1.484 + d1 *= 10.0;
1.485 + }
1.486 + return ((int) d1); /* 85 */
1.487 + }
1.488 + }
1.489 + } while (!feof(f));
1.490 +
1.491 + fclose(f);
1.492 + return 0;
1.493 +}