| 1 | /* $Id: startuphacks-win.c 2243 2009-01-10 02:24:02Z bird $ */ | 
|---|
| 2 | /** @file | 
|---|
| 3 | * kBuild - Alternative argument parser for the windows startup code. | 
|---|
| 4 | * | 
|---|
| 5 | * @todo Update license when SED is updated. | 
|---|
| 6 | */ | 
|---|
| 7 |  | 
|---|
| 8 | /* | 
|---|
| 9 | * Copyright (c) 2006-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net> | 
|---|
| 10 | * | 
|---|
| 11 | * parse_args(): Copyright (c) 1992-1998 by Eberhard Mattes | 
|---|
| 12 | * | 
|---|
| 13 | * | 
|---|
| 14 | * This file is part of kBuild. | 
|---|
| 15 | * | 
|---|
| 16 | * kBuild is free software; you can redistribute it and/or modify | 
|---|
| 17 | * it under the terms of the GNU General Public License as published by | 
|---|
| 18 | * the Free Software Foundation; either version 2 of the License, or | 
|---|
| 19 | * (at your option) any later version. | 
|---|
| 20 | * | 
|---|
| 21 | * kBuild is distributed in the hope that it will be useful, | 
|---|
| 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
| 24 | * GNU General Public License for more details. | 
|---|
| 25 | * | 
|---|
| 26 | * You should have received a copy of the GNU General Public License | 
|---|
| 27 | * along with kBuild; if not, write to the Free Software | 
|---|
| 28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|---|
| 29 | * | 
|---|
| 30 | */ | 
|---|
| 31 |  | 
|---|
| 32 | /******************************************************************************* | 
|---|
| 33 | *   Header Files                                                               * | 
|---|
| 34 | *******************************************************************************/ | 
|---|
| 35 | #include <stdlib.h> | 
|---|
| 36 | #include <malloc.h> | 
|---|
| 37 | #include <Windows.h> | 
|---|
| 38 |  | 
|---|
| 39 |  | 
|---|
| 40 | /******************************************************************************* | 
|---|
| 41 | *   Internal Functions                                                         * | 
|---|
| 42 | *******************************************************************************/ | 
|---|
| 43 | static int parse_args(const char *pszSrc, char **argv, char *pchPool); | 
|---|
| 44 |  | 
|---|
| 45 |  | 
|---|
| 46 | /******************************************************************************* | 
|---|
| 47 | *   Global Variables                                                           * | 
|---|
| 48 | *******************************************************************************/ | 
|---|
| 49 | /** argument count found by parse_args(). */ | 
|---|
| 50 | static int  g_cArgs = 0; | 
|---|
| 51 | /** the argument vector, for __getmainargs(). */ | 
|---|
| 52 | static char **g_papszArgs = NULL; | 
|---|
| 53 |  | 
|---|
| 54 |  | 
|---|
| 55 |  | 
|---|
| 56 | int __cdecl _setargv(void) | 
|---|
| 57 | { | 
|---|
| 58 | static char s_szProgramName[MAX_PATH + 1]; | 
|---|
| 59 | const char *pszCmdLine; | 
|---|
| 60 | char       *pszCmdLineBuf; | 
|---|
| 61 | int         cb; | 
|---|
| 62 |  | 
|---|
| 63 | /* | 
|---|
| 64 | * Set the program name. | 
|---|
| 65 | */ | 
|---|
| 66 | GetModuleFileName(NULL, s_szProgramName, MAX_PATH); | 
|---|
| 67 | s_szProgramName[MAX_PATH] = '\0'; | 
|---|
| 68 | #if _MSC_VER >= 1400 && !defined(CRTDLL) && !defined(_DLL) | 
|---|
| 69 | _set_pgmptr(s_szProgramName); | 
|---|
| 70 | #endif | 
|---|
| 71 |  | 
|---|
| 72 | /* | 
|---|
| 73 | * Get the commandline, use the program name if nothings available. | 
|---|
| 74 | */ | 
|---|
| 75 | pszCmdLine = (const char *)GetCommandLineA(); | 
|---|
| 76 | if (!pszCmdLine || !*pszCmdLine) | 
|---|
| 77 | pszCmdLine = s_szProgramName; | 
|---|
| 78 |  | 
|---|
| 79 | /* | 
|---|
| 80 | * Parse the argument commandline emitting the unix argument vector. | 
|---|
| 81 | */ | 
|---|
| 82 | cb = parse_args(pszCmdLine, NULL, NULL); | 
|---|
| 83 | g_papszArgs = malloc(sizeof(*g_papszArgs) * (g_cArgs + 2)); | 
|---|
| 84 | if (!g_papszArgs) | 
|---|
| 85 | return -1; | 
|---|
| 86 | pszCmdLineBuf = malloc(cb); | 
|---|
| 87 | if (!pszCmdLineBuf) | 
|---|
| 88 | return -1; | 
|---|
| 89 | parse_args(pszCmdLine, g_papszArgs, pszCmdLineBuf); | 
|---|
| 90 | g_papszArgs[g_cArgs] = g_papszArgs[g_cArgs + 1] = NULL; | 
|---|
| 91 |  | 
|---|
| 92 | /* set return variables */ | 
|---|
| 93 | __argc = g_cArgs; | 
|---|
| 94 | __argv = g_papszArgs; | 
|---|
| 95 | return 0; | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 |  | 
|---|
| 99 | /* when linking with the crtexe.c, the __getmainargs() call will redo the _setargv job inside the msvc*.dll. */ | 
|---|
| 100 | int __cdecl __getmainargs(int *pargc, char ***pargv, char ***penvp, int dowildcard, /*_startupinfo*/ void *startinfo) | 
|---|
| 101 | { | 
|---|
| 102 | __argc = *pargc = g_cArgs; | 
|---|
| 103 | __argv = *pargv = g_papszArgs; | 
|---|
| 104 | *penvp = _environ; | 
|---|
| 105 | return 0; | 
|---|
| 106 | } | 
|---|
| 107 |  | 
|---|
| 108 | #if defined(_M_IX86) | 
|---|
| 109 | int (__cdecl * _imp____getmainargs)(int *, char ***, char ***, int, /*_startupinfo*/ void *) = __getmainargs; | 
|---|
| 110 | #else | 
|---|
| 111 | int (__cdecl * __imp___getmainargs)(int *, char ***, char ***, int, /*_startupinfo*/ void *) = __getmainargs; | 
|---|
| 112 | #endif | 
|---|
| 113 |  | 
|---|
| 114 |  | 
|---|
| 115 |  | 
|---|
| 116 | /** | 
|---|
| 117 | * Parses the argument string passed in as pszSrc. | 
|---|
| 118 | * | 
|---|
| 119 | * @returns size of the processed arguments. | 
|---|
| 120 | * @param   pszSrc  Pointer to the commandline that's to be parsed. | 
|---|
| 121 | * @param   argv    Pointer to argument vector to put argument pointers in. NULL allowed. | 
|---|
| 122 | * @param   pchPool Pointer to memory pchPool to put the arguments into. NULL allowed. | 
|---|
| 123 | */ | 
|---|
| 124 | static int parse_args(const char *pszSrc, char **argv, char *pchPool) | 
|---|
| 125 | { | 
|---|
| 126 | int   bs; | 
|---|
| 127 | char  chQuote; | 
|---|
| 128 | char *pfFlags; | 
|---|
| 129 | int   cbArgs; | 
|---|
| 130 |  | 
|---|
| 131 | #define PUTC(c) do { ++cbArgs; if (pchPool != NULL) *pchPool++ = (c); } while (0) | 
|---|
| 132 | #define PUTV    do { ++g_cArgs; if (argv != NULL) *argv++ = pchPool; } while (0) | 
|---|
| 133 | #define WHITE(c) ((c) == ' ' || (c) == '\t') | 
|---|
| 134 |  | 
|---|
| 135 | #define _ARG_DQUOTE   0x01          /* Argument quoted (")                  */ | 
|---|
| 136 | #define _ARG_RESPONSE 0x02          /* Argument read from response file     */ | 
|---|
| 137 | #define _ARG_WILDCARD 0x04          /* Argument expanded from wildcard      */ | 
|---|
| 138 | #define _ARG_ENV      0x08          /* Argument from environment            */ | 
|---|
| 139 | #define _ARG_NONZERO  0x80          /* Always set, to avoid end of string   */ | 
|---|
| 140 |  | 
|---|
| 141 | g_cArgs = 0; cbArgs = 0; | 
|---|
| 142 |  | 
|---|
| 143 | #if 0 | 
|---|
| 144 | /* argv[0] */ | 
|---|
| 145 | PUTC((char)_ARG_NONZERO); | 
|---|
| 146 | PUTV; | 
|---|
| 147 | for (;;) | 
|---|
| 148 | { | 
|---|
| 149 | PUTC(*pszSrc); | 
|---|
| 150 | if (*pszSrc == 0) | 
|---|
| 151 | break; | 
|---|
| 152 | ++pszSrc; | 
|---|
| 153 | } | 
|---|
| 154 | ++pszSrc; | 
|---|
| 155 | #endif | 
|---|
| 156 |  | 
|---|
| 157 | for (;;) | 
|---|
| 158 | { | 
|---|
| 159 | while (WHITE(*pszSrc)) | 
|---|
| 160 | ++pszSrc; | 
|---|
| 161 | if (*pszSrc == 0) | 
|---|
| 162 | break; | 
|---|
| 163 | pfFlags = pchPool; | 
|---|
| 164 | PUTC((char)_ARG_NONZERO); | 
|---|
| 165 | PUTV; | 
|---|
| 166 | bs = 0; chQuote = 0; | 
|---|
| 167 | for (;;) | 
|---|
| 168 | { | 
|---|
| 169 | if (!chQuote ? (*pszSrc == '"' || *pszSrc == '\'') : *pszSrc == chQuote) | 
|---|
| 170 | { | 
|---|
| 171 | while (bs >= 2) | 
|---|
| 172 | { | 
|---|
| 173 | PUTC('\\'); | 
|---|
| 174 | bs -= 2; | 
|---|
| 175 | } | 
|---|
| 176 | if (bs & 1) | 
|---|
| 177 | PUTC(*pszSrc); | 
|---|
| 178 | else | 
|---|
| 179 | { | 
|---|
| 180 | chQuote = chQuote ? 0 : *pszSrc; | 
|---|
| 181 | if (pfFlags != NULL) | 
|---|
| 182 | *pfFlags |= _ARG_DQUOTE; | 
|---|
| 183 | } | 
|---|
| 184 | bs = 0; | 
|---|
| 185 | } | 
|---|
| 186 | else if (*pszSrc == '\\') | 
|---|
| 187 | ++bs; | 
|---|
| 188 | else | 
|---|
| 189 | { | 
|---|
| 190 | while (bs != 0) | 
|---|
| 191 | { | 
|---|
| 192 | PUTC('\\'); | 
|---|
| 193 | --bs; | 
|---|
| 194 | } | 
|---|
| 195 | if (*pszSrc == 0 || (WHITE(*pszSrc) && !chQuote)) | 
|---|
| 196 | break; | 
|---|
| 197 | PUTC(*pszSrc); | 
|---|
| 198 | } | 
|---|
| 199 | ++pszSrc; | 
|---|
| 200 | } | 
|---|
| 201 | PUTC(0); | 
|---|
| 202 | } | 
|---|
| 203 | return cbArgs; | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|