source: trunk/src/lib/startuphacks-win.c@ 648

Last change on this file since 648 was 648, checked in by bird, 19 years ago

nicked commandline -> argv parser from kLIBC so kmk_sed can grok single quoted stuff on windows.

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