/*
* CRTglob.c
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
*
- * Include this object file to set _CRT_glob to a state that will
- * turn on command line globbing by default. NOTE: _CRT_glob has a default
- * state of on. Specify CRT_noglob.o to turn off globbing by default.
+ * This file is a part of the mingw-runtime package; it has no copyright
+ * assigned and is placed in the Public Domain. No warranty is given; refer
+ * to the file DISCLAIMER within the package.
*
- * To use this object include the object file in your link command:
- * gcc -o foo.exe foo.o CRTglob.o
+ * Link with this object file to set _CRT_glob to a state that will turn
+ * on command line globbing by default, preferring the MinGW algorithm to
+ * Microsoft's, but without enabling any of its additional features, as
+ * described in include/_mingw.h.
+ *
+ * NOTE: this file is linked by default, via libmingw32.a, if _CRT_glob
+ * is not defined elsewhere in explicitly linked object files. To turn
+ * globbing off, you may link explicitly with CRT_noglob.o, or you may
+ * define _CRT_glob with a value of zero, as a global variable in one of
+ * your own source files, (typically, the one which defines your main()
+ * function). To enable any of the additional globbing features described
+ * in include/_mingw.h, you should define _CRT_glob yourself, initializing
+ * it to the value formed by logical OR of __CRT_GLOB_USE_MINGW__ with the
+ * additional feature descriptors you wish to enable, while to select
+ * Microsoft's globbing algorithm in preference to MinGW's, you should
+ * initialize _CRT_glob = __CRT_glob = __CRT_GLOB_USE_MSVCRT__
*
*/
+#include <_mingw.h>
+
+int _CRT_glob = __CRT_GLOB_USE_MINGW__;
-int _CRT_glob = -1;
+/* $RCSfile$: end of file */
+2014-11-08 Keith Marshall <keithmarshall@users.sourceforge.net>
+
+ Implement new command line argument globbing strategy.
+
+ * include/_mingw.h: Backport feature defines from master...
+ (__CRT_GLOB_USE_MINGW__, __CRT_GLOB_USE_MSVCRT__): New manifest
+ constants; define them. They select the preferred globbing algorithm.
+ [_CRT_glob & __CRT_GLOB_USE_MINGW__] (__CRT_GLOB_USE_SINGLE_QUOTE__)
+ (__CRT_GLOB_BRACKET_GROUPS__, __CRT_GLOB_CASE_SENSITIVE__): New option
+ bit-map constants; define them. When added to __CRT_GLOB_USE_MINGW__,
+ they enable optional additional features supported by this algorithm.
+ (__CRT_GLOB_ESCAPE_CHAR__): New manifest constant; define it.
+
+ * CRTglob.c (_CRT_glob): Change default to __CRT_GLOB_USE_MINGW__.
+
+ * Makefile.in (libmingw32.a): Add setargv.$OBJEXT, furnished by...
+ * setargv.c: ...new file; it implements the initialization mechanism
+ for the __CRT_GLOB_USE_MINGW__ globbing algorithm, when invoked by...
+ (_setargv) [_CRT_glob & __CRT_GLOB_USE_MINGW__]: ...this new function;
+ it invokes the algorithm via an API similar to that described by MSDN,
+ while continuing to support our original _CRT_glob interpretation.
+ (_setargv) [! _CRT_glob & __CRT_GLOB_USE_MINGW__]: Invoke Microsoft
+ algorithm, via the MSDN-alike API, by calling back to...
+
+ * crt1.c (_mingw32_init_mainargs): ...this original function, now
+ relocated to here, as a publicly addressable function; formerly...
+ (__mingw_CRTStartup): ...called directly from here, we now redirect
+ the call through _setargv(), whence it may be called indirectly.
+
+ * init.c: Redundant file; delete it. It originally provided...
+ (_mingw32_init_mainargs): ...this, now relocated as noted above, with
+ original static attribute removed, to allow global addressing.
+
2014-11-07 Keith Marshall <keithmarshall@users.sourceforge.net>
Backport glob implementation from master to legacy.
$(CC) -C -E -P -D__FILENAME__=$@ -xc-header $< > $@
all-mingwrt-libs install-mingwrt-libs: libmingw32.a libmingwex.a
-libmingw32.a: $(addsuffix .$(OBJEXT), CRTinit CRTfmode CRTglob \
- cpu_features CRT_fp10 txtmode main dllmain gccmain crtst tlsmcrt \
- tlsmthread tlssup tlsthrd pseudo-reloc pseudo-reloc-list)
+libmingw32.a: $(addsuffix .$(OBJEXT), CRTinit CRTglob setargv \
+ CRTfmode cpu_features CRT_fp10 txtmode main dllmain gccmain crtst \
+ tlsmcrt tlsmthread tlssup tlsthrd pseudo-reloc pseudo-reloc-list)
libmingw32.a libmingwex.a libm.a libmingwthrd.a libgmon.a:
$(AR) $(ARFLAGS) $@ $?
*/
/* Hide the declaration of _fmode with dllimport attribute in stdlib.h to
- avoid problems with older GCC. */
+ * avoid problems with older GCC.
+ */
#define __IN_MINGW_RUNTIME
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <signal.h>
-/* NOTE: The code for initializing the _argv, _argc, and environ variables
- * has been moved to a separate .c file which is included in both
- * crt1.c and dllcrt1.c. This means changes in the code don't have to
- * be manually synchronized, but it does lead to this not-generally-
- * a-good-idea use of include. */
-#include "init.c"
#include "cpu_features.h"
extern void __main ();
extern void _pei386_runtime_relocator (void);
+/* Main program entry point, and argument initialization hook.
+ */
extern int main (int, char **, char **);
-/* TLS initialization hook. */
-extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
+int _argc = 0;
+char **_argv = NULL;
-/*
- * Must have the correct app type for MSVCRT.
+/* NOTE: Thanks to Pedro A. Aranda Gutiirrez <paag@tid.es> for pointing
+ * this out: the GetMainArgs() function, (provided by CRTDLL.DDL, as an
+ * argument initialization hook), takes a fourth argument (an int), which
+ * controls the globbing of the command line; if it is non-zero the command
+ * line will be globbed (e.g. *.* will be expanded to a list, separated by
+ * spaces, of all files in the startup directory).
+ *
+ * We determine how globbing should be performed, by inspection of the two
+ * least significant bits of the global int variable _CRT_glob, (defined in
+ * the mingw32 library, with a default value of 2). If this pair of bits
+ * represent a value of 2 or more, the new MinGW globbing algorithm, (as
+ * implemented by function _setargv() in setargv.c), will be applied; for
+ * values of one or zero, _setargv() will delegate the globbing function to
+ * the _mingw32_init_mainargs() callback function implemented below, and so
+ * invoking the Microsoft GetMainArgs() algorithm, with its fourth argument
+ * set to one or zero, to match the least significant bit of _CRT_glob.
+ *
+ * The mingw32 library default value of 2 for _CRT_glob enables command line
+ * globbing using the MinGW algorithm. If you prefer to adopt the Microsoft
+ * algorithm, you should define _CRT_glob as a global variable, by including
+ * a line in one of your own source code files, like this:
+ *
+ * int _CRT_glob = 1;
+ *
+ * Alternatively, if you prefer to disable globbing, and do all command line
+ * processing yourself, (and so evade possible bogons in the Microsoft or in
+ * the MinGW globbing code), include a similar line in one of your own source
+ * code files, defining _CRT_glob with a value of zero, like this:
+ *
+ * int _CRT_glob = 0;
+ */
+extern int _CRT_glob;
+
+#ifdef __MSVCRT__
+/* In MSVCRT.DLL, Microsoft's initialization hook is called __getmainargs(),
+ * and it expects a further structure argument, (which we don't use, but pass
+ * it as a dummy, with a declared size of zero in its first and only field).
*/
+typedef struct { int newmode; } _startupinfo;
+extern void __getmainargs( int *, char ***, char ***, int, _startupinfo * );
+#else
+/* In CRTDLL.DLL, the initialization hook is called __GetMainArgs().
+ */
+extern void __GetMainArgs( int *, char ***, char ***, int );
+#endif
+
+void _mingw32_init_mainargs()
+{
+ /* This is the old start-up mechanism, in which we use a start-up
+ * hook provided by Microsoft's runtime library to initialize the
+ * argument and environment vectors.
+ *
+ * Note that the preferred method for accessing the environment
+ * vector is via a direct pointer retrieved from the runtime DLL,
+ * using a system call declared in stdlib.h; thus, we don't need
+ * to preserve the pointer returned by the start-up hook, so we
+ * may simply capture it locally, and subsequently discard it.
+ */
+ char **dummy_envp;
+
+# define _CRT_GLOB_OPT _CRT_glob & __CRT_GLOB_USE_MSVCRT__
+# ifdef __MSVCRT__
+ /* The MSVCRT.DLL start-up hook requires this invocation
+ * protocol...
+ */
+ _startupinfo start_info = { 0 };
+ __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
+
+# else
+ /* ...while a somewhat simpler protocol is applicable, in
+ * the case of the CRTDLL.DLL version.
+ */
+ __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
+# endif
+}
+
+/* TLS initialization hook.
+ */
+extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
+
+/* Must have the correct app type for MSVCRT.
+ */
#ifdef __MSVCRT__
-#define __UNKNOWN_APP 0
-#define __CONSOLE_APP 1
-#define __GUI_APP 2
+# define __UNKNOWN_APP 0
+# define __CONSOLE_APP 1
+# define __GUI_APP 2
+
__MINGW_IMPORT void __set_app_type(int);
+
#endif /* __MSVCRT__ */
-/* Global _fmode for this .exe, not the one in msvcrt.dll,
- The default is set in txtmode.o in libmingw32.a */
-/* Override the dllimport'd declarations in stdlib.h */
+/* Global _fmode for this .exe, (not the one in msvcrt.dll).
+ *
+ * The default is set in txtmode.o in libmingw32.a
+ * Override the dllimport'd declarations in stdlib.h
+ */
#undef _fmode
extern int _fmode;
#ifdef __MSVCRT__
static void
_mingw32_init_fmode (void)
{
- /* Don't set the std file mode if the user hasn't set any value for it. */
+ /* Don't set the std file mode if the user hasn't set any value for it.
+ */
if (_CRT_fmode)
- {
- _fmode = _CRT_fmode;
-
- /*
- * This overrides the default file mode settings for stdin,
- * stdout and stderr. At first I thought you would have to
- * test with isatty, but it seems that the DOS console at
- * least is smart enough to handle _O_BINARY stdout and
- * still display correctly.
- */
- if (stdin)
- {
- _setmode (_fileno (stdin), _CRT_fmode);
- }
- if (stdout)
- {
- _setmode (_fileno (stdout), _CRT_fmode);
- }
- if (stderr)
- {
- _setmode (_fileno (stderr), _CRT_fmode);
- }
- }
-
- /* Now sync the dll _fmode to the one for this .exe. */
-#ifdef __MSVCRT__
+ {
+ _fmode = _CRT_fmode;
+
+ /* This overrides the default file mode settings for stdin,
+ * stdout and stderr. At first I thought you would have to
+ * test with isatty, but it seems that the DOS console at
+ * least is smart enough to handle _O_BINARY stdout and
+ * still display correctly.
+ */
+ if (stdin) _setmode (_fileno (stdin), _CRT_fmode);
+ if (stdout) _setmode (_fileno (stdout), _CRT_fmode);
+ if (stderr) _setmode (_fileno (stderr), _CRT_fmode);
+ }
+
+ /* Now sync the dll _fmode to the one for this .exe.
+ */
+# ifdef __MSVCRT__
*__p__fmode() = _fmode;
-#else
+# else
*_imp___fmode_dll = _fmode;
-#endif
+# endif
}
-/* This function will be called when a trap occurs. Thanks to Jacob
- Navia for his contribution. */
+/* This function will be called when a trap occurs. Thanks to
+ * Jacob Navia for this contribution.
+ */
static CALLBACK long
_gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
{
return action;
}
-/*
- * The function mainCRTStartup is the entry point for all console programs.
+/* The function mainCRTStartup is the entry point for all console programs.
*/
static void __MINGW_ATTRIB_NORETURN
__mingw_CRTStartup (void)
{
int nRet;
- /* Initialize TLS callback. */
+ /* Initialize TLS callback.
+ */
if (__dyn_tls_init_callback != NULL)
__dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
- /*
- * Set up the top-level exception handler so that signal handling
+ /* Set up the top-level exception handler so that signal handling
* works as expected. The mapping between ANSI/POSIX signals and
- * Win32 SE is not 1-to-1, so caveat emptore.
+ * Win32 SE is not 1-to-1, so caveat emptor.
*
*/
SetUnhandledExceptionFilter (_gnu_exception_handler);
- /*
- * Initialize floating point unit.
+ /* Initialize floating point unit.
*/
__cpu_features_init (); /* Do we have SSE, etc.*/
_fpreset (); /* Supplied by the runtime library. */
- /*
- * Set up __argc, __argv and _environ.
+ /* Set up __argc, __argv and _environ.
*/
- _mingw32_init_mainargs ();
+ _setargv ();
- /*
- * Sets the default file mode.
+ /* Sets the default file mode.
* If _CRT_fmode is set, also set mode for stdin, stdout
* and stderr, as well
* NOTE: DLLs don't do this because that would be rude!
*/
_mingw32_init_fmode ();
- /* Adust references to dllimported data that have non-zero offsets. */
+ /* Adust references to dllimported data that have non-zero offsets.
+ */
_pei386_runtime_relocator ();
/* Align the stack to 16 bytes for the sake of SSE ops in main
- or in functions inlined into main. */
+ * or in functions inlined into main.
+ */
asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
/* From libgcc.a, __main calls global class constructors via
which has its own __do_global_ctors. */
__main ();
- /*
- * Call the main function. If the user does not supply one
+ /* Call the main function. If the user does not supply one
* the one in the 'libmingw32.a' library will be linked in, and
* that one calls WinMain. See main.c in the 'lib' dir
* for more details.
*/
nRet = main (_argc, _argv, environ);
- /*
- * Perform exit processing for the C library. This means
+ /* Perform exit processing for the C library. This means
* flushing output and calling 'atexit' registered functions.
*/
_cexit ();
#endif
#endif
-/* These are defined by the user (or the compiler)
- to specify how identifiers are imported from a DLL.
-
- __DECLSPEC_SUPPORTED Defined if dllimport attribute is supported.
- __MINGW_IMPORT The attribute definition to specify imported
- variables/functions.
- _CRTIMP As above. For MS compatibility.
- __MINGW32_VERSION Runtime version.
- __MINGW32_MAJOR_VERSION Runtime major version.
- __MINGW32_MINOR_VERSION Runtime minor version.
- __MINGW32_BUILD_DATE Runtime build date.
-
- Macros to enable MinGW features which deviate from standard MSVC
- compatible behaviour; these may be specified directly in user code,
- activated implicitly, (e.g. by specifying _POSIX_C_SOURCE or such),
- or by inclusion in __MINGW_FEATURES__:
-
- __USE_MINGW_ANSI_STDIO Select a more ANSI C99 compatible
- implementation of printf() and friends.
+/* The following are defined by the user (or by the compiler), to specify how
+ * identifiers are imported from a DLL. All headers should include this first,
+ * and then use __DECLSPEC_SUPPORTED to choose between the old ``__imp__name''
+ * style or the __MINGW_IMPORT style for declarations.
+ *
+ * __DECLSPEC_SUPPORTED Defined if dllimport attribute is supported.
+ * __MINGW_IMPORT The attribute definition to specify imported
+ * variables/functions.
+ * _CRTIMP As above. For MS compatibility.
+ * __MINGW32_VERSION Runtime version.
+ * __MINGW32_MAJOR_VERSION Runtime major version.
+ * __MINGW32_MINOR_VERSION Runtime minor version.
+ * __MINGW32_BUILD_DATE Runtime build date.
+ *
+ * Macros to enable MinGW features which deviate from standard MSVC
+ * compatible behaviour; these may be specified directly in user code,
+ * activated implicitly, (e.g. by specifying _POSIX_C_SOURCE or such),
+ * or by inclusion in __MINGW_FEATURES__:
+ *
+ * __USE_MINGW_ANSI_STDIO Select a more ANSI C99 compatible
+ * implementation of printf() and friends.
+ *
+ * Other macros:
+ *
+ * __int64 define to be long long. Using a typedef
+ * doesn't work for "unsigned __int64"
+ *
+ *
+ * Manifest definitions for flags to control globbing of the command line
+ * during application start up, (before main() is called). The first pair,
+ * when assigned as bit flags within _CRT_glob, select the globbing algorithm
+ * to be used; (the MINGW algorithm overrides MSCVRT, if both are specified).
+ * Prior to mingwrt-3.21, only the MSVCRT option was supported; this choice
+ * may produce different results, depending on which particular version of
+ * MSVCRT.DLL is in use; (in recent versions, it seems to have become
+ * definitively broken, when globbing within double quotes).
+ */
+#define __CRT_GLOB_USE_MSVCRT__ 0x0001
- Other macros:
+/* From mingwrt-3.21 onward, this should be the preferred choice; it will
+ * produce consistent results, regardless of the MSVCRT.DLL version in use.
+ */
+#define __CRT_GLOB_USE_MINGW__ 0x0002
- __int64 define to be long long. Using a typedef
- doesn't work for "unsigned __int64"
+/* When the __CRT_GLOB_USE_MINGW__ flag is set, within _CRT_glob, the
+ * following additional options are also available; they are not enabled
+ * by default, but the user may elect to enable any combination of them,
+ * by setting _CRT_glob to the boolean sum (i.e. logical OR combination)
+ * of __CRT_GLOB_USE_MINGW__ and the desired options.
+ *
+ * __CRT_GLOB_USE_SINGLE_QUOTE__ allows use of single (apostrophe)
+ * quoting characters, analogously to
+ * POSIX usage, as an alternative to
+ * double quotes, for collection of
+ * arguments separated by white space
+ * into a single logical argument.
+ *
+ * __CRT_GLOB_BRACKET_GROUPS__ enable interpretation of bracketed
+ * character groups as POSIX compatible
+ * globbing patterns, matching any one
+ * character which is either included
+ * in, or excluded from the group.
+ *
+ * __CRT_GLOB_CASE_SENSITIVE__ enable case sensitive matching for
+ * globbing patterns; this is default
+ * behaviour for POSIX, but because of
+ * the case insensitive nature of the
+ * MS-Windows file system, it is more
+ * appropriate to use case insensitive
+ * globbing as the MinGW default.
+ *
+ */
+#define __CRT_GLOB_USE_SINGLE_QUOTE__ 0x0010
+#define __CRT_GLOB_BRACKET_GROUPS__ 0x0020
+#define __CRT_GLOB_CASE_SENSITIVE__ 0x0040
- All headers should include this first, and then use __DECLSPEC_SUPPORTED
- to choose between the old ``__imp__name'' style or __MINGW_IMPORT
- style declarations. */
+/* The MinGW globbing algorithm uses the ASCII DEL control code as a marker
+ * for globbing characters which were embedded within quoted arguments; (the
+ * quotes are stripped away BEFORE the argument is globbed; the globbing code
+ * treats the marked character as immutable, and strips out the DEL markers,
+ * before storing the resultant argument). The DEL code is mapped to this
+ * function here; DO NOT change it, without rebuilding the runtime.
+ */
+#define __CRT_GLOB_ESCAPE_CHAR__ (char)(127)
/* Manifest definitions identifying the flag bits, controlling activation
+++ /dev/null
-/*
- * init.c
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
- *
- * Code to initialize standard file handles and command line arguments.
- * This file is #included in both crt1.c and dllcrt1.c.
- *
- */
-
-/*
- * Access to a standard 'main'-like argument count and list. Also included
- * is a table of environment variables.
- */
-int _argc = 0;
-char **_argv = 0;
-
-/* NOTE: Thanks to Pedro A. Aranda Gutiirrez <paag@tid.es> for pointing
- * this out to me. GetMainArgs (used below) takes a fourth argument
- * which is an int that controls the globbing of the command line. If
- * _CRT_glob is non-zero the command line will be globbed (e.g. *.*
- * expanded to be all files in the startup directory). In the mingw32
- * library a _CRT_glob variable is defined as being -1, enabling
- * this command line globbing by default. To turn it off and do all
- * command line processing yourself (and possibly escape bogons in
- * MS's globbing code) include a line in one of your source modules
- * defining _CRT_glob and setting it to zero, like this:
- * int _CRT_glob = 0;
- */
-extern int _CRT_glob;
-
-#ifdef __MSVCRT__
-typedef struct {
- int newmode;
-} _startupinfo;
-extern void __getmainargs (int *, char ***, char ***, int, _startupinfo *);
-#else
-extern void __GetMainArgs (int *, char ***, char ***, int);
-#endif
-
-/*
- * Initialize the _argc, _argv and environ variables.
- */
-static void
-_mingw32_init_mainargs ()
-{
- /* The environ variable is provided directly in stdlib.h through
- * a dll function call. */
- char **dummy_environ;
-#ifdef __MSVCRT__
- _startupinfo start_info;
- start_info.newmode = 0;
-#endif
-
- /*
- * Microsoft's runtime provides a function for doing just that.
- */
-#ifdef __MSVCRT__
- (void) __getmainargs (&_argc, &_argv, &dummy_environ, _CRT_glob,
- &start_info);
-#else
- /* CRTDLL version */
- (void) __GetMainArgs (&_argc, &_argv, &dummy_environ, _CRT_glob);
-#endif
-}
-
--- /dev/null
+/*
+ * setargv.c
+ *
+ * Implements runtime initialization code to populate the argument
+ * vector, which will subsequently be passed to the main() function;
+ * provides a _setargv() hook, similar to that described on MSDN.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2014, MinGW.org Project
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ */
+#include <glob.h>
+#include <string.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/* Access to a standard 'main'-like argument count and list.
+ */
+extern int _argc;
+extern char ** _argv;
+extern int _CRT_glob;
+
+#define ARGV_INLINE static __inline__ __attribute__((__always_inline__))
+
+#define ARGV_ESCAPE __CRT_GLOB_ESCAPE_CHAR__
+#define ARGV_SQUOTE __CRT_GLOB_USE_SINGLE_QUOTE__
+#define ARGV_NOGROUP __CRT_GLOB_BRACKET_GROUPS__
+
+ARGV_INLINE
+char *backslash( int count, char *buf )
+{
+ /* Helper used by the MinGW replacement command line globbing handler,
+ * to provide appropriate handling of backslashes while preparing the
+ * command line arguments for globbing.
+ */
+ while( count-- )
+ *buf++ = '\\';
+ return buf;
+}
+
+ARGV_INLINE
+char *unquote( int quote, int altquote, int escape, int *state, char *buf )
+{
+ /* Helper used by the MinGW replacement command line globbing handler,
+ * to provide a single level of reduction for balanced quotation marks,
+ * while preparing the command line arguments for globbing.
+ */
+ buf = backslash( escape >> 1, buf );
+ if( (escape & 1) || (*state == altquote) )
+ /*
+ * In this case, the quotation mark is to be interpreted as a literal,
+ * and is NOT a candidate for reduction...
+ */
+ *buf++ = quote;
+ else
+ /* ...while this is the more usual case, of a quotation mark used to
+ * delimit a single argument; it must be reduced.
+ */
+ *state ^= quote;
+ return buf;
+}
+
+ARGV_INLINE
+void __mingw32_setargv( const char *cmdline )
+{
+ /* Implementation of the MinGW replacement command line interpreter.
+ */
+ char cmdbuf[1 + strlen( cmdline ) << 1];
+ int c, gotarg = 0, quoted = 0, bracket = 0, bslash = 0;
+ char *argptr = cmdbuf; const char *cmdptr = cmdline;
+ glob_t gl_argv;
+
+ /* Capture any non-default globbing options, which the user may have
+ * specified via a custom setting for _CRT_glob.
+ */
+ int gl_opts = GLOB_NOCHECK;
+ if( _CRT_glob & __CRT_GLOB_CASE_SENSITIVE__ )
+ gl_opts |= GLOB_CASEMATCH;
+
+ /* We explicitly DO NOT use the GLOB_DOOFFS capability; ensure that
+ * the associated field, in the glob_t structure, is initialized to
+ * correctly reflect this.
+ */
+ gl_argv.gl_offs = 0;
+
+ /* Scan the command line, and prepare it for globbing.
+ */
+ while( c = *cmdptr++ )
+ {
+ /* Got a character to process...
+ */
+ switch( c )
+ {
+ /* Specific characters, which serve as globbing tokens,
+ * need special handling.
+ */
+ case '\\':
+ /* We don't (yet) know if this is a literal backslash,
+ * (directory separator), or an escape for a following
+ * quote character; just note its presence, until we
+ * have looked far enough ahead to decide.
+ */
+ ++bslash;
+ break;
+
+ case '[':
+ /* POSIX defines this as a globbing token, (introducing
+ * a character group); we don't support this by default,
+ * so defeat it, unless the extended behaviour has been
+ * requested by the user.
+ */
+ bracket = (_CRT_glob & ARGV_NOGROUP) ? 0 : ARGV_NOGROUP;
+
+ case '*':
+ case '?':
+ /* These standard globbing tokens...
+ */
+ case ARGV_ESCAPE:
+ /* ...and the escape character itself, need to be escaped
+ * when they appear in any context in which they should be
+ * interpreted literally, rather than globbed.
+ */
+ argptr = backslash( bslash, argptr );
+ if( quoted || (bracket == ARGV_NOGROUP) || (c == ARGV_ESCAPE) )
+ *argptr++ = ARGV_ESCAPE;
+ bracket = bslash = 0;
+ *argptr++ = c;
+ break;
+
+ case '"':
+ /* The double quote always acts as an argument quoting
+ * character, (unless escaped); handle it accordingly.
+ */
+ argptr = unquote( c, '\'', bslash, "ed, argptr );
+ gotarg = 1; bslash = 0;
+ break;
+
+ case '\'':
+ /* POSIX also defines the single quote as a quoting
+ * character, but MS-Windows does not; we offer this
+ * extended handling...
+ */
+ if( _CRT_glob & ARGV_SQUOTE )
+ {
+ /* ...only when the user has explicitly enabled the
+ * POSIX compatible extended quoting option.
+ */
+ argptr = unquote( c, '"', bslash, "ed, argptr );
+ gotarg = 1; bslash = 0;
+ break;
+ }
+
+ default:
+ /* With one exception, any other character is handled
+ * literally, after flushing out any pending backslashes.
+ */
+ argptr = backslash( bslash, argptr );
+ if( (quoted == 0) && isspace( c ) )
+ {
+ /* The one exception is any white space character,
+ * when it is not contained within quotes; this acts
+ * as an argument separator, (or is simply discarded
+ * if there is no argument already collected)...
+ */
+ if( gotarg || (argptr > cmdbuf) )
+ {
+ /* ...so, when there is a argument pending, we may
+ * now add it to the globbed argument vector.
+ */
+ *argptr = '\0';
+ __mingw_glob( argptr = cmdbuf, gl_opts, NULL, &gl_argv );
+ gl_opts |= GLOB_APPEND;
+ gotarg = 0;
+ }
+ }
+ else
+ /* In every other case, we simply collect the current
+ * literal character into the next pending argument.
+ */
+ *argptr++ = c;
+
+ /* Irrespective of how we handled the current character,
+ * we can be certain that there are no pending backslashes
+ * by the time we get to here.
+ */
+ bslash = 0;
+ }
+ }
+ /* Finally, when we've run out of command line characters to process,
+ * flush out any final pending backslashes, ...
+ */
+ argptr = backslash( bslash, argptr );
+ if( gotarg || (argptr > cmdbuf) )
+ {
+ /* ...and add any final pending argument to the globbed vector.
+ */
+ *argptr = '\0';
+ __mingw_glob( argptr = cmdbuf, gl_opts, NULL, &gl_argv );
+ }
+ /* ...and store the resultant globbed vector into the "argc" and "argv"
+ * variables to be passed to main(); note that this allows us to safely
+ * discard our working glob_t structure, but we MUST NOT globfree() it,
+ * as that would destroy the content of "argv".
+ */
+ _argc = gl_argv.gl_pathc;
+ _argv = gl_argv.gl_pathv;
+}
+
+extern void _mingw32_init_mainargs( void );
+
+void _setargv()
+{
+ /* Initialize the _argc, _argv and environ variables.
+ */
+ if( (_CRT_glob & __CRT_GLOB_USE_MINGW__) == 0 )
+ {
+ /* This is the old start-up mechanism, implemented via a callback
+ * into the CRT initialization module, in which we use a start-up
+ * hook provided by Microsoft's runtime library to initialize the
+ * argument and environment vectors.
+ */
+ _mingw32_init_mainargs();
+ }
+ else
+ { /* Here, we implement a new, more POSIX compatible mechanism,
+ * for initializing the argument vector; note that we delegate
+ * to the previously defined inline function, which avoids the
+ * broken globbing behaviour of some more recent versions of
+ * MSVCRT.DLL
+ */
+ __mingw32_setargv( GetCommandLine() );
+ }
+}
+
+/* $RCSfile$: end of file */