summaryrefslogtreecommitdiffstats
path: root/private/crt32/startup/stdargv.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/startup/stdargv.c')
-rw-r--r--private/crt32/startup/stdargv.c501
1 files changed, 501 insertions, 0 deletions
diff --git a/private/crt32/startup/stdargv.c b/private/crt32/startup/stdargv.c
new file mode 100644
index 000000000..e75e98b77
--- /dev/null
+++ b/private/crt32/startup/stdargv.c
@@ -0,0 +1,501 @@
+/***
+*stdargv.c - standard & wildcard _setargv routine
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* processes program command line, with or without wildcard expansion
+*
+*Revision History:
+* 06-27-89 PHG module created, based on asm version
+* 04-09-90 GJF Added #include <cruntime.h>. Made calling types
+* explicit (_CALLTYPE1 or _CALLTYPE4). Also, fixed the
+* copyright.
+* 06-04-90 GJF Changed error message interface.
+* 08-31-90 GJF Removed 32 from API names.
+* 09-25-90 GJF Merged tree version with local version (8-31 change
+* with 6-4 change).
+* 10-08-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-25-91 SRW Include oscalls.h if _WIN32_ OR WILDCARD defined
+* 01-25-91 SRW Changed Win32 Process Startup [_WIN32_]
+* 01-25-91 MHL Fixed bug in Win32 Process Startup [_WIN32_]
+* 01-28-91 GJF Fixed call to DOSFINDFIRST (removed last arg).
+* 01-31-91 MHL Changed to call GetModuleFileName instead of NtCurrentPeb() [_WIN32_]
+* 02-18-91 SRW Fixed command line parsing bug [_WIN32_]
+* 03-11-91 GJF Fixed check of FindFirstFile return [_WIN32_].
+* 03-12-91 SRW Add FindClose call to _find [_WIN32_]
+* 04-16-91 SRW Fixed quote parsing logic for arguments.
+* 03-31-92 DJM POSIX support.
+* 05-12-92 DJM ifndefed for POSIX.
+* 06-02-92 SKS Add #include <dos.h> for CRTDLL definition of _pgmptr
+* 04-19-93 GJF Change test in the do-while loop in parse_cmdline to
+* NOT terminate on chars with high bit set.
+* 05-14-93 GJF Added support for quoted program names.
+* 05-28-93 KRS Added MBCS support under _MBCS switches.
+* 06-04-93 KRS Added more MBCS logic.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <internal.h>
+#include <rterr.h>
+#include <stdlib.h>
+#if defined(WILDCARD) || defined(_WIN32_)
+#include <dos.h>
+#include <oscalls.h>
+#endif
+#ifdef _MBCS
+#include <mbctype.h>
+#endif
+
+static void _CRTAPI3 parse_cmdline(char *cmdstart, char **argv, char *args,
+ int *numargs, int *numbytes);
+
+/***
+*_setargv, __setargv - set up "argc" and "argv" for C programs
+*
+*Purpose:
+* Read the command line and create the argv array for C
+* programs.
+*
+*Entry:
+* Arguments are retrieved from the program command line,
+* pointed to by _acmdln.
+*
+*Exit:
+* "argv" points to a null-terminated list of pointers to ASCIZ
+* strings, each of which is an argument from the command line.
+* "argc" is the number of arguments. The strings are copied from
+* the environment segment into space allocated on the heap/stack.
+* The list of pointers is also located on the heap or stack.
+* _pgmptr points to the program name.
+*
+*Exceptions:
+* Terminates with out of memory error if no memory to allocate.
+*
+*******************************************************************************/
+
+#ifdef WILDCARD
+void _CRTAPI1 __setargv (
+#else
+void _CRTAPI1 _setargv (
+#endif
+ void
+ )
+{
+ char *p;
+ char *cmdstart; /* start of command line to parse */
+ int numargs, numbytes;
+
+#ifdef _CRUISER_
+
+ /* OS/2 sets up memory like this:
+ <nul><full path of program><nul><prog name as typed><nul><arguments><nul>
+ ^
+ _acmdline
+ */
+
+ /* first we set _pgmptr to point to the full name of program */
+ p = _acmdln - 1;
+ while (*(p-1) != '\0')
+ --p;
+ _pgmptr = p;
+
+#else /* ndef _CRUISER_ */
+
+#if defined(_WIN32_)
+ static char _pgmname[ MAX_PATH ];
+
+ /* Get the program name pointer from Win32 Base */
+
+ GetModuleFileName( NULL, _pgmname, sizeof( _pgmname ));
+ _pgmptr = _pgmname;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* if there's no command line at all (won't happen from cmd.exe, but
+ possibly another program), then we use _pgmptr as the command line
+ to parse, so that argv[0] is initialized to the program name */
+ cmdstart = (*_acmdln == '\0') ? _pgmptr : _acmdln;
+
+ /* first find out how much space is needed to store args */
+ parse_cmdline(cmdstart, NULL, NULL, &numargs, &numbytes);
+
+ /* allocate space for argv[] vector and strings */
+ p = malloc(numargs * sizeof(char *) + numbytes);
+ if (p == NULL)
+ _amsg_exit(_RT_SPACEARG);
+
+ /* store args and argv ptrs in just allocated block */
+ parse_cmdline(cmdstart, (char **)p, p + numargs * sizeof(char *), &numargs, &numbytes);
+
+ /* set argv and argc */
+ __argc = numargs - 1;
+ __argv = (char **)p;
+#ifdef WILDCARD
+ /* call _cwild to expand wildcards in arg vector */
+ if (_cwild())
+ _amsg_exit(_RT_SPACEARG); /* out of space */
+#endif
+}
+
+
+/***
+*static void parse_cmdline(cmdstart, argv, args, numargs, numbytes)
+*
+*Purpose:
+* Parses the command line and sets up the argv[] array.
+* On entry, cmdstart should point to the command line,
+* argv should point to memory for the argv array, args
+* points to memory to place the text of the arguments.
+* If these are NULL, then no storing (only coujting)
+* is done. On exit, *numargs has the number of
+* arguments (plus one for a final NULL argument),
+* and *numbytes has the number of bytes used in the buffer
+* pointed to by args.
+*
+*Entry:
+* char *cmdstart - pointer to command line of the form
+* <progname><nul><args><nul>
+* char **argv - where to build argv array; NULL means don't
+* build array
+* char *args - where to place argument text; NULL means don't
+* store text
+*
+*Exit:
+* no return value
+* int *numargs - returns number of argv entries created
+* int *numbytes - number of bytes used in args buffer
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 parse_cmdline (
+ char *cmdstart,
+ char **argv,
+ char *args,
+ int *numargs,
+ int *numbytes
+ )
+{
+ char *p;
+ unsigned char c;
+ int inquote; /* 1 = inside quotes */
+ int copychar; /* 1 = copy char to *args */
+ unsigned numslash; /* num of backslashes seen */
+
+ *numbytes = 0;
+ *numargs = 1; /* the program name at least */
+
+ /* first scan the program name, copy it, and count the bytes */
+ p = cmdstart;
+ if (argv)
+ *argv++ = args;
+#ifdef WILDCARD
+ /* To handle later wild card expansion, we prefix each entry by
+ it's first character before quote handling. This is done
+ so _cwild() knows whether to expand an entry or not. */
+ if (args)
+ *args++ = *p;
+ ++*numbytes;
+
+#endif /* WILDCARD */
+ /* A quoted program name is handled here. The handling is much
+ simpler than for other arguments. Basically, whatever lies
+ between the leading double-quote and next one, or a terminal null
+ character is simply accepted. Fancier handling is not required
+ because the program name must be a legal NTFS/HPFS file name.
+ Note that the double-quote characters are not copied, nor do they
+ contribute to numbytes. */
+ if ( *p == '\"' ) {
+ /* scan from just past the first double-quote through the next
+ double-quote, or up to a null, whichever comes first */
+ while ( (*(++p) != '\"') && (*p != '\0') ) {
+
+#ifdef _MBCS
+ if (_ismbblead(*p)) {
+ *numbytes += 2;
+ if ( args ) {
+ *args++ = *p++;
+ *args++ = *p;
+ }
+ }
+ else {
+#endif
+ ++*numbytes;
+ if ( args )
+ *args++ = *p;
+#ifdef _MBCS
+ }
+#endif
+ }
+ /* append the terminating null */
+ ++*numbytes;
+ if ( args )
+ *args++ = '\0';
+
+ /* if we stopped on a double-quote (usual case), skip over it */
+ if ( *p == '\"' )
+ p++;
+ }
+ else {
+ /* Not a quoted program name */
+ do {
+ ++*numbytes;
+ if (args)
+ *args++ = *p;
+#ifdef _CRUISER_
+
+ } while (*p++ != '\0');
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ c = (unsigned char) *p++;
+#ifdef _MBCS
+ if (_ismbblead(c)) {
+ ++*numbytes;
+ if (args)
+ *args++ = *p; /* copy 2nd byte too */
+ p++; /* skip over trail byte */
+ }
+#endif
+
+ } while ( c > ' ' );
+
+ if ( c == '\0' ) {
+ p--;
+ } else {
+ if (args)
+ *(args-1) = '\0';
+ }
+ }
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ inquote = 0;
+
+ /* loop on each argument */
+ for(;;) {
+
+#ifdef _CRUISER_
+ /* skip blanks */
+ while (*p == ' ' || *p == '\t')
+ ++p;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ if ( *p ) {
+ while (*p == ' ' || *p == '\t')
+ ++p;
+ }
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (*p == '\0')
+ break; /* end of args */
+
+ /* scan an argument */
+ if (argv)
+ *argv++ = args; /* store ptr to arg */
+ ++*numargs;
+
+#ifdef WILDCARD
+ /* To handle later wild card expansion, we prefix each entry by
+ it's first character before quote handling. This is done
+ so _cwild() knows whether to expand an entry or not. */
+ if (args)
+ *args++ = *p;
+ ++*numbytes;
+
+#endif /* WILDCARD */
+
+ /* loop through scanning one argument */
+ for (;;) {
+ copychar = 1;
+ /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
+ 2N+1 backslashes + " ==> N backslashes + literal "
+ N backslashes ==> N backslashes */
+ numslash = 0;
+ while (*p == '\\') {
+ /* count number of backslashes for use below */
+ ++p;
+ ++numslash;
+ }
+ if (*p == '\"') {
+ /* if 2N backslashes before, start/end quote, otherwise
+ copy literally */
+ if (numslash % 2 == 0) {
+ if (inquote)
+ if (p[1] == '\"')
+ p++; /* Double quote inside quoted string */
+ else /* skip first quote char and copy second */
+ copychar = 0;
+ else
+ copychar = 0; /* don't copy quote */
+
+ inquote = !inquote;
+ }
+ numslash /= 2; /* divide numslash by two */
+ }
+
+ /* copy slashes */
+ while (numslash--) {
+ if (args)
+ *args++ = '\\';
+ ++*numbytes;
+ }
+
+ /* if at end of arg, break loop */
+ if (*p == '\0' || (!inquote && (*p == ' ' || *p == '\t')))
+ break;
+
+ /* copy character into argument */
+#ifdef _MBCS
+ if (copychar) {
+ if (args) {
+ if (_ismbblead(*p)) {
+ *args++ = *p++;
+ ++*numbytes;
+ }
+ *args++ = *p;
+ } else {
+ if (_ismbblead(*p)) {
+ ++p;
+ ++*numbytes;
+ }
+ }
+ ++*numbytes;
+ }
+ ++p;
+#else
+ if (copychar) {
+ if (args)
+ *args++ = *p;
+ ++*numbytes;
+ }
+ ++p;
+#endif
+ }
+
+ /* null-terminate the argument */
+
+ if (args)
+ *args++ = '\0'; /* terminate string */
+ ++*numbytes;
+ }
+
+ /* We put one last argument in -- a null ptr */
+ if (argv)
+ *argv++ = NULL;
+ ++*numargs;
+}
+
+
+#ifdef WILDCARD
+/***
+*_find(pattern) - find matching filename
+*
+*Purpose:
+* if argument is non-null, do a DOSFINDFIRST on that pattern
+* otherwise do a DOSFINDNEXT call. Return matching filename
+* or NULL if no more matches.
+*
+*Entry:
+* pattern = pointer to pattern or NULL
+* (NULL means find next matching filename)
+*
+*Exit:
+* returns pointer to matching file name
+* or NULL if no more matches.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 _find (
+ char *pattern
+ )
+{
+ char *retval;
+
+#ifdef _CRUISER_
+ static FILEFINDBUF findbuf;
+ HDIR findhandle = HDIR_SYSTEM;
+ ULONG findcount = 1;
+ int rc;
+
+ if (pattern)
+ rc = DOSFINDFIRST(pattern, &findhandle, FILE_NORMAL | FILE_DIRECTORY,
+ &findbuf, sizeof(findbuf), &findcount, 1L);
+ else
+ rc = DOSFINDNEXT(findhandle, &findbuf, sizeof(findbuf), &findcount);
+
+ retval = rc ? NULL : findbuf.achName;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ static HANDLE _WildFindHandle;
+ static LPWIN32_FIND_DATA findbuf;
+
+ if (pattern) {
+ if (findbuf == NULL)
+ findbuf = (LPWIN32_FIND_DATA)malloc(MAX_PATH + sizeof(*findbuf));
+
+ if (_WildFindHandle != NULL) {
+ (void)FindClose( _WildFindHandle );
+ _WildFindHandle = NULL;
+ }
+
+ _WildFindHandle = FindFirstFile( (LPSTR)pattern, findbuf );
+ if (_WildFindHandle == (HANDLE)0xffffffff)
+ return NULL;
+ }
+ else
+ if (!FindNextFile( _WildFindHandle, findbuf )) {
+ (void)FindClose( _WildFindHandle );
+ _WildFindHandle = NULL;
+ return NULL;
+ }
+
+ retval = findbuf->cFileName;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ return retval;
+}
+
+#endif /* WILDCARD */
+
+#endif /* ndef _POSIX_ */