stdargv.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 12k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /***
  2. *stdargv.c - standard & wildcard _setargv routine
  3. *
  4. *    Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *    processes program command line, with or without wildcard expansion
  8. *
  9. *******************************************************************************/
  10. #ifdef _MBCS
  11. #undef _MBCS
  12. #endif
  13. #ifndef _POSIX_
  14. #include <cruntime.h>
  15. #include <internal.h>
  16. #include <rterr.h>
  17. #include <stdlib.h>
  18. #if defined(WILDCARD) || defined(_WIN32)
  19. #include <dos.h>
  20. #include <oscalls.h>
  21. #endif
  22. #include <tchar.h>
  23. // #include <dbgint.h>
  24. #define NULCHAR    _T('')
  25. #define SPACECHAR  _T(' ')
  26. #define TABCHAR    _T('t')
  27. #define DQUOTECHAR _T('"')
  28. #define SLASHCHAR  _T('\')
  29. #ifdef WPRFLAG
  30. static void __cdecl wparse_cmdline(wchar_t *cmdstart, wchar_t **argv, wchar_t *args,
  31.     int *numargs, int *numchars);
  32. #else
  33. static void __cdecl parse_cmdline(char *cmdstart, char **argv, char *args,
  34.     int *numargs, int *numchars);
  35. #endif
  36. /***
  37. *_setargv, __setargv - set up "argc" and "argv" for C programs
  38. *
  39. *Purpose:
  40. *    Read the command line and create the argv array for C
  41. *    programs.
  42. *
  43. *Entry:
  44. *    Arguments are retrieved from the program command line,
  45. *    pointed to by _acmdln.
  46. *
  47. *Exit:
  48. *    "argv" points to a null-terminated list of pointers to ASCIZ
  49. *    strings, each of which is an argument from the command line.
  50. *    "argc" is the number of arguments.  The strings are copied from
  51. *    the environment segment into space allocated on the heap/stack.
  52. *    The list of pointers is also located on the heap or stack.
  53. *    _pgmptr points to the program name.
  54. *
  55. *Exceptions:
  56. *    Terminates with out of memory error if no memory to allocate.
  57. *
  58. *******************************************************************************/
  59. #ifdef WILDCARD
  60. #ifdef WPRFLAG
  61. void __cdecl __wsetargv (
  62. #else
  63. void __cdecl __setargv (
  64. #endif /* WPRFLAG */
  65. #else /* WILDCARD */
  66. #ifdef WPRFLAG
  67. void __cdecl _wsetargv (
  68. #else
  69. void __cdecl _setargv (
  70. #endif /* WPRFLAG */
  71. #endif /* WILDCARD */
  72.     void
  73.     )
  74. {
  75.         _TSCHAR *p;
  76.         _TSCHAR *cmdstart;            /* start of command line to parse */
  77.     int numargs, numchars;
  78. #ifdef    DLL_FOR_WIN32S
  79.     #define _pgmname    (_GetPPD()->_ppd__pgmname)
  80. #else    /* ndef DLL_FOR_WIN32S */
  81.     static _TSCHAR _pgmname[ MAX_PATH ];
  82. #endif    /* DLL_FOR_WIN32S */
  83.         /* Get the program name pointer from Win32 Base */
  84.         GetModuleFileName( NULL, _pgmname, sizeof( _pgmname ) / sizeof(_TSCHAR));
  85. #ifdef WPRFLAG
  86.         _wpgmptr = _pgmname;
  87. #else
  88.         _pgmptr = _pgmname;
  89. #endif
  90.         /* if there's no command line at all (won't happen from cmd.exe, but
  91.            possibly another program), then we use _pgmptr as the command line
  92.            to parse, so that argv[0] is initialized to the program name */
  93. #ifdef WPRFLAG
  94.         cmdstart = (*_wcmdln == NULCHAR) ? _wpgmptr : _wcmdln;
  95. #else
  96.         cmdstart = (*_acmdln == NULCHAR) ? _pgmptr : _acmdln;
  97. #endif
  98.         /* first find out how much space is needed to store args */
  99. #ifdef WPRFLAG
  100.         wparse_cmdline(cmdstart, NULL, NULL, &numargs, &numchars);
  101. #else
  102.         parse_cmdline(cmdstart, NULL, NULL, &numargs, &numchars);
  103. #endif
  104.         /* allocate space for argv[] vector and strings */
  105.         p = malloc(numargs * sizeof(_TSCHAR *) + numchars * sizeof(_TSCHAR));
  106.         if (p == NULL)
  107.             _amsg_exit(_RT_SPACEARG);
  108.         /* store args and argv ptrs in just allocated block */
  109. #ifdef WPRFLAG
  110.         wparse_cmdline(cmdstart, (wchar_t **)p, (wchar_t *)(((char *)p) + numargs * sizeof(wchar_t *)), &numargs, &numchars);
  111. #else
  112.         parse_cmdline(cmdstart, (char **)p, p + numargs * sizeof(char *), &numargs, &numchars);
  113. #endif
  114.         /* set argv and argc */
  115.         __argc = numargs - 1;
  116. #ifdef WPRFLAG
  117.         __wargv = (wchar_t **)p;
  118. #else
  119.         __argv = (char **)p;
  120. #endif /* WPRFLAG */
  121. #ifdef WILDCARD
  122.         /* call _[w]cwild to expand wildcards in arg vector */
  123. #ifdef WPRFLAG
  124.         if (_wcwild())
  125. #else /* WPRFLAG */
  126.         if (_cwild())
  127. #endif /* WPRFLAG */
  128.         _amsg_exit(_RT_SPACEARG);    /* out of space */
  129. #endif /* WILDCARD */
  130. }
  131. /***
  132. *static void parse_cmdline(cmdstart, argv, args, numargs, numchars)
  133. *
  134. *Purpose:
  135. *    Parses the command line and sets up the argv[] array.
  136. *    On entry, cmdstart should point to the command line,
  137. *    argv should point to memory for the argv array, args
  138. *    points to memory to place the text of the arguments.
  139. *    If these are NULL, then no storing (only coujting)
  140. *    is done.  On exit, *numargs has the number of
  141. *    arguments (plus one for a final NULL argument),
  142. *    and *numchars has the number of bytes used in the buffer
  143. *    pointed to by args.
  144. *
  145. *Entry:
  146. *    _TSCHAR *cmdstart - pointer to command line of the form
  147. *        <progname><nul><args><nul>
  148. *    _TSCHAR **argv - where to build argv array; NULL means don't
  149. *            build array
  150. *    _TSCHAR *args - where to place argument text; NULL means don't
  151. *            store text
  152. *
  153. *Exit:
  154. *    no return value
  155. *    int *numargs - returns number of argv entries created
  156. *    int *numchars - number of characters used in args buffer
  157. *
  158. *Exceptions:
  159. *
  160. *******************************************************************************/
  161. #ifdef WPRFLAG
  162. static void __cdecl wparse_cmdline (
  163. #else
  164. static void __cdecl parse_cmdline (
  165. #endif
  166.     _TSCHAR *cmdstart,
  167.     _TSCHAR **argv,
  168.     _TSCHAR *args,
  169.     int *numargs,
  170.     int *numchars
  171.     )
  172. {
  173.         _TSCHAR *p;
  174.         _TUCHAR c;
  175.         int inquote;            /* 1 = inside quotes */
  176.         int copychar;            /* 1 = copy char to *args */
  177.         unsigned numslash;            /* num of backslashes seen */
  178.         *numchars = 0;
  179.         *numargs = 1;        /* the program name at least */
  180.         /* first scan the program name, copy it, and count the bytes */
  181.         p = cmdstart;
  182.         if (argv)
  183.             *argv++ = args;
  184. #ifdef WILDCARD
  185.         /* To handle later wild card expansion, we prefix each entry by
  186.         it's first character before quote handling.  This is done
  187.         so _[w]cwild() knows whether to expand an entry or not. */
  188.         if (args)
  189.             *args++ = *p;
  190.         ++*numchars;
  191. #endif    /* WILDCARD */
  192.         /* A quoted program name is handled here. The handling is much
  193.            simpler than for other arguments. Basically, whatever lies
  194.            between the leading double-quote and next one, or a terminal null
  195.            character is simply accepted. Fancier handling is not required
  196.            because the program name must be a legal NTFS/HPFS file name.
  197.            Note that the double-quote characters are not copied, nor do they
  198.            contribute to numchars. */
  199.         if ( *p == DQUOTECHAR ) {
  200.             /* scan from just past the first double-quote through the next
  201.                double-quote, or up to a null, whichever comes first */
  202.             while ( (*(++p) != DQUOTECHAR) && (*p != NULCHAR) ) {
  203. #ifdef _MBCS
  204.                 if (_ismbblead(*p)) {
  205.                     ++*numchars;
  206.                     if ( args )
  207.                         *args++ = *p++;
  208.                 }
  209. #endif
  210.                 ++*numchars;
  211.                 if ( args )
  212.                     *args++ = *p;
  213.             }
  214.             /* append the terminating null */
  215.             ++*numchars;
  216.             if ( args )
  217.                 *args++ = NULCHAR;
  218.             /* if we stopped on a double-quote (usual case), skip over it */
  219.             if ( *p == DQUOTECHAR )
  220.                 p++;
  221.         }
  222.         else {
  223.             /* Not a quoted program name */
  224.             do {
  225.                 ++*numchars;
  226.                 if (args)
  227.                     *args++ = *p;
  228.                 c = (_TUCHAR) *p++;
  229. #ifdef _MBCS
  230.                 if (_ismbblead(c)) {
  231.                     ++*numchars;
  232.                     if (args)
  233.                         *args++ = *p;    /* copy 2nd byte too */
  234.                     p++;  /* skip over trail byte */
  235.                 }
  236. #endif
  237.             } while ( c != SPACECHAR && c != NULCHAR && c != TABCHAR );
  238.             if ( c == NULCHAR ) {
  239.                 p--;
  240.             } else {
  241.                 if (args)
  242.                     *(args-1) = NULCHAR;
  243.             }
  244.         }
  245.         inquote = 0;
  246.         /* loop on each argument */
  247.         for(;;) {
  248.             if ( *p ) {
  249.                 while (*p == SPACECHAR || *p == TABCHAR)
  250.                     ++p;
  251.             }
  252.             if (*p == NULCHAR)
  253.                 break;            /* end of args */
  254.             /* scan an argument */
  255.             if (argv)
  256.                 *argv++ = args;        /* store ptr to arg */
  257.             ++*numargs;
  258. #ifdef WILDCARD
  259.         /* To handle later wild card expansion, we prefix each entry by
  260.         it's first character before quote handling.  This is done
  261.         so _[w]cwild() knows whether to expand an entry or not. */
  262.         if (args)
  263.             *args++ = *p;
  264.         ++*numchars;
  265. #endif    /* WILDCARD */
  266.         /* loop through scanning one argument */
  267.         for (;;) {
  268.             copychar = 1;
  269.             /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
  270.                2N+1 backslashes + " ==> N backslashes + literal "
  271.                N backslashes ==> N backslashes */
  272.             numslash = 0;
  273.             while (*p == SLASHCHAR) {
  274.                 /* count number of backslashes for use below */
  275.                 ++p;
  276.                 ++numslash;
  277.             }
  278.             if (*p == DQUOTECHAR) {
  279.                 /* if 2N backslashes before, start/end quote, otherwise
  280.                     copy literally */
  281.                 if (numslash % 2 == 0) {
  282.                     if (inquote) {
  283.                         if (p[1] == DQUOTECHAR)
  284.                             p++;    /* Double quote inside quoted string */
  285.                         else        /* skip first quote char and copy second */
  286.                             copychar = 0;
  287.                     } else
  288.                         copychar = 0;       /* don't copy quote */
  289.                     inquote = !inquote;
  290.                 }
  291.                 numslash /= 2;        /* divide numslash by two */
  292.             }
  293.             /* copy slashes */
  294.             while (numslash--) {
  295.                 if (args)
  296.                     *args++ = SLASHCHAR;
  297.                 ++*numchars;
  298.             }
  299.             /* if at end of arg, break loop */
  300.             if (*p == NULCHAR || (!inquote && (*p == SPACECHAR || *p == TABCHAR)))
  301.                 break;
  302.             /* copy character into argument */
  303. #ifdef _MBCS
  304.             if (copychar) {
  305.                 if (args) {
  306.                     if (_ismbblead(*p)) {
  307.                         *args++ = *p++;
  308.                         ++*numchars;
  309.                     }
  310.                     *args++ = *p;
  311.                 } else {
  312.                     if (_ismbblead(*p)) {
  313.                         ++p;
  314.                         ++*numchars;
  315.                     }
  316.                 }   
  317.                 ++*numchars;
  318.             }
  319.             ++p;
  320. #else 
  321.             if (copychar) {
  322.                 if (args)
  323.                     *args++ = *p;
  324.                 ++*numchars;
  325.             }
  326.             ++p;
  327. #endif 
  328.         }
  329.             /* null-terminate the argument */
  330.             if (args)
  331.                 *args++ = NULCHAR;        /* terminate string */
  332.             ++*numchars;
  333.         }
  334.         /* We put one last argument in -- a null ptr */
  335.         if (argv)
  336.             *argv++ = NULL;
  337.         ++*numargs;
  338. }
  339. #endif /* ndef _POSIX_ */