Blame | Last modification | View Log | RSS feed
/*Emulation of DOS startup code, using the following rules wheninterpreting arguments given on the operating system command line:Arguments are delimited by white space, which is either a spaceor a tab.A string surrounded by double quotation marks is interpreted asa single argument, regardless of white space contained within. Aquoted string can be embedded in an argument. Note that thecaret (^) is not recognized as an escape character or delimiter.A double quotation mark preceded by a backslash, \", isinterpreted as a literal double quotation mark (").Backslashes are interpreted literally, unless they immediatelyprecede a double quotation mark.If an even number of backslashes is followed by a doublequotation mark, then one backslash (\) is placed in the argvarray for every pair of backslashes (\\), and the doublequotation mark (") is interpreted as a string delimiter.If an odd number of backslashes is followed by a doublequotation mark, then one backslash (\) is placed in the argvarray for every pair of backslashes (\\) and the double quotationmark is interpreted as an escape sequence by the remainingbackslash, causing a literal double quotation mark (") tobe placed in argv.This list illustrates the rules above by showing the interpretedresult passed to argv for several examples of command-linearguments. The output listed in the second, third, and fourthcolumns is from the ARGS.C program that follows the list.Command-Line Input argv[1] argv[2] argv[3]"a b c" d e a b c d e"ab\"c" "\\" d ab"c \ da\\\b d"e f"g h a\\\b de fg ha\\\"b c d a\"b c da\\\\"b c" d e a\\b c d e*/#include <stdio.h>#include <stdlib.h>#include <tchar.h>#define NULCHAR '\0'#define NLCHAR '\n'#define CRCHAR '\r'#define SPACECHAR ' '#define TABCHAR '\t'#define DQUOTECHAR '\"'#define SLASHCHAR '\\'static void parse(const char *, const char *, char **, char *, int *, int *, int);/****_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.********************************************************************************/intparse_cmdbuffer(const char *arg0, const char *cmd, char ***__argv, int *__argc ){char *p;int numargs, numchars;int nls; /* 1 = contained line feeds *//* Are there line feeds, of so dont use SPACES or TABS asargument delimitors */nls = strchr(cmd, NLCHAR) ? 1 : 0;/* first find out how much space is needed to store args */parse(arg0, cmd, NULL, NULL, &numargs, &numchars, nls);/* allocate space for argv[] vector and strings */p = malloc(numargs * sizeof(char *) + numchars * sizeof(char));if (p == NULL)return -1; /* error *//* store args and argv ptrs in just allocated block */parse(arg0, cmd, (char **)p, p + numargs * sizeof(char *), &numargs, &numchars, nls);/* set argv and argc */*__argc = numargs - 1;*__argv = (char **)p;return *__argc;}/****static void parse_cmdline(cmdstart, argv, args, numargs, numchars)**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 *numchars 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 *numchars - number of characters used in args buffer**Exceptions:********************************************************************************/static voidparse( const char *arg0, const char *cmdstart,char **argv, char *args, int *numargs, int *numchars, int linefeeds ){const char *p;int inquote = 0; /* 1 = inside quotes */char quote_char;int copychar = 0; /* 1 = copy char to *args */unsigned numslash; /* num of backslashes seen *//* Handle arg0 */if (argv)*argv++ = (char *)arg0;*numargs = 1; /* the program name at least */*numchars = strlen(arg0)+1;/* Loop on each argument */for(p = cmdstart;;) {/* Eat (leading) white space */if ( *p ) {while (*p == SPACECHAR || *p == TABCHAR || *p == NLCHAR || *p == CRCHAR)++p;}if (*p == NULCHAR)break; /* end of args *//* scan an argument */if (argv)*argv++ = args; /* store ptr to arg */++*numargs;/* loop through scanning one argument */for (;;) {copychar = 1;/* Rules: 2N backslashes + " ==> N backslashes and begin/end quote2N+1 backslashes + " ==> N backslashes + literal "N backslashes ==> N backslashes */numslash = 0;while (*p == SLASHCHAR) {/* count number of backslashes for use below */++p;++numslash;}if (*p == DQUOTECHAR) {/* if 2N backslashes before, start/end quote, otherwisecopy literally */if (numslash % 2 == 0) {if (inquote) {if (p[1] == DQUOTECHAR)p++; /* Double quote inside quoted string */else /* skip first quote char and copy second */copychar = 0;} elsecopychar = 0; /* don't copy quote */inquote = !inquote;}numslash /= 2; /* divide numslash by two */}/* copy slashes */while (numslash--) {if (args)*args++ = SLASHCHAR;++*numchars;quote_char = SLASHCHAR;}/* if at end of arg, break loop */if (*p == NULCHAR || *p == NLCHAR || *p == CRCHAR ||(!inquote && !linefeeds &&(*p == SPACECHAR || *p == TABCHAR)))break;/* copy character into argument */if (copychar) {if (args)*args++ = *p;++*numchars;}++p;}/* Warnings */if (inquote) {fprintf(stderr, "%s: Unmatched quote argument (@%u).\n",arg0, (unsigned)(p - cmdstart)+1);}inquote = 0;/* null-terminate the argument */if (args)*args++ = NULCHAR; /* terminate string */++*numchars;}/* We put one last argument in -- a null ptr */if (argv)*argv++ = NULL;++*numargs;}