4 * Implements runtime initialization code to populate the argument
5 * vector, which will subsequently be passed to the main() function;
6 * provides a _setargv() hook, similar to that described on MSDN.
10 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
11 * Copyright (C) 2014, 2017, MinGW.org Project
13 * ---------------------------------------------------------------------------
15 * Permission is hereby granted, free of charge, to any person obtaining a
16 * copy of this software and associated documentation files (the "Software"),
17 * to deal in the Software without restriction, including without limitation
18 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19 * and/or sell copies of the Software, and to permit persons to whom the
20 * Software is furnished to do so, subject to the following conditions:
22 * The above copyright notice and this permission notice shall be included
23 * in all copies or substantial portions of the Software.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 * DEALINGS IN THE SOFTWARE.
33 * ---------------------------------------------------------------------------
36 #define _ISOC99_SOURCE
42 #define WIN32_LEAN_AND_MEAN
45 /* Access to a standard 'main'-like argument count and list.
51 #define ARGV_INLINE static __inline__ __attribute__((__always_inline__))
53 #define ARGV_ESCAPE __CRT_GLOB_ESCAPE_CHAR__
54 #define ARGV_SQUOTE __CRT_GLOB_USE_SINGLE_QUOTE__
55 #define ARGV_NOGROUP __CRT_GLOB_BRACKET_GROUPS__
58 char *backslash( int count, char *buf )
60 /* Helper used by the MinGW replacement command line globbing handler,
61 * to provide appropriate handling of backslashes while preparing the
62 * command line arguments for globbing.
70 char *unquote( int quote, int altquote, int escape, int *state, char *buf )
72 /* Helper used by the MinGW replacement command line globbing handler,
73 * to provide a single level of reduction for balanced quotation marks,
74 * while preparing the command line arguments for globbing.
76 buf = backslash( escape >> 1, buf );
77 if( (escape & 1) || (*state == altquote) )
79 * In this case, the quotation mark is to be interpreted as a literal,
80 * and is NOT a candidate for reduction...
84 /* ...while this is the more usual case, of a quotation mark used to
85 * delimit a single argument; it must be reduced.
92 void __mingw32_setargv( const char *cmdline )
94 /* Implementation of the MinGW replacement command line interpreter.
96 char cmdbuf[1 + strlen( cmdline ) << 1];
97 int c, gotarg = 0, quoted = 0, bracket = 0, bslash = 0;
98 char *argptr = cmdbuf; const char *cmdptr = cmdline;
101 /* Capture any non-default globbing options, which the user may have
102 * specified via a custom setting for _CRT_glob.
104 int gl_opts = GLOB_NOCHECK | (_CRT_glob & (GLOB_CASEMATCH | GLOB_BRACE));
106 /* We explicitly DO NOT use the GLOB_DOOFFS capability; ensure that
107 * the associated field, in the glob_t structure, is initialized to
108 * correctly reflect this.
112 /* Scan the command line, and prepare it for globbing.
114 while( c = *cmdptr++ )
116 /* Got a character to process...
120 /* Specific characters, which serve as globbing tokens,
121 * need special handling.
125 /* Backslashes within single quotes are always literal.
130 /* We don't (yet) know if this is a literal backslash,
131 * (directory separator), or an escape for a following
132 * quote character; just note its presence, until we
133 * have looked far enough ahead to decide.
139 /* POSIX defines this as a globbing token, (introducing
140 * a character group); we don't support this by default,
141 * so defeat it, unless the extended behaviour has been
142 * requested by the user.
144 bracket = (_CRT_glob & ARGV_NOGROUP) ? 0 : ARGV_NOGROUP;
148 /* These standard globbing tokens...
151 /* ...and the escape character itself, need to be escaped
152 * when they appear in any context in which they should be
153 * interpreted literally, rather than globbed.
155 argptr = backslash( bslash, argptr );
156 if( quoted || (bracket == ARGV_NOGROUP) || (c == ARGV_ESCAPE) )
157 *argptr++ = ARGV_ESCAPE;
158 bracket = bslash = 0;
163 /* The double quote always acts as an argument quoting
164 * character, (unless escaped); handle it accordingly.
166 argptr = unquote( c, '\'', bslash, "ed, argptr );
167 gotarg = 1; bslash = 0;
171 /* POSIX also defines the single quote as a quoting
172 * character, but MS-Windows does not; we offer this
173 * extended handling...
175 if( _CRT_glob & ARGV_SQUOTE )
177 /* ...only when the user has explicitly enabled the
178 * POSIX compatible extended quoting option.
180 argptr = unquote( c, '"', bslash, "ed, argptr );
181 gotarg = 1; bslash = 0;
186 /* With one exception, any other character is handled
187 * literally, after flushing out any pending backslashes.
189 argptr = backslash( bslash, argptr );
190 if( (quoted == 0) && isblank( c ) )
192 /* The one exception is any blank or tab character,
193 * when it is not contained within quotes; this acts
194 * as an argument separator, (or is simply discarded
195 * if there is no argument already collected)...
197 if( gotarg || (argptr > cmdbuf) )
199 /* ...so, when there is a argument pending, we may
200 * now add it to the globbed argument vector.
203 __mingw_glob( argptr = cmdbuf, gl_opts, NULL, &gl_argv );
204 gl_opts |= GLOB_APPEND;
209 /* In every other case, we simply collect the current
210 * literal character into the next pending argument.
214 /* Irrespective of how we handled the current character,
215 * we can be certain that there are no pending backslashes
216 * by the time we get to here.
221 /* Finally, when we've run out of command line characters to process,
222 * flush out any final pending backslashes, ...
224 argptr = backslash( bslash, argptr );
225 if( gotarg || (argptr > cmdbuf) )
227 /* ...and add any final pending argument to the globbed vector.
230 __mingw_glob( argptr = cmdbuf, gl_opts, NULL, &gl_argv );
232 /* ...and store the resultant globbed vector into the "argc" and "argv"
233 * variables to be passed to main(); note that this allows us to safely
234 * discard our working glob_t structure, but we MUST NOT globfree() it,
235 * as that would destroy the content of "argv".
237 _argc = gl_argv.gl_pathc;
238 _argv = gl_argv.gl_pathv;
241 extern void _mingw32_init_mainargs( void );
245 /* Initialize the _argc, _argv and environ variables.
247 if( (_CRT_glob & __CRT_GLOB_USE_MINGW__) == 0 )
249 /* This is the old start-up mechanism, implemented via a callback
250 * into the CRT initialization module, in which we use a start-up
251 * hook provided by Microsoft's runtime library to initialize the
252 * argument and environment vectors.
254 _mingw32_init_mainargs();
257 { /* Here, we implement a new, more POSIX compatible mechanism,
258 * for initializing the argument vector; note that we delegate
259 * to the previously defined inline function, which avoids the
260 * broken globbing behaviour of some more recent versions of
263 __mingw32_setargv( GetCommandLine() );
267 /* $RCSfile$: end of file */