Posted to tcl by jdc at Sat Mar 24 16:21:41 GMT 2007view raw

  1. /*
  2. *-------------------------------------------------------------------------
  3. *
  4. * setargv --
  5. *
  6. * Parse the Windows command line string into argc/argv. Done here
  7. * because we don't trust the builtin argument parser in crt0.
  8. * Windows applications are responsible for breaking their command
  9. * line into arguments.
  10. *
  11. * 2N backslashes + quote -> N backslashes + begin quoted string
  12. * 2N + 1 backslashes + quote -> literal
  13. * N backslashes + non-quote -> literal
  14. * quote + quote in a quoted string -> single quote
  15. * quote + quote not in quoted string -> empty string
  16. * quote -> begin quoted string
  17. *
  18. * Results:
  19. * Fills argcPtr with the number of arguments and argvPtr with the
  20. * array of arguments.
  21. *
  22. * Side effects:
  23. * Memory allocated.
  24. *
  25. *--------------------------------------------------------------------------
  26. */
  27.  
  28. static void
  29. setargv(argcPtr, argvPtr)
  30. int *argcPtr; /* Filled with number of argument strings. */
  31. char ***argvPtr; /* Filled with argument strings (malloc'd). */
  32. {
  33. char *cmdLine, *p, *arg, *argSpace;
  34. char **argv;
  35. int argc, size, inquote, copy, slashes;
  36.  
  37. cmdLine = GetCommandLine(); /* INTL: BUG */
  38.  
  39. /*
  40. * Precompute an overly pessimistic guess at the number of arguments
  41. * in the command line by counting non-space spans.
  42. */
  43.  
  44. size = 2;
  45. for (p = cmdLine; *p != '\0'; p++) {
  46. if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
  47. size++;
  48. while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
  49. p++;
  50. }
  51. if (*p == '\0') {
  52. break;
  53. }
  54. }
  55. }
  56. argSpace = (char *) Tcl_Alloc(
  57. (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1));
  58. argv = (char **) argSpace;
  59. argSpace += size * sizeof(char *);
  60. size--;
  61.  
  62. p = cmdLine;
  63. for (argc = 0; argc < size; argc++) {
  64. argv[argc] = arg = argSpace;
  65. while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
  66. p++;
  67. }
  68. if (*p == '\0') {
  69. break;
  70. }
  71.  
  72. inquote = 0;
  73. slashes = 0;
  74. while (1) {
  75. copy = 1;
  76. while (*p == '\\') {
  77. slashes++;
  78. p++;
  79. }
  80. if (*p == '"') {
  81. if ((slashes & 1) == 0) {
  82. copy = 0;
  83. if ((inquote) && (p[1] == '"')) {
  84. p++;
  85. copy = 1;
  86. } else {
  87. inquote = !inquote;
  88. }
  89. }
  90. slashes >>= 1;
  91. }
  92.  
  93. while (slashes) {
  94. *arg = '\\';
  95. arg++;
  96. slashes--;
  97. }
  98.  
  99. if ((*p == '\0')
  100. || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */
  101. break;
  102. }
  103. if (copy != 0) {
  104. *arg = *p;
  105. arg++;
  106. }
  107. p++;
  108. }
  109. *arg = '\0';
  110. argSpace = arg + 1;
  111. }
  112. argv[argc] = NULL;
  113.  
  114. *argcPtr = argc;
  115. *argvPtr = argv;
  116. }