PageRenderTime 90ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/nqc-3.1.r6/nqc/CmdLine.cpp

#
C++ | 211 lines | 130 code | 36 blank | 45 comment | 46 complexity | 407601c6cd70fc0845789a66e15f468e MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /*
  2. * The contents of this file are subject to the Mozilla Public License
  3. * Version 1.0 (the "License"); you may not use this file except in
  4. * compliance with the License. You may obtain a copy of the License at
  5. * http://www.mozilla.org/MPL/
  6. *
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  9. * License for the specific language governing rights and limitations
  10. * under the License.
  11. *
  12. * The Initial Developer of this code is David Baum.
  13. * Portions created by David Baum are Copyright (C) 2000 David Baum.
  14. * All Rights Reserved.
  15. *
  16. * Portions created by John Hansen are Copyright (C) 2005 John Hansen.
  17. * All Rights Reserved.
  18. *
  19. */
  20. #include "CmdLine.h"
  21. #include <cstring>
  22. #include <cctype>
  23. CmdLine::~CmdLine()
  24. {
  25. unsigned int i;
  26. for(i=0; i<fArgs.size(); ++i)
  27. {
  28. delete[] fArgs[i];
  29. }
  30. }
  31. /*
  32. * Add a single argument
  33. */
  34. void CmdLine::Add(const char *a)
  35. {
  36. char *s;
  37. if (!a) return;
  38. s = new char[strlen(a) + 1];
  39. strcpy(s, a);
  40. fArgs.push_back(s);
  41. }
  42. /*
  43. * Add an array of arguments
  44. */
  45. void CmdLine::Add(int argc, const char * const *argv)
  46. {
  47. int i;
  48. for(i=0; i<argc; ++i)
  49. Add(argv[i]);
  50. }
  51. /*
  52. * Parse multiple arguments from a single line.
  53. *
  54. * Use double quotes to enclose whitespace within arguments.
  55. * No escaping is performed. The 'skip' parameter indicates
  56. * how many of the resulting arguments should be skipped (i.e.
  57. * not placed in the arg list). This is useful if you want to
  58. * strip out the first argument (typically the command itself).
  59. */
  60. void CmdLine::Parse(const char *line, int skip)
  61. {
  62. if (!line) return;
  63. char *buf = new char[strlen(line)+1];
  64. char *dst = buf;
  65. const char *src = line;
  66. enum
  67. {
  68. IDLE = 0,
  69. READING,
  70. QUOTING
  71. } state = IDLE;
  72. while(true)
  73. {
  74. // read chars until no more
  75. char c = *src++;
  76. if (c == 0) break;
  77. if (c == '\"')
  78. {
  79. // quote
  80. if (state == QUOTING)
  81. state = READING;
  82. else
  83. state = QUOTING;
  84. }
  85. else if (c== ' ' || c== '\t')
  86. {
  87. // whitespace
  88. if (state == READING)
  89. {
  90. // done with argument, terminate it and add to list
  91. *dst = 0;
  92. if (skip)
  93. --skip;
  94. else
  95. Add(buf);
  96. // reset to idle state and empty arg
  97. state = IDLE;
  98. dst = buf;
  99. }
  100. else if (state == QUOTING)
  101. *dst++ = c;
  102. }
  103. else
  104. {
  105. if (state == IDLE)
  106. state = READING;
  107. *dst++ = c;
  108. }
  109. }
  110. // add last arg if any
  111. if (dst > buf)
  112. {
  113. *dst = 0;
  114. if (!skip)
  115. Add(buf);
  116. }
  117. delete [] buf;
  118. }
  119. #if 0
  120. void CmdLine::Parse(const char *line)
  121. {
  122. const char *start, *ptr;
  123. if (!line) return;
  124. ptr = line;
  125. while(*ptr)
  126. {
  127. // eat up leading whitespace
  128. for(start = ptr; *start; ++start)
  129. if (!isspace(*start)) break;
  130. if (*start == 0) break;
  131. if (*start == '\"')
  132. {
  133. ++start;
  134. // find closing quote
  135. for(ptr = start; *ptr; ++ptr)
  136. {
  137. if (*ptr == '\\')
  138. {
  139. // char was escaped
  140. if (ptr[1] != 0) ++ptr;
  141. }
  142. else if (*ptr == '\"')
  143. break;
  144. }
  145. Add(start, ptr, true);
  146. if (*ptr == '\"')
  147. ++ptr;
  148. }
  149. else
  150. {
  151. // find end of token
  152. for(ptr = start; *ptr; ++ptr)
  153. if (isspace(*ptr)) break;
  154. // new argument
  155. if (ptr > start)
  156. Add(start, ptr, false);
  157. }
  158. }
  159. }
  160. void CmdLine::Add(const char *start, const char *end, bool escape)
  161. {
  162. int len = end - start;
  163. char *arg = new char[len + 1];
  164. char *dst = arg;
  165. while(len--)
  166. {
  167. if (escape && *start == '\\')
  168. ++start;
  169. else
  170. *dst++ = *start++;
  171. }
  172. *dst++ = 0;
  173. fArgs.Append(arg);
  174. }
  175. #endif