Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
9.7 KiB

  1. /************************************************************************/
  2. /* */
  3. /* RCPP - Resource Compiler Pre-Processor for NT system */
  4. /* */
  5. /* GETFLAGS.C - Parse Command Line Flags */
  6. /* */
  7. /* 27-Nov-90 w-BrianM Update for NT from PM SDK RCPP */
  8. /* */
  9. /************************************************************************/
  10. #include "rc.h"
  11. /************************************************************************/
  12. /* Define function specific macros and global vars */
  13. /************************************************************************/
  14. static WCHAR *ErrString; /* Store string pointer in case of error */
  15. /************************************************************************/
  16. /* Local Function Prototypes */
  17. /************************************************************************/
  18. int getnumber (WCHAR *);
  19. int isita (WCHAR *, WCHAR);
  20. void substr (struct cmdtab *, WCHAR *, int);
  21. int tailmatch (WCHAR *, WCHAR *);
  22. /************************************************************************
  23. * crack_cmd(table, string, func, dup)
  24. * set flags determined by the string based on table.
  25. * func will get the next word.
  26. * if dup is set, any strings stored away will get pstrduped
  27. * see getflags.h for specific matching and setting operators
  28. *
  29. * for flags which take parameters, a 'char' following the flag where 'char' is
  30. * '#' : says the parameter string may be separated from the option.
  31. * ie, "-M#" accepts "-Mabc" and "-M abc"
  32. * '*' : says the parameter must be concatenated with the flag
  33. * ie, "-A*" accepts only "-Axyz" not "-A xyz"
  34. * if neither is specified a space is required between parameter and flag
  35. * ie, "-o" accepts only "-o file" and not "-ofile"
  36. *
  37. * Modified by: Dave Weil D001
  38. * recognize '-' and '/' as equivalent on MSDOS
  39. *
  40. ************************************************************************/
  41. int
  42. crack_cmd(
  43. struct cmdtab *tab,
  44. WCHAR *string,
  45. WCHAR *(*next)(void),
  46. int _dup
  47. )
  48. {
  49. register WCHAR *format, *str;
  50. if (!string) {
  51. return(0);
  52. }
  53. ErrString = string;
  54. for (; tab->type; tab++) /* for each format */ {
  55. format = tab->format;
  56. str = string;
  57. for (; ; ) /* scan the string */
  58. switch (*format) {
  59. /* optional space between flag and parameter */
  60. case L'#':
  61. if ( !*str ) {
  62. substr(tab, (*next)(), _dup);
  63. } else {
  64. substr(tab, str, _dup);
  65. }
  66. return(tab->retval);
  67. break;
  68. /* no space allowed between flag and parameter */
  69. case L'*':
  70. if (*str && tailmatch(format, str))
  71. substr(tab, str, _dup);
  72. else
  73. goto notmatch;
  74. return(tab->retval);
  75. break;
  76. /* space required between flag and parameter */
  77. case 0:
  78. if (*str) { /* str left, no good */
  79. goto notmatch;
  80. } else if (tab->type & TAKESARG) { /* if it takes an arg */
  81. substr(tab, (*next)(), _dup);
  82. } else { /* doesn't want an arg */
  83. substr(tab, (WCHAR *)0, _dup);
  84. }
  85. return(tab->retval);
  86. break;
  87. case L'-':
  88. if (L'-' == *str) {
  89. str++;
  90. format++;
  91. continue;
  92. } else {
  93. goto notmatch;
  94. }
  95. default:
  96. if (*format++ == *str++)
  97. continue;
  98. goto notmatch;
  99. }
  100. notmatch:
  101. ;
  102. }
  103. return(0);
  104. }
  105. /************************************************************************/
  106. /* set the appropriate flag(s). called only when we know we have a match */
  107. /************************************************************************/
  108. void
  109. substr(
  110. struct cmdtab *tab,
  111. register WCHAR *str,
  112. int _dup
  113. )
  114. {
  115. register struct subtab *q;
  116. LIST * list;
  117. WCHAR *string = str;
  118. switch (tab->type) {
  119. case FLAG:
  120. *(int *)(tab->flag) = 1;
  121. return;
  122. case UNFLAG:
  123. *(int *)(tab->flag) = 0;
  124. return;
  125. case NOVSTR:
  126. if (*(WCHAR **)(tab->flag)) {
  127. /* before we print it out in the error message get rid of the
  128. * arg specifier (e.g. #) at the end of the format.
  129. */
  130. // string = _wcsdup(tab->format);
  131. // string[wcslen(string)-1] = L'\0';
  132. //
  133. // message 1046 doesn't exist and don't know what it should be
  134. // Msg_Temp = GET_MSG(1046);
  135. // SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, string, *(WCHAR **)(tab->flag), str);
  136. Msg_Temp = GET_MSG(1000);
  137. fatal(1000);
  138. return;
  139. }
  140. /* fall through */
  141. case STRING:
  142. *(WCHAR **)(tab->flag) = (_dup ? _wcsdup(str) : str);
  143. return;
  144. case NUMBER:
  145. *(int *)(tab->flag) = getnumber (str);
  146. return;
  147. case PSHSTR:
  148. list = (LIST * )(tab->flag);
  149. if (list->li_top > 0)
  150. list->li_defns[--list->li_top] = (_dup ? _wcsdup(str) : str);
  151. else {
  152. Msg_Temp = GET_MSG(1047);
  153. SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, tab->format, str);
  154. fatal(1047);
  155. }
  156. return;
  157. case SUBSTR:
  158. for ( ; *str; ++str) { /* walk the substring */
  159. for (q = (struct subtab *)tab->flag; q->letter; q++) {
  160. /*
  161. ** for every member in the table
  162. */
  163. if (*str == (WCHAR)q->letter)
  164. switch (q->type) {
  165. case FLAG:
  166. *(q->flag) = 1;
  167. goto got_letter;
  168. case UNFLAG:
  169. *(q->flag) = 0;
  170. goto got_letter;
  171. default:
  172. goto got_letter;
  173. }
  174. }
  175. got_letter:
  176. if (!q->letter) {
  177. Msg_Temp = GET_MSG(1048);
  178. SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, *str, ErrString);
  179. fatal(1048);
  180. }
  181. }
  182. return;
  183. default:
  184. return;
  185. }
  186. }
  187. /************************************************************************/
  188. /* Parse the string and return a number 0 <= x < 0xffff (64K) */
  189. /************************************************************************/
  190. int
  191. getnumber (
  192. WCHAR *str
  193. )
  194. {
  195. long i = 0;
  196. WCHAR *ptr = str;
  197. for (; iswspace(*ptr); ptr++)
  198. ;
  199. if (!iswdigit(*ptr) || (((i = wcstol(ptr, NULL, 10)) >= 65535) || i < 0)) {
  200. Msg_Temp = GET_MSG(1049);
  201. SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, str);
  202. fatal(1049); /* invalid numerical argument, 'str' */
  203. }
  204. return ((int) i);
  205. }
  206. /************************************************************************/
  207. /* is the letter in the string? */
  208. /************************************************************************/
  209. int
  210. isita (
  211. register WCHAR *str,
  212. register WCHAR let
  213. )
  214. {
  215. if (str)
  216. while (*str)
  217. if (*str++ == let)
  218. return(1);
  219. return(0);
  220. }
  221. /************************************************************************/
  222. /* compare a tail format (as in *.c) with a string. if there is no */
  223. /* tail, anything matches. (null strings are detected elsewhere) */
  224. /* the current implementation only allows one wild card */
  225. /************************************************************************/
  226. int
  227. tailmatch (
  228. WCHAR *format,
  229. WCHAR *str
  230. )
  231. {
  232. register WCHAR *f = format;
  233. register WCHAR *s = str;
  234. if (f[1] == 0) /* wild card is the last thing in the format, it matches */
  235. return(1);
  236. while (f[1]) /* find char in front of null in format */
  237. f++;
  238. while (s[1]) /* find char in front of null in string to check */
  239. s++;
  240. while (*s == *f) { /* check chars walking towards front */
  241. s--;
  242. f--;
  243. }
  244. /*
  245. ** if we're back at the beginning of the format
  246. ** and
  247. ** the string is either at the beginning or somewhere inside
  248. ** then we have a match.
  249. **
  250. ** ex format == "*.c", str == "file.c"
  251. ** at this point *f = '*' and *s == 'e', since we've kicked out of the above
  252. ** loop. since f==format and s>=str this is a match.
  253. ** but if format == "*.c" and str == "file.asm" then
  254. ** *f == 'c' and *s = 'm', f != format and no match.
  255. */
  256. return((f == format) && (s >= str));
  257. }