diff --git a/ccdv-win32.c b/ccdv-win32.c index 98c6169ab..3601298c3 100644 --- a/ccdv-win32.c +++ b/ccdv-win32.c @@ -1,527 +1,527 @@ -/* ccdv.c */ - -/* Ported to Win32 by Randy Heit - * Maybe I got a little carried away. This is pure Win32 code without any CRT in sight. - * - * To build this, use one of these command lines: - * - * [MinGW] gcc -Os -s -nostdlib -o ccdv.exe ccdv-win32.c -lkernel32 -luser32 - * [MSC] cl -O1 ccdv-win32.c -link -subsystem:console -opt:nowin98 kernel32.lib user32.lib - * - * Rewriting this to not use any global variables can save 512 bytes when compiled with MSC - * because it allows the .data section to be ommitted, which means the header can occupy - * 512 bytes rather than 1024. With GCC, it doesn't help the size any, since GCC still has - * the separate .idata and .rdata sections. Since MSC really doesn't need this tool, - * I'm not bothering with that size optimization. - */ - -#define WIN32_LEAN_AND_MEAN -#include - -#define COLOR_SUCCESS (FOREGROUND_GREEN|FOREGROUND_INTENSITY) /* green */ -#define COLOR_FAILURE (FOREGROUND_RED|FOREGROUND_INTENSITY) /* red */ -#define COLOR_WARNING (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY) /* yellow */ -#define COLOR_COMMAND (FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY) /* cyan */ - -#define TEXT_BLOCK_SIZE 8192 -#define INDENT 2 - -PROCESS_INFORMATION gCCP; -size_t gNBufUsed, gNBufAllocated; -char *gBuf; -char *gAction; -char *gTarget; -char *gAr; -char *gArLibraryTarget; -BOOL gDumpCmdArgs; -char *gArgsStr; -int gColumns; -int gExitStatus; -HANDLE gHeap; - -HANDLE gStdOut, gStdErr; - -#ifdef __GNUC__ -#define REGPARM(x) __attribute((regparm(x))) -#else -#define REGPARM(x) -#endif - -void REGPARM(1) perror(const char *string) -{ - char *buffer; - DWORD error = GetLastError(); - DWORD len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error, 0, (LPTSTR)&buffer, 0, NULL); - DWORD wrote; - WriteFile (gStdErr, string, lstrlen(string), &wrote, NULL); - if(len == 0) - { - char errcode[9]; - wsprintf(errcode, "%08x", error); - WriteFile (gStdErr, ": Error ", 8, &wrote, NULL); - WriteFile (gStdErr, errcode, 8, &wrote, NULL); - } - else - { - WriteFile (gStdErr, ": ", 2, &wrote, NULL); - WriteFile (gStdErr, buffer, len, &wrote, NULL); - LocalFree(buffer); - } - WriteFile (gStdErr, "\n", 1, &wrote, NULL); -} - -static void DumpFormattedOutput() -{ - CONSOLE_SCREEN_BUFFER_INFO info; - DWORD out; - WORD color; - char *cp; - char spaces[8 + 1] = " "; - char *saved; - int curcol; - int i; - - if(!GetConsoleScreenBufferInfo(gStdOut, &info)) - { - WriteFile(gStdOut, gBuf, lstrlen(gBuf), &out, NULL); - WriteFile(gStdOut, "\n", 1, &out, NULL); - return; - } - - color = info.wAttributes & ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); - curcol = 0; - saved = NULL; - if(gDumpCmdArgs) - { - SetConsoleTextAttribute(gStdOut, color | COLOR_COMMAND); - WriteConsole(gStdOut, gBuf, lstrlen(gArgsStr)+1, &out, NULL); - SetConsoleTextAttribute(gStdOut, info.wAttributes); - } - for(cp = gBuf + lstrlen(gArgsStr) + 1;; cp++) - { - if(*cp == '\0') - { - if(saved != NULL) - { - cp = saved; - saved = NULL; - } - else - break; - } - if(*cp == '\r') - continue; - if(*cp == '\t') - { - saved = cp + 1; - cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8)); - } - if(curcol == 0) - { - for(i = INDENT; --i >= 0;) - WriteConsole(gStdOut, " " ,1, &out, NULL); - curcol = INDENT; - } - WriteConsole(gStdOut, cp, 1, &out, NULL); - if(++curcol == (gColumns - 1)) - { - WriteConsole(gStdOut, "\n", 1, &out, NULL); - curcol = 0; - } - else if(*cp == '\n') - curcol = 0; - } - HeapFree(gHeap, 0, gBuf); -} /* DumpFormattedOutput */ - -static void Wait(void) -{ - DWORD exitcode; - WaitForSingleObject(gCCP.hProcess, INFINITE); - GetExitCodeProcess(gCCP.hProcess, &exitcode); - gExitStatus = (int)exitcode; -} /* Wait */ - -static DWORD WINAPI SlurpThread(LPVOID foo) -{ - HANDLE fd = (HANDLE)foo; - char *newbuf; - DWORD ntoread; - DWORD nread; - - for(;;) - { - if(gNBufUsed == (gNBufAllocated - 1)) - { - if((newbuf = - (char *) HeapReAlloc(gHeap, 0, gBuf, - gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) - { - return 1; - } - gNBufAllocated += TEXT_BLOCK_SIZE; - gBuf = newbuf; - } - ntoread = (gNBufAllocated - gNBufUsed - 1); - if(!ReadFile(fd, gBuf + gNBufUsed, ntoread, &nread, NULL)) - { - return 2; - } - else if(nread > 0) - { - gNBufUsed += nread; - gBuf[gNBufUsed] = '\0'; - } - } - return 0; -} - -static void REGPARM(2) WriteAction(HANDLE hStdOut, const char *suffix) -{ - DWORD out; - - WriteFile(hStdOut, gAction, lstrlen(gAction), &out, NULL); - if(gTarget != NULL) - { - WriteFile(hStdOut, " ", 1, &out, NULL); - WriteFile(hStdOut, gTarget, lstrlen(gTarget), &out, NULL); - } - WriteFile(hStdOut, suffix, 3, &out, NULL); -} - -static int REGPARM(2) Slurp(HANDLE fd, HANDLE hStdOut) -{ - HANDLE handles[2]; - DWORD waitstate; - DWORD exitcode; - DWORD out; - const char *trail = "/-\\|", *trailcp; - CONSOLE_SCREEN_BUFFER_INFO info; - CONSOLE_CURSOR_INFO cursorInfo; - WORD color, colors[5]; - int ncells, i; - - trailcp = trail; - if(hStdOut != NULL) - { - WriteAction(hStdOut, "..."); - } - - handles[0] = gCCP.hProcess; - handles[1] = CreateThread(NULL, 0, SlurpThread, (LPVOID)fd, 0, NULL); - - if(handles[1] == 0) - { - perror("ccdv: CreateThread"); - return -1; - } - - if(hStdOut != NULL) - { - GetConsoleScreenBufferInfo(hStdOut, &info); - info.dwCursorPosition.X = info.dwSize.X - 9; - if(GetConsoleCursorInfo(hStdOut, &cursorInfo)) - { - cursorInfo.bVisible = FALSE; - SetConsoleCursorInfo(hStdOut, &cursorInfo); - } - else - { - cursorInfo.bVisible = TRUE; - } - } - - gExitStatus = 0xabadcafe; - while(gExitStatus == 0xabadcafe) - { - waitstate = WaitForMultipleObjects(2, handles, FALSE, 1000); - switch(waitstate) - { - case WAIT_TIMEOUT: - if(hStdOut != NULL) - { - SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); - WriteConsoleA(hStdOut, trailcp, 1, &out, NULL); - if(*++trailcp == '\0') - trailcp = trail; - } - break; - - case WAIT_FAILED: - perror("ccdv: WaitForMultipleObjects"); - CloseHandle(handles[1]); - return -1; - - case WAIT_OBJECT_0: - GetExitCodeProcess(gCCP.hProcess, &exitcode); - CloseHandle(handles[1]); - gExitStatus = (int)exitcode; - break; - - case WAIT_OBJECT_0+1: - GetExitCodeThread(handles[1], &exitcode); - CloseHandle(handles[1]); - if(exitcode == 1) - { - perror("ccdv: HeapReAlloc"); - return -1; - } - else if(exitcode == 2) - { - perror("ccdv: ReadFile"); - return -1; - } - Wait(); - break; - } - } - if(hStdOut != NULL) - { - info.dwCursorPosition.X = 0; - SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); - WriteAction(hStdOut, ": "); - info.dwCursorPosition.X = info.dwSize.X - 10; - if(gExitStatus == 0) - { - SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); - WriteConsoleA(hStdOut, "[OK] ", 9, &out, NULL); - color = ((gNBufUsed - lstrlen(gArgsStr)) < 4) ? COLOR_SUCCESS : COLOR_WARNING; - ncells = 2; - } - else - { - SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); - WriteConsoleA(hStdOut, "[ERROR] ", 9, &out, NULL); - color = COLOR_FAILURE; - ncells = 5; - gDumpCmdArgs = 1; /* print cmd when there are errors */ - } - color |= info.wAttributes & ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); - for(i = 0; i < ncells; ++i) - { - colors[i] = color; - } - info.dwCursorPosition.X++; - WriteConsoleOutputAttribute(hStdOut, colors, ncells, info.dwCursorPosition, &out); - if(!cursorInfo.bVisible) - { - cursorInfo.bVisible = TRUE; - SetConsoleCursorInfo(hStdOut, &cursorInfo); - } - WriteConsole(hStdOut, "\n", 1, &out, NULL); - } - else - { - gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */ - } - return (0); -} /* SlurpProgress */ - -static const char *REGPARM(2) Basename(const char *path, int len) -{ - while(len > 0) - { - len--; - if(path[len] == '/' || path[len] == '\\') - { - return path + len + 1; - } - } - return path; -} /* Basename */ - -static const char *REGPARM(2) Extension(const char *path, int len) -{ - while(len > 0) - { - len--; - if(path[len] == '.') - { - return path + len; - } - } - return ""; -} /* Extension */ - -static void Usage(void) -{ - static const char sUsage[] = "\ -Usage: ccdv /path/to/cc CFLAGS...\n\ -\n\ -I wrote this to reduce the deluge Make output to make finding actual problems\n\ -easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\ -\n\ - .c.o:\n\ - $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ -\n\ -Rewrite your rule so it looks like:\n\ -\n\ - .c.o:\n\ - @ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ - .cpp.o:\n\ - @ccdv $(CXX) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ -\n\ -ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n\ - -- Mike Gleason, NcFTP Software \n\ - -- John F Meinel Jr, \n\ - "; - DWORD out; - WriteFile (gStdErr, sUsage, sizeof(sUsage)-1, &out, NULL); - ExitProcess(96); -} /* Usage */ - -static BOOL REGPARM(3) StepCmdLine(char **cmdline, char **arg, int *arglen) -{ - char *gArgsStr = *cmdline; - - // Skip whitespace - while(*gArgsStr == ' ' || *gArgsStr == '\t' || *gArgsStr == '\n' || *gArgsStr == '\r') - { - gArgsStr++; - } - if(*gArgsStr == 0) - { - *cmdline = gArgsStr; - return FALSE; - } - if(*gArgsStr == '\"') - { // It's a quoted string - *arg = ++gArgsStr; - while(*gArgsStr && *gArgsStr != '\"') - { - gArgsStr++; - } - *arglen = gArgsStr - *arg; - if(*gArgsStr) - { // Ends with a quote - gArgsStr++; - } - *cmdline = gArgsStr; - return TRUE; - } - // It's a whitespace-separated string - *arg = gArgsStr; - while(*gArgsStr && *gArgsStr != ' ' && *gArgsStr != '\t' && *gArgsStr != '\n' && *gArgsStr != '\r') - { - gArgsStr++; - } - *arglen = gArgsStr - *arg; - *cmdline = gArgsStr; - return TRUE; -} - -static void REGPARM(3) SetTarget(char **target, const char *arg, int arglen) -{ - const char *base; - - if (*target) HeapFree(gHeap, 0, *target); - base = Basename(arg, arglen); - arglen = arglen - (base - arg) + 1; - *target = HeapAlloc(gHeap, 0, arglen); - lstrcpyn(*target, base, arglen); -} - -void mainCRTStartup(void) -{ - const char *ext; - char *cmdline, *arg; - int arglen, extlen; - SECURITY_ATTRIBUTES security; - STARTUPINFO siStartInfo; - HANDLE pipeRd, pipeWr, pipeRdDup; - char emerg[256]; - DWORD nread; - int cc = 0; - int yy = 0; - CONSOLE_SCREEN_BUFFER_INFO bufferInfo; - - gExitStatus = 95; - gHeap = GetProcessHeap(); - gArgsStr = cmdline = GetCommandLine(); - gStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - gStdErr = GetStdHandle(STD_ERROR_HANDLE); - - if (!StepCmdLine(&cmdline, &arg, &arglen) || // Skip ccdv.exe - !StepCmdLine(&cmdline, &arg, &arglen)) // Read name of process to run - { - Usage(); - } - - // "Running *argv[1]*" - ext = Basename(arg, arglen); - extlen = arglen - (ext - arg); - gAction = HeapAlloc(gHeap, 0, 64+extlen); - lstrcpy(gAction, "Running "); - lstrcpyn(gAction+8, ext, extlen+1); - - if (extlen == 2 && lstrcmpi(gAction+8, "ar") == CSTR_EQUAL) - { - SetTarget(&gAr, arg, arglen); - } - - while(StepCmdLine(&cmdline, &arg, &arglen)) - { - if(arglen == 2 && arg[0] == '-' && arg[1] == 'o') - { - if(StepCmdLine(&cmdline, &arg, &arglen)) - { - ext = Extension(arg, arglen); - if(ext[0] != '.' || (ext[1] != 'o' && ext[1] != 'O')) - { - lstrcpy(gAction, "Linking"); - SetTarget(&gTarget, arg, arglen); - } - } - continue; - } - else if(arg[0] == '-' || arg[0] == '+' || arg[0] == '/') - { - continue; - } - ext = Extension(arg, arglen); - if(ext[0] == '.' && (ext[1] == 'C' || ext[1] == 'c')) - { - cc++; - SetTarget(&gTarget, arg, arglen); - } - else if(ext[0] == '.' && ext[1] == 'y') - { - yy++; - } - else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ".nas", 4, ext, -1) == CSTR_EQUAL) - { - lstrcpy(gAction, "Assembling"); - SetTarget(&gTarget, arg, arglen); - } - else if(gArLibraryTarget == NULL && ext[0] == '.' && ext[1] == 'a') - { - SetTarget(&gArLibraryTarget, arg, arglen); - } - } - if((gAr != NULL) && (gArLibraryTarget != NULL)) - { - lstrcpy(gAction, "Creating library"); - if(gTarget != NULL) HeapFree(gHeap, 0, gTarget); - gTarget = gArLibraryTarget; - gArLibraryTarget = NULL; - } - else if(cc > 0) - { - lstrcpy(gAction, yy == 0 ? "Compiling" : "Generating"); - } - - /* Initialize security attributes for the pipe */ - security.nLength = sizeof security; - security.lpSecurityDescriptor = NULL; - security.bInheritHandle = TRUE; - - if(!CreatePipe(&pipeRd, &pipeWr, &security, 0)) - { - perror("ccdv: pipe"); - ExitProcess(97); - } - +/* ccdv.c */ + +/* Ported to Win32 by Randy Heit + * Maybe I got a little carried away. This is pure Win32 code without any CRT in sight. + * + * To build this, use one of these command lines: + * + * [MinGW] gcc -Os -s -nostdlib -o ccdv.exe ccdv-win32.c -lkernel32 -luser32 + * [MSC] cl -O1 ccdv-win32.c -link -subsystem:console -opt:nowin98 kernel32.lib user32.lib + * + * Rewriting this to not use any global variables can save 512 bytes when compiled with MSC + * because it allows the .data section to be ommitted, which means the header can occupy + * 512 bytes rather than 1024. With GCC, it doesn't help the size any, since GCC still has + * the separate .idata and .rdata sections. Since MSC really doesn't need this tool, + * I'm not bothering with that size optimization. + */ + +#define WIN32_LEAN_AND_MEAN +#include + +#define COLOR_SUCCESS (FOREGROUND_GREEN|FOREGROUND_INTENSITY) /* green */ +#define COLOR_FAILURE (FOREGROUND_RED|FOREGROUND_INTENSITY) /* red */ +#define COLOR_WARNING (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY) /* yellow */ +#define COLOR_COMMAND (FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY) /* cyan */ + +#define TEXT_BLOCK_SIZE 8192 +#define INDENT 2 + +PROCESS_INFORMATION gCCP; +size_t gNBufUsed, gNBufAllocated; +char *gBuf; +char *gAction; +char *gTarget; +char *gAr; +char *gArLibraryTarget; +BOOL gDumpCmdArgs; +char *gArgsStr; +int gColumns; +int gExitStatus; +HANDLE gHeap; + +HANDLE gStdOut, gStdErr; + +#ifdef __GNUC__ +#define REGPARM(x) __attribute((regparm(x))) +#else +#define REGPARM(x) +#endif + +void REGPARM(1) perror(const char *string) +{ + char *buffer; + DWORD error = GetLastError(); + DWORD len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, 0, (LPTSTR)&buffer, 0, NULL); + DWORD wrote; + WriteFile (gStdErr, string, lstrlen(string), &wrote, NULL); + if(len == 0) + { + char errcode[9]; + wsprintf(errcode, "%08x", error); + WriteFile (gStdErr, ": Error ", 8, &wrote, NULL); + WriteFile (gStdErr, errcode, 8, &wrote, NULL); + } + else + { + WriteFile (gStdErr, ": ", 2, &wrote, NULL); + WriteFile (gStdErr, buffer, len, &wrote, NULL); + LocalFree(buffer); + } + WriteFile (gStdErr, "\n", 1, &wrote, NULL); +} + +static void DumpFormattedOutput() +{ + CONSOLE_SCREEN_BUFFER_INFO info; + DWORD out; + WORD color; + char *cp; + char spaces[8 + 1] = " "; + char *saved; + int curcol; + int i; + + if(!GetConsoleScreenBufferInfo(gStdOut, &info)) + { + WriteFile(gStdOut, gBuf, lstrlen(gBuf), &out, NULL); + WriteFile(gStdOut, "\n", 1, &out, NULL); + return; + } + + color = info.wAttributes & ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); + curcol = 0; + saved = NULL; + if(gDumpCmdArgs) + { + SetConsoleTextAttribute(gStdOut, color | COLOR_COMMAND); + WriteConsole(gStdOut, gBuf, lstrlen(gArgsStr)+1, &out, NULL); + SetConsoleTextAttribute(gStdOut, info.wAttributes); + } + for(cp = gBuf + lstrlen(gArgsStr) + 1;; cp++) + { + if(*cp == '\0') + { + if(saved != NULL) + { + cp = saved; + saved = NULL; + } + else + break; + } + if(*cp == '\r') + continue; + if(*cp == '\t') + { + saved = cp + 1; + cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8)); + } + if(curcol == 0) + { + for(i = INDENT; --i >= 0;) + WriteConsole(gStdOut, " " ,1, &out, NULL); + curcol = INDENT; + } + WriteConsole(gStdOut, cp, 1, &out, NULL); + if(++curcol == (gColumns - 1)) + { + WriteConsole(gStdOut, "\n", 1, &out, NULL); + curcol = 0; + } + else if(*cp == '\n') + curcol = 0; + } + HeapFree(gHeap, 0, gBuf); +} /* DumpFormattedOutput */ + +static void Wait(void) +{ + DWORD exitcode; + WaitForSingleObject(gCCP.hProcess, INFINITE); + GetExitCodeProcess(gCCP.hProcess, &exitcode); + gExitStatus = (int)exitcode; +} /* Wait */ + +static DWORD WINAPI SlurpThread(LPVOID foo) +{ + HANDLE fd = (HANDLE)foo; + char *newbuf; + DWORD ntoread; + DWORD nread; + + for(;;) + { + if(gNBufUsed == (gNBufAllocated - 1)) + { + if((newbuf = + (char *) HeapReAlloc(gHeap, 0, gBuf, + gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) + { + return 1; + } + gNBufAllocated += TEXT_BLOCK_SIZE; + gBuf = newbuf; + } + ntoread = (gNBufAllocated - gNBufUsed - 1); + if(!ReadFile(fd, gBuf + gNBufUsed, ntoread, &nread, NULL)) + { + return 2; + } + else if(nread > 0) + { + gNBufUsed += nread; + gBuf[gNBufUsed] = '\0'; + } + } + return 0; +} + +static void REGPARM(2) WriteAction(HANDLE hStdOut, const char *suffix) +{ + DWORD out; + + WriteFile(hStdOut, gAction, lstrlen(gAction), &out, NULL); + if(gTarget != NULL) + { + WriteFile(hStdOut, " ", 1, &out, NULL); + WriteFile(hStdOut, gTarget, lstrlen(gTarget), &out, NULL); + } + WriteFile(hStdOut, suffix, 3, &out, NULL); +} + +static int REGPARM(2) Slurp(HANDLE fd, HANDLE hStdOut) +{ + HANDLE handles[2]; + DWORD waitstate; + DWORD exitcode; + DWORD out; + const char *trail = "/-\\|", *trailcp; + CONSOLE_SCREEN_BUFFER_INFO info; + CONSOLE_CURSOR_INFO cursorInfo; + WORD color, colors[5]; + int ncells, i; + + trailcp = trail; + if(hStdOut != NULL) + { + WriteAction(hStdOut, "..."); + } + + handles[0] = gCCP.hProcess; + handles[1] = CreateThread(NULL, 0, SlurpThread, (LPVOID)fd, 0, NULL); + + if(handles[1] == 0) + { + perror("ccdv: CreateThread"); + return -1; + } + + if(hStdOut != NULL) + { + GetConsoleScreenBufferInfo(hStdOut, &info); + info.dwCursorPosition.X = info.dwSize.X - 9; + if(GetConsoleCursorInfo(hStdOut, &cursorInfo)) + { + cursorInfo.bVisible = FALSE; + SetConsoleCursorInfo(hStdOut, &cursorInfo); + } + else + { + cursorInfo.bVisible = TRUE; + } + } + + gExitStatus = 0xabadcafe; + while(gExitStatus == 0xabadcafe) + { + waitstate = WaitForMultipleObjects(2, handles, FALSE, 1000); + switch(waitstate) + { + case WAIT_TIMEOUT: + if(hStdOut != NULL) + { + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteConsoleA(hStdOut, trailcp, 1, &out, NULL); + if(*++trailcp == '\0') + trailcp = trail; + } + break; + + case WAIT_FAILED: + perror("ccdv: WaitForMultipleObjects"); + CloseHandle(handles[1]); + return -1; + + case WAIT_OBJECT_0: + GetExitCodeProcess(gCCP.hProcess, &exitcode); + CloseHandle(handles[1]); + gExitStatus = (int)exitcode; + break; + + case WAIT_OBJECT_0+1: + GetExitCodeThread(handles[1], &exitcode); + CloseHandle(handles[1]); + if(exitcode == 1) + { + perror("ccdv: HeapReAlloc"); + return -1; + } + else if(exitcode == 2) + { + perror("ccdv: ReadFile"); + return -1; + } + Wait(); + break; + } + } + if(hStdOut != NULL) + { + info.dwCursorPosition.X = 0; + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteAction(hStdOut, ": "); + info.dwCursorPosition.X = info.dwSize.X - 10; + if(gExitStatus == 0) + { + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteConsoleA(hStdOut, "[OK] ", 9, &out, NULL); + color = ((gNBufUsed - lstrlen(gArgsStr)) < 4) ? COLOR_SUCCESS : COLOR_WARNING; + ncells = 2; + } + else + { + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + WriteConsoleA(hStdOut, "[ERROR] ", 9, &out, NULL); + color = COLOR_FAILURE; + ncells = 5; + gDumpCmdArgs = 1; /* print cmd when there are errors */ + } + color |= info.wAttributes & ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); + for(i = 0; i < ncells; ++i) + { + colors[i] = color; + } + info.dwCursorPosition.X++; + WriteConsoleOutputAttribute(hStdOut, colors, ncells, info.dwCursorPosition, &out); + if(!cursorInfo.bVisible) + { + cursorInfo.bVisible = TRUE; + SetConsoleCursorInfo(hStdOut, &cursorInfo); + } + WriteConsole(hStdOut, "\n", 1, &out, NULL); + } + else + { + gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */ + } + return (0); +} /* SlurpProgress */ + +static const char *REGPARM(2) Basename(const char *path, int len) +{ + while(len > 0) + { + len--; + if(path[len] == '/' || path[len] == '\\') + { + return path + len + 1; + } + } + return path; +} /* Basename */ + +static const char *REGPARM(2) Extension(const char *path, int len) +{ + while(len > 0) + { + len--; + if(path[len] == '.') + { + return path + len; + } + } + return ""; +} /* Extension */ + +static void Usage(void) +{ + static const char sUsage[] = "\ +Usage: ccdv /path/to/cc CFLAGS...\n\ +\n\ +I wrote this to reduce the deluge Make output to make finding actual problems\n\ +easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\ +\n\ + .c.o:\n\ + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ +\n\ +Rewrite your rule so it looks like:\n\ +\n\ + .c.o:\n\ + @ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ + .cpp.o:\n\ + @ccdv $(CXX) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ +\n\ +ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n\ + -- Mike Gleason, NcFTP Software \n\ + -- John F Meinel Jr, \n\ + "; + DWORD out; + WriteFile (gStdErr, sUsage, sizeof(sUsage)-1, &out, NULL); + ExitProcess(96); +} /* Usage */ + +static BOOL REGPARM(3) StepCmdLine(char **cmdline, char **arg, int *arglen) +{ + char *gArgsStr = *cmdline; + + // Skip whitespace + while(*gArgsStr == ' ' || *gArgsStr == '\t' || *gArgsStr == '\n' || *gArgsStr == '\r') + { + gArgsStr++; + } + if(*gArgsStr == 0) + { + *cmdline = gArgsStr; + return FALSE; + } + if(*gArgsStr == '\"') + { // It's a quoted string + *arg = ++gArgsStr; + while(*gArgsStr && *gArgsStr != '\"') + { + gArgsStr++; + } + *arglen = gArgsStr - *arg; + if(*gArgsStr) + { // Ends with a quote + gArgsStr++; + } + *cmdline = gArgsStr; + return TRUE; + } + // It's a whitespace-separated string + *arg = gArgsStr; + while(*gArgsStr && *gArgsStr != ' ' && *gArgsStr != '\t' && *gArgsStr != '\n' && *gArgsStr != '\r') + { + gArgsStr++; + } + *arglen = gArgsStr - *arg; + *cmdline = gArgsStr; + return TRUE; +} + +static void REGPARM(3) SetTarget(char **target, const char *arg, int arglen) +{ + const char *base; + + if (*target) HeapFree(gHeap, 0, *target); + base = Basename(arg, arglen); + arglen = arglen - (base - arg) + 1; + *target = HeapAlloc(gHeap, 0, arglen); + lstrcpyn(*target, base, arglen); +} + +void mainCRTStartup(void) +{ + const char *ext; + char *cmdline, *arg; + int arglen, extlen; + SECURITY_ATTRIBUTES security; + STARTUPINFO siStartInfo; + HANDLE pipeRd, pipeWr, pipeRdDup; + char emerg[256]; + DWORD nread; + int cc = 0; + int yy = 0; + CONSOLE_SCREEN_BUFFER_INFO bufferInfo; + + gExitStatus = 95; + gHeap = GetProcessHeap(); + gArgsStr = cmdline = GetCommandLine(); + gStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + gStdErr = GetStdHandle(STD_ERROR_HANDLE); + + if (!StepCmdLine(&cmdline, &arg, &arglen) || // Skip ccdv.exe + !StepCmdLine(&cmdline, &arg, &arglen)) // Read name of process to run + { + Usage(); + } + + // "Running *argv[1]*" + ext = Basename(arg, arglen); + extlen = arglen - (ext - arg); + gAction = HeapAlloc(gHeap, 0, 64+extlen); + lstrcpy(gAction, "Running "); + lstrcpyn(gAction+8, ext, extlen+1); + + if (extlen == 2 && lstrcmpi(gAction+8, "ar") == CSTR_EQUAL) + { + SetTarget(&gAr, arg, arglen); + } + + while(StepCmdLine(&cmdline, &arg, &arglen)) + { + if(arglen == 2 && arg[0] == '-' && arg[1] == 'o') + { + if(StepCmdLine(&cmdline, &arg, &arglen)) + { + ext = Extension(arg, arglen); + if(ext[0] != '.' || (ext[1] != 'o' && ext[1] != 'O')) + { + lstrcpy(gAction, "Linking"); + SetTarget(&gTarget, arg, arglen); + } + } + continue; + } + else if(arg[0] == '-' || arg[0] == '+' || arg[0] == '/') + { + continue; + } + ext = Extension(arg, arglen); + if(ext[0] == '.' && (ext[1] == 'C' || ext[1] == 'c')) + { + cc++; + SetTarget(&gTarget, arg, arglen); + } + else if(ext[0] == '.' && ext[1] == 'y') + { + yy++; + } + else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ".nas", 4, ext, -1) == CSTR_EQUAL) + { + lstrcpy(gAction, "Assembling"); + SetTarget(&gTarget, arg, arglen); + } + else if(gArLibraryTarget == NULL && ext[0] == '.' && ext[1] == 'a') + { + SetTarget(&gArLibraryTarget, arg, arglen); + } + } + if((gAr != NULL) && (gArLibraryTarget != NULL)) + { + lstrcpy(gAction, "Creating library"); + if(gTarget != NULL) HeapFree(gHeap, 0, gTarget); + gTarget = gArLibraryTarget; + gArLibraryTarget = NULL; + } + else if(cc > 0) + { + lstrcpy(gAction, yy == 0 ? "Compiling" : "Generating"); + } + + /* Initialize security attributes for the pipe */ + security.nLength = sizeof security; + security.lpSecurityDescriptor = NULL; + security.bInheritHandle = TRUE; + + if(!CreatePipe(&pipeRd, &pipeWr, &security, 0)) + { + perror("ccdv: pipe"); + ExitProcess(97); + } + if (!DuplicateHandle(GetCurrentProcess(), pipeRd, GetCurrentProcess(), &pipeRdDup , 0, FALSE, @@ -530,40 +530,40 @@ void mainCRTStartup(void) perror("ccdv: DuplicateHandle"); } CloseHandle(pipeRd); - - /* Initialize startup info for the child process */ - siStartInfo.cb = sizeof siStartInfo; - siStartInfo.lpReserved = NULL; - siStartInfo.lpDesktop = NULL; - siStartInfo.lpTitle = NULL; - siStartInfo.dwX = 0; - siStartInfo.dwY = 0; - siStartInfo.dwXSize = 0; - siStartInfo.dwYSize = 0; - siStartInfo.dwXCountChars = 0; - siStartInfo.dwYCountChars = 0; - siStartInfo.dwFillAttribute = 0; - siStartInfo.dwFlags = STARTF_USESTDHANDLES; - siStartInfo.wShowWindow = 0; - siStartInfo.cbReserved2 = 0; - siStartInfo.lpReserved2 = 0; - siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - siStartInfo.hStdOutput = pipeWr; - siStartInfo.hStdError = pipeWr; + + /* Initialize startup info for the child process */ + siStartInfo.cb = sizeof siStartInfo; + siStartInfo.lpReserved = NULL; + siStartInfo.lpDesktop = NULL; + siStartInfo.lpTitle = NULL; + siStartInfo.dwX = 0; + siStartInfo.dwY = 0; + siStartInfo.dwXSize = 0; + siStartInfo.dwYSize = 0; + siStartInfo.dwXCountChars = 0; + siStartInfo.dwYCountChars = 0; + siStartInfo.dwFillAttribute = 0; + siStartInfo.dwFlags = STARTF_USESTDHANDLES; + siStartInfo.wShowWindow = 0; + siStartInfo.cbReserved2 = 0; + siStartInfo.lpReserved2 = 0; + siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + siStartInfo.hStdOutput = pipeWr; + siStartInfo.hStdError = pipeWr; StepCmdLine(&gArgsStr, &arg, &arglen); // Skip "ccdv" - while(*gArgsStr == ' ' || *gArgsStr == '\t' || *gArgsStr == '\n' || *gArgsStr == '\r') - gArgsStr++; + while(*gArgsStr == ' ' || *gArgsStr == '\t' || *gArgsStr == '\n' || *gArgsStr == '\r') + gArgsStr++; extlen = lstrlen(gArgsStr); gNBufAllocated = extlen + TEXT_BLOCK_SIZE; - gBuf = (char *) HeapAlloc(gHeap, 0, gNBufAllocated); - if(gBuf == NULL) - goto panic; - gNBufUsed = extlen + 1; - lstrcpy(gBuf, gArgsStr); - gBuf[extlen] = '\n'; - gBuf[extlen+1] = 0; + gBuf = (char *) HeapAlloc(gHeap, 0, gNBufAllocated); + if(gBuf == NULL) + goto panic; + gNBufUsed = extlen + 1; + lstrcpy(gBuf, gArgsStr); + gBuf[extlen] = '\n'; + gBuf[extlen+1] = 0; if(!CreateProcessA(NULL, gArgsStr, /* command gArgsStr */ @@ -583,28 +583,28 @@ void mainCRTStartup(void) goto panic; } CloseHandle(gCCP.hThread); - - if(GetConsoleScreenBufferInfo(gStdOut, &bufferInfo)) - { - gColumns = bufferInfo.dwSize.X; - if(Slurp(pipeRdDup, gStdOut) < 0) - goto panic; - } - else - { - if(Slurp(pipeRdDup, NULL) < 0) - goto panic; - } - DumpFormattedOutput(); - ExitProcess(gExitStatus); - - panic: - gDumpCmdArgs = 1; /* print cmd when there are errors */ - DumpFormattedOutput(); - while(ReadFile(pipeRdDup, emerg, sizeof emerg, &nread, NULL) && nread > 0) - WriteFile(gStdErr, emerg, nread, &nread, NULL); - Wait(); - ExitProcess(gExitStatus); -} /* main */ - -/* eof ccdv.c */ + + if(GetConsoleScreenBufferInfo(gStdOut, &bufferInfo)) + { + gColumns = bufferInfo.dwSize.X; + if(Slurp(pipeRdDup, gStdOut) < 0) + goto panic; + } + else + { + if(Slurp(pipeRdDup, NULL) < 0) + goto panic; + } + DumpFormattedOutput(); + ExitProcess(gExitStatus); + + panic: + gDumpCmdArgs = 1; /* print cmd when there are errors */ + DumpFormattedOutput(); + while(ReadFile(pipeRdDup, emerg, sizeof emerg, &nread, NULL) && nread > 0) + WriteFile(gStdErr, emerg, nread, &nread, NULL); + Wait(); + ExitProcess(gExitStatus); +} /* main */ + +/* eof ccdv.c */