os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/win/nmakehlp.c
Update contrib.
2 * ----------------------------------------------------------------------------
5 * This is used to fix limitations within nmake and the environment.
7 * Copyright (c) 2002 by David Gravereaux.
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 * ----------------------------------------------------------------------------
13 * RCS: @(#) $Id: nmakehlp.c,v 1.1.4.4 2006/10/18 08:49:33 patthoyts Exp $
14 * ----------------------------------------------------------------------------
17 #define _CRT_SECURE_NO_DEPRECATE
19 #pragma comment (lib, "user32.lib")
20 #pragma comment (lib, "kernel32.lib")
23 #if defined(_M_IA64) || defined(_M_AMD64)
24 #pragma comment(lib, "bufferoverflowU")
27 /* ISO hack for dumb VC++ */
29 #define snprintf _snprintf
36 int CheckForCompilerFeature(const char *option);
37 int CheckForLinkerFeature(const char *option);
38 int IsIn(const char *string, const char *substring);
39 int GrepForDefine(const char *file, const char *string);
40 DWORD WINAPI ReadFromPipe(LPVOID args);
45 #define STATICBUFFERSIZE 1000
48 char buffer[STATICBUFFERSIZE];
51 pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
52 pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
55 * exitcodes: 0 == no, 1 == yes, 2 == error
68 * Make sure children (cl.exe and link.exe) are kept quiet.
71 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
74 * Make sure the compiler and linker aren't effected by the outside world.
77 SetEnvironmentVariable("CL", "");
78 SetEnvironmentVariable("LINK", "");
80 if (argc > 1 && *argv[1] == '-') {
81 switch (*(argv[1]+1)) {
84 chars = snprintf(msg, sizeof(msg) - 1,
85 "usage: %s -c <compiler option>\n"
86 "Tests for whether cl.exe supports an option\n"
87 "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
88 WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
92 return CheckForCompilerFeature(argv[2]);
95 chars = snprintf(msg, sizeof(msg) - 1,
96 "usage: %s -l <linker option>\n"
97 "Tests for whether link.exe supports an option\n"
98 "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
99 WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
103 return CheckForLinkerFeature(argv[2]);
106 chars = snprintf(msg, sizeof(msg) - 1,
107 "usage: %s -f <string> <substring>\n"
108 "Find a substring within another\n"
109 "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
110 WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
113 } else if (argc == 3) {
115 * If the string is blank, there is no match.
120 return IsIn(argv[2], argv[3]);
124 chars = snprintf(msg, sizeof(msg) - 1,
125 "usage: %s -g <file> <string>\n"
126 "grep for a #define\n"
127 "exitcodes: integer of the found string (no decimals)\n",
129 WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
133 return GrepForDefine(argv[2], argv[3]);
136 chars = snprintf(msg, sizeof(msg) - 1,
137 "usage: %s -c|-l|-f ...\n"
138 "This is a little helper app to equalize shell differences between WinNT and\n"
139 "Win9x and get nmake.exe to accomplish its job.\n",
141 WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
146 CheckForCompilerFeature(
150 PROCESS_INFORMATION pi;
151 SECURITY_ATTRIBUTES sa;
155 HANDLE hProcess, h, pipeThreads[2];
158 hProcess = GetCurrentProcess();
160 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
161 ZeroMemory(&si, sizeof(STARTUPINFO));
162 si.cb = sizeof(STARTUPINFO);
163 si.dwFlags = STARTF_USESTDHANDLES;
164 si.hStdInput = INVALID_HANDLE_VALUE;
166 ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
167 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
168 sa.lpSecurityDescriptor = NULL;
169 sa.bInheritHandle = FALSE;
172 * Create a non-inheritible pipe.
175 CreatePipe(&Out.pipe, &h, &sa, 0);
178 * Dupe the write side, make it inheritible, and close the original.
181 DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
182 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
185 * Same as above, but for the error side.
188 CreatePipe(&Err.pipe, &h, &sa, 0);
189 DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
190 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
196 lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");
199 * Append our option for testing
202 lstrcat(cmdline, option);
205 * Filename to compile, which exists, but is nothing and empty.
208 lstrcat(cmdline, " .\\nul");
211 NULL, /* Module name. */
212 cmdline, /* Command line. */
213 NULL, /* Process handle not inheritable. */
214 NULL, /* Thread handle not inheritable. */
215 TRUE, /* yes, inherit handles. */
216 DETACHED_PROCESS, /* No console for you. */
217 NULL, /* Use parent's environment block. */
218 NULL, /* Use parent's starting directory. */
219 &si, /* Pointer to STARTUPINFO structure. */
220 &pi); /* Pointer to PROCESS_INFORMATION structure. */
223 DWORD err = GetLastError();
224 int chars = snprintf(msg, sizeof(msg) - 1,
225 "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
227 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
228 FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
230 WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
235 * Close our references to the write handles that have now been inherited.
238 CloseHandle(si.hStdOutput);
239 CloseHandle(si.hStdError);
241 WaitForInputIdle(pi.hProcess, 5000);
242 CloseHandle(pi.hThread);
245 * Start the pipe reader threads.
248 pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
249 pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
252 * Block waiting for the process to end.
255 WaitForSingleObject(pi.hProcess, INFINITE);
256 CloseHandle(pi.hProcess);
259 * Wait for our pipe to get done reading, should it be a little slow.
262 WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
263 CloseHandle(pipeThreads[0]);
264 CloseHandle(pipeThreads[1]);
267 * Look for the commandline warning code in both streams.
268 * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
271 return !(strstr(Out.buffer, "D4002") != NULL
272 || strstr(Err.buffer, "D4002") != NULL
273 || strstr(Out.buffer, "D9002") != NULL
274 || strstr(Err.buffer, "D9002") != NULL);
278 CheckForLinkerFeature(
282 PROCESS_INFORMATION pi;
283 SECURITY_ATTRIBUTES sa;
287 HANDLE hProcess, h, pipeThreads[2];
290 hProcess = GetCurrentProcess();
292 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
293 ZeroMemory(&si, sizeof(STARTUPINFO));
294 si.cb = sizeof(STARTUPINFO);
295 si.dwFlags = STARTF_USESTDHANDLES;
296 si.hStdInput = INVALID_HANDLE_VALUE;
298 ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
299 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
300 sa.lpSecurityDescriptor = NULL;
301 sa.bInheritHandle = TRUE;
304 * Create a non-inheritible pipe.
307 CreatePipe(&Out.pipe, &h, &sa, 0);
310 * Dupe the write side, make it inheritible, and close the original.
313 DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
314 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
317 * Same as above, but for the error side.
320 CreatePipe(&Err.pipe, &h, &sa, 0);
321 DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
322 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
328 lstrcpy(cmdline, "link.exe -nologo ");
331 * Append our option for testing.
334 lstrcat(cmdline, option);
337 NULL, /* Module name. */
338 cmdline, /* Command line. */
339 NULL, /* Process handle not inheritable. */
340 NULL, /* Thread handle not inheritable. */
341 TRUE, /* yes, inherit handles. */
342 DETACHED_PROCESS, /* No console for you. */
343 NULL, /* Use parent's environment block. */
344 NULL, /* Use parent's starting directory. */
345 &si, /* Pointer to STARTUPINFO structure. */
346 &pi); /* Pointer to PROCESS_INFORMATION structure. */
349 DWORD err = GetLastError();
350 int chars = snprintf(msg, sizeof(msg) - 1,
351 "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
353 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
354 FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
356 WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
361 * Close our references to the write handles that have now been inherited.
364 CloseHandle(si.hStdOutput);
365 CloseHandle(si.hStdError);
367 WaitForInputIdle(pi.hProcess, 5000);
368 CloseHandle(pi.hThread);
371 * Start the pipe reader threads.
374 pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
375 pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
378 * Block waiting for the process to end.
381 WaitForSingleObject(pi.hProcess, INFINITE);
382 CloseHandle(pi.hProcess);
385 * Wait for our pipe to get done reading, should it be a little slow.
388 WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
389 CloseHandle(pipeThreads[0]);
390 CloseHandle(pipeThreads[1]);
393 * Look for the commandline warning code in the stderr stream.
396 return !(strstr(Out.buffer, "LNK1117") != NULL ||
397 strstr(Err.buffer, "LNK1117") != NULL ||
398 strstr(Out.buffer, "LNK4044") != NULL ||
399 strstr(Err.buffer, "LNK4044") != NULL);
406 pipeinfo *pi = (pipeinfo *) args;
407 char *lastBuf = pi->buffer;
412 if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
413 CloseHandle(pi->pipe);
416 ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
417 if (!ok || dwRead == 0) {
418 CloseHandle(pi->pipe);
424 return 0; /* makes the compiler happy */
430 const char *substring)
432 return (strstr(string, substring) != NULL);
436 * Find a specified #define by name.
438 * If the line is '#define TCL_VERSION "8.5"', it returns 85 as the result.
447 char s1[51], s2[51], s3[51];
451 f = fopen(file, "rt");
457 r = fscanf(f, "%50s", s1);
458 if (r == 1 && !strcmp(s1, "#define")) {
460 * Get next two words.
463 r = fscanf(f, "%50s %50s", s2, s3);
469 * Is the first word what we're looking for?
472 if (!strcmp(s2, string)) {
476 * Add 1 past first double quote char. "8.5"
479 d1 = atof(s3 + 1); /* 8.5 */
480 while (floor(d1) != d1) {
483 return ((int) d1); /* 85 */