~ubuntu-branches/ubuntu/dapper/perl-tk/dapper

« back to all changes in this revision

Viewing changes to pTk/mTk/tclWin/nmakehlp.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael C. Schultheiss
  • Date: 2006-01-16 16:54:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060116165402-1ppygm8hh8ahel2x
Tags: 1:804.027-2
* Incorporate changes from NMU (Thanks to Steve Kowalik.
  Closes: #348086)
* debian/control: Update Standards-Version (no changes needed)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ----------------------------------------------------------------------------
 
2
 * nmakehlp.c --
 
3
 *
 
4
 *      This is used to fix limitations within nmake and the environment.
 
5
 *
 
6
 * Copyright (c) 2002 by David Gravereaux.
 
7
 *
 
8
 * See the file "license.terms" for information on usage and redistribution
 
9
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 
10
 *
 
11
 * ----------------------------------------------------------------------------
 
12
 * RCS: @(#) $Id: nmakehlp.c,v 1.1 2002/03/27 21:15:43 davygrvy Exp $
 
13
 * ----------------------------------------------------------------------------
 
14
 */
 
15
#include <windows.h>
 
16
#pragma comment (lib, "user32.lib")
 
17
#pragma comment (lib, "kernel32.lib")
 
18
 
 
19
/* protos */
 
20
int CheckForCompilerFeature (const char *option);
 
21
int CheckForLinkerFeature (const char *option);
 
22
int IsIn (const char *string, const char *substring);
 
23
DWORD WINAPI ReadFromPipe (LPVOID args);
 
24
 
 
25
/* globals */
 
26
typedef struct {
 
27
    HANDLE pipe;
 
28
    char buffer[1000];
 
29
} pipeinfo;
 
30
 
 
31
pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
 
32
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
 
33
 
 
34
 
 
35
 
 
36
/* exitcodes: 0 == no, 1 == yes, 2 == error */
 
37
int
 
38
main (int argc, char *argv[])
 
39
{
 
40
    char msg[300];
 
41
    DWORD dwWritten;
 
42
    int chars;
 
43
 
 
44
    if (argc > 1 && *argv[1] == '-') {
 
45
        switch (*(argv[1]+1)) {
 
46
        case 'c':
 
47
            if (argc != 3) {
 
48
                chars = wsprintf(msg, "usage: %s -c <compiler option>\n"
 
49
                        "Tests for whether cl.exe supports an option\n"
 
50
                        "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
 
51
                WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
 
52
                return 2;
 
53
            }
 
54
            return CheckForCompilerFeature(argv[2]);
 
55
        case 'l':
 
56
            if (argc != 3) {
 
57
                chars = wsprintf(msg, "usage: %s -l <linker option>\n"
 
58
                        "Tests for whether link.exe supports an option\n"
 
59
                        "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
 
60
                WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
 
61
                return 2;
 
62
            }
 
63
            return CheckForLinkerFeature(argv[2]);
 
64
        case 'f':
 
65
            if (argc == 2) {
 
66
                chars = wsprintf(msg, "usage: %s -f <string> <substring>\n"
 
67
                    "Find a substring within another\n"
 
68
                    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
 
69
                WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
 
70
                return 2;
 
71
            } else if (argc == 3) {
 
72
                /* if the string is blank, there is no match */
 
73
                return 0;
 
74
            } else {
 
75
                return IsIn(argv[2], argv[3]);
 
76
            }
 
77
        }
 
78
    }
 
79
    chars = wsprintf(msg, "usage: %s -c|-l|-f ...\n"
 
80
            "This is a little helper app to equalize shell differences between WinNT and\n"
 
81
            "Win9x and get nmake.exe to accomplish its job.\n",
 
82
            argv[0]);
 
83
    WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
 
84
    return 2;
 
85
}
 
86
 
 
87
int
 
88
CheckForCompilerFeature (const char *option)
 
89
{
 
90
    STARTUPINFO si;
 
91
    PROCESS_INFORMATION pi;
 
92
    SECURITY_ATTRIBUTES sa;
 
93
    DWORD threadID;
 
94
    char msg[300];
 
95
    BOOL ok;
 
96
    HANDLE hProcess, h, pipeThreads[2];
 
97
    char cmdline[100];
 
98
 
 
99
    hProcess = GetCurrentProcess();
 
100
 
 
101
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
 
102
    ZeroMemory(&si, sizeof(STARTUPINFO));
 
103
    si.cb = sizeof(STARTUPINFO);
 
104
    si.dwFlags   = STARTF_USESTDHANDLES;
 
105
    si.hStdInput = INVALID_HANDLE_VALUE;
 
106
 
 
107
    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
 
108
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
 
109
    sa.lpSecurityDescriptor = NULL;
 
110
    sa.bInheritHandle = FALSE;
 
111
 
 
112
    /* create a non-inheritible pipe. */
 
113
    CreatePipe(&Out.pipe, &h, &sa, 0);
 
114
 
 
115
    /* dupe the write side, make it inheritible, and close the original. */
 
116
    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput,
 
117
            0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
118
 
 
119
    /* Same as above, but for the error side. */
 
120
    CreatePipe(&Err.pipe, &h, &sa, 0);
 
121
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
 
122
            0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
123
 
 
124
    /* base command line */
 
125
    strcpy(cmdline, "cl.exe -nologo -c -TC -Fdtemp ");
 
126
    /* append our option for testing */
 
127
    strcat(cmdline, option);
 
128
    /* filename to compile, which exists, but is nothing and empty. */
 
129
    strcat(cmdline, " nul");
 
130
 
 
131
    ok = CreateProcess(
 
132
            NULL,           /* Module name. */
 
133
            cmdline,        /* Command line. */
 
134
            NULL,           /* Process handle not inheritable. */
 
135
            NULL,           /* Thread handle not inheritable. */
 
136
            TRUE,           /* yes, inherit handles. */
 
137
            DETACHED_PROCESS, /* No console for you. */
 
138
            NULL,           /* Use parent's environment block. */
 
139
            NULL,           /* Use parent's starting directory. */
 
140
            &si,            /* Pointer to STARTUPINFO structure. */
 
141
            &pi);           /* Pointer to PROCESS_INFORMATION structure. */
 
142
 
 
143
    if (!ok) {
 
144
        DWORD err = GetLastError();
 
145
        int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
 
146
 
 
147
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
 
148
                FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
 
149
                (300-chars), 0);
 
150
        WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
 
151
        return 2;
 
152
    }
 
153
 
 
154
    /* close our references to the write handles that have now been inherited. */
 
155
    CloseHandle(si.hStdOutput);
 
156
    CloseHandle(si.hStdError);
 
157
 
 
158
    WaitForInputIdle(pi.hProcess, 5000);
 
159
    CloseHandle(pi.hThread);
 
160
 
 
161
    /* start the pipe reader threads. */
 
162
    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
 
163
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
 
164
 
 
165
    /* block waiting for the process to end. */
 
166
    WaitForSingleObject(pi.hProcess, INFINITE);
 
167
    CloseHandle(pi.hProcess);
 
168
 
 
169
    /* clean up temporary files before returning */
 
170
    DeleteFile("temp.idb");
 
171
    DeleteFile("temp.pdb");
 
172
 
 
173
    /* wait for our pipe to get done reading, should it be a little slow. */
 
174
    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
 
175
    CloseHandle(pipeThreads[0]);
 
176
    CloseHandle(pipeThreads[1]);
 
177
 
 
178
    /* look for the commandline warning code in both streams. */
 
179
    return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL);
 
180
}
 
181
 
 
182
int
 
183
CheckForLinkerFeature (const char *option)
 
184
{
 
185
    STARTUPINFO si;
 
186
    PROCESS_INFORMATION pi;
 
187
    SECURITY_ATTRIBUTES sa;
 
188
    DWORD threadID;
 
189
    char msg[300];
 
190
    BOOL ok;
 
191
    HANDLE hProcess, h, pipeThreads[2];
 
192
    char cmdline[100];
 
193
 
 
194
    hProcess = GetCurrentProcess();
 
195
 
 
196
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
 
197
    ZeroMemory(&si, sizeof(STARTUPINFO));
 
198
    si.cb = sizeof(STARTUPINFO);
 
199
    si.dwFlags   = STARTF_USESTDHANDLES;
 
200
    si.hStdInput = INVALID_HANDLE_VALUE;
 
201
 
 
202
    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
 
203
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
 
204
    sa.lpSecurityDescriptor = NULL;
 
205
    sa.bInheritHandle = TRUE;
 
206
 
 
207
    /* create a non-inheritible pipe. */
 
208
    CreatePipe(&Out.pipe, &h, &sa, 0);
 
209
 
 
210
    /* dupe the write side, make it inheritible, and close the original. */
 
211
    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput,
 
212
            0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
213
 
 
214
    /* Same as above, but for the error side. */
 
215
    CreatePipe(&Err.pipe, &h, &sa, 0);
 
216
    DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
 
217
            0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
 
218
 
 
219
    /* base command line */
 
220
    strcpy(cmdline, "link.exe -nologo ");
 
221
    /* append our option for testing */
 
222
    strcat(cmdline, option);
 
223
    /* filename to compile, which exists, but is nothing and empty. */
 
224
//    strcat(cmdline, " nul");
 
225
 
 
226
    ok = CreateProcess(
 
227
            NULL,           /* Module name. */
 
228
            cmdline,        /* Command line. */
 
229
            NULL,           /* Process handle not inheritable. */
 
230
            NULL,           /* Thread handle not inheritable. */
 
231
            TRUE,           /* yes, inherit handles. */
 
232
            DETACHED_PROCESS, /* No console for you. */
 
233
            NULL,           /* Use parent's environment block. */
 
234
            NULL,           /* Use parent's starting directory. */
 
235
            &si,            /* Pointer to STARTUPINFO structure. */
 
236
            &pi);           /* Pointer to PROCESS_INFORMATION structure. */
 
237
 
 
238
    if (!ok) {
 
239
        DWORD err = GetLastError();
 
240
        int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
 
241
 
 
242
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
 
243
                FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
 
244
                (300-chars), 0);
 
245
        WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
 
246
        return 2;
 
247
    }
 
248
 
 
249
    /* close our references to the write handles that have now been inherited. */
 
250
    CloseHandle(si.hStdOutput);
 
251
    CloseHandle(si.hStdError);
 
252
 
 
253
    WaitForInputIdle(pi.hProcess, 5000);
 
254
    CloseHandle(pi.hThread);
 
255
 
 
256
    /* start the pipe reader threads. */
 
257
    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
 
258
    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
 
259
 
 
260
    /* block waiting for the process to end. */
 
261
    WaitForSingleObject(pi.hProcess, INFINITE);
 
262
    CloseHandle(pi.hProcess);
 
263
 
 
264
    /* wait for our pipe to get done reading, should it be a little slow. */
 
265
    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
 
266
    CloseHandle(pipeThreads[0]);
 
267
    CloseHandle(pipeThreads[1]);
 
268
 
 
269
    /* look for the commandline warning code in the stderr stream. */
 
270
    return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL);
 
271
}
 
272
 
 
273
DWORD WINAPI
 
274
ReadFromPipe (LPVOID args)
 
275
{
 
276
    pipeinfo *pi = (pipeinfo *) args;
 
277
    char *lastBuf = pi->buffer;
 
278
    DWORD dwRead;
 
279
    BOOL ok;
 
280
 
 
281
again:
 
282
    ok = ReadFile(pi->pipe, lastBuf, 25, &dwRead, 0L);
 
283
    if (!ok || dwRead == 0) {
 
284
        CloseHandle(pi->pipe);
 
285
        return 0;
 
286
    }
 
287
    lastBuf += dwRead;
 
288
    goto again;
 
289
 
 
290
    return 0;  /* makes the compiler happy */
 
291
}
 
292
 
 
293
int
 
294
IsIn (const char *string, const char *substring)
 
295
{
 
296
    return (strstr(string, substring) != NULL);
 
297
}