Leaked source code of windows server 2003
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.

287 lines
9.2 KiB

  1. /***********************************************************************
  2. * Microsoft (R) Windows (R) Resource Compiler
  3. *
  4. * Copyright (c) Microsoft Corporation. All rights reserved.
  5. *
  6. * File Comments:
  7. *
  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 (const wchar_t *);
  19. int isita (const wchar_t *, const wchar_t);
  20. void substr (struct cmdtab *, wchar_t *, int);
  21. int tailmatch (const wchar_t *, const wchar_t *);
  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. const wchar_t *format;
  50. wchar_t *str;
  51. if (!string) {
  52. return(0);
  53. }
  54. ErrString = string;
  55. for (; tab->type; tab++) /* for each format */ {
  56. format = tab->format;
  57. str = string;
  58. for (; ; ) /* scan the string */
  59. switch (*format) {
  60. /* optional space between flag and parameter */
  61. case L'#':
  62. if ( !*str ) {
  63. substr(tab, (*next)(), _dup);
  64. } else {
  65. substr(tab, str, _dup);
  66. }
  67. return(tab->retval);
  68. break;
  69. /* no space allowed between flag and parameter */
  70. case L'*':
  71. if (*str && tailmatch(format, str))
  72. substr(tab, str, _dup);
  73. else
  74. goto notmatch;
  75. return(tab->retval);
  76. break;
  77. /* space required between flag and parameter */
  78. case 0:
  79. if (*str) { /* str left, no good */
  80. goto notmatch;
  81. } else if (tab->type & TAKESARG) { /* if it takes an arg */
  82. substr(tab, (*next)(), _dup);
  83. } else { /* doesn't want an arg */
  84. substr(tab, (WCHAR *)0, _dup);
  85. }
  86. return(tab->retval);
  87. break;
  88. case L'-':
  89. if (L'-' == *str) {
  90. str++;
  91. format++;
  92. continue;
  93. } else {
  94. goto notmatch;
  95. }
  96. default:
  97. if (*format++ == *str++)
  98. continue;
  99. goto notmatch;
  100. }
  101. notmatch:
  102. ;
  103. }
  104. return(0);
  105. }
  106. /************************************************************************/
  107. /* set the appropriate flag(s). called only when we know we have a match */
  108. /************************************************************************/
  109. void
  110. substr(
  111. struct cmdtab *tab,
  112. wchar_t *str,
  113. int _dup
  114. )
  115. {
  116. const struct subtab *q;
  117. LIST * list;
  118. const wchar_t *string = str;
  119. switch (tab->type) {
  120. case FLAG:
  121. *(int *)(tab->flag) = 1;
  122. return;
  123. case UNFLAG:
  124. *(int *)(tab->flag) = 0;
  125. return;
  126. case NOVSTR:
  127. if (*(WCHAR **)(tab->flag)) {
  128. /* before we print it out in the error message get rid of the
  129. * arg specifier (e.g. #) at the end of the format.
  130. */
  131. // string = _wcsdup(tab->format);
  132. // string[wcslen(string)-1] = L'\0';
  133. //
  134. // message 1046 doesn't exist and don't know what it should be
  135. // SET_MSG(1046, string, *(WCHAR **)(tab->flag), str);
  136. fatal(1000);
  137. return;
  138. }
  139. /* fall through */
  140. case STRING:
  141. *(WCHAR **)(tab->flag) = (_dup ? _wcsdup(str) : str);
  142. return;
  143. case NUMBER:
  144. *(int *)(tab->flag) = getnumber(str);
  145. return;
  146. case PSHSTR:
  147. list = (LIST * )(tab->flag);
  148. if (list->li_top > 0)
  149. list->li_defns[--list->li_top] = (_dup ? _wcsdup(str) : str);
  150. else {
  151. fatal(1047, tab->format, str);
  152. }
  153. return;
  154. case SUBSTR:
  155. for ( ; *str; ++str) { /* walk the substring */
  156. for (q = (struct subtab *)tab->flag; q->letter; q++) {
  157. /*
  158. ** for every member in the table
  159. */
  160. if (*str == (WCHAR)q->letter)
  161. switch (q->type) {
  162. case FLAG:
  163. *(q->flag) = 1;
  164. goto got_letter;
  165. case UNFLAG:
  166. *(q->flag) = 0;
  167. goto got_letter;
  168. default:
  169. goto got_letter;
  170. }
  171. }
  172. got_letter:
  173. if (!q->letter) {
  174. fatal(1048, *str, ErrString);
  175. }
  176. }
  177. return;
  178. default:
  179. return;
  180. }
  181. }
  182. /************************************************************************/
  183. /* Parse the string and return a number 0 <= x < 0xffff (64K) */
  184. /************************************************************************/
  185. int
  186. getnumber (
  187. const wchar_t *str
  188. )
  189. {
  190. long i = 0;
  191. const wchar_t *ptr = str;
  192. for (; iswspace(*ptr); ptr++)
  193. ;
  194. if (!iswdigit(*ptr) || (((i = wcstol(ptr, NULL, 10)) >= 65535) || i < 0)) {
  195. fatal(1049, str); /* invalid numerical argument, 'str' */
  196. }
  197. return((int) i);
  198. }
  199. /************************************************************************/
  200. /* is the letter in the string? */
  201. /************************************************************************/
  202. int
  203. isita (
  204. const wchar_t *str,
  205. const wchar_t let
  206. )
  207. {
  208. if (str)
  209. while (*str)
  210. if (*str++ == let)
  211. return(1);
  212. return(0);
  213. }
  214. /************************************************************************/
  215. /* compare a tail format (as in *.c) with a string. if there is no */
  216. /* tail, anything matches. (null strings are detected elsewhere) */
  217. /* the current implementation only allows one wild card */
  218. /************************************************************************/
  219. int
  220. tailmatch (
  221. const wchar_t *format,
  222. const wchar_t *str
  223. )
  224. {
  225. const wchar_t *f = format;
  226. const wchar_t *s = str;
  227. if (f[1] == 0) /* wild card is the last thing in the format, it matches */
  228. return(1);
  229. while (f[1]) /* find char in front of null in format */
  230. f++;
  231. while (s[1]) /* find char in front of null in string to check */
  232. s++;
  233. while (*s == *f) { /* check chars walking towards front */
  234. s--;
  235. f--;
  236. }
  237. /*
  238. ** if we're back at the beginning of the format
  239. ** and
  240. ** the string is either at the beginning or somewhere inside
  241. ** then we have a match.
  242. **
  243. ** ex format == "*.c", str == "file.c"
  244. ** at this point *f = '*' and *s == 'e', since we've kicked out of the above
  245. ** loop. since f==format and s>=str this is a match.
  246. ** but if format == "*.c" and str == "file.asm" then
  247. ** *f == 'c' and *s = 'm', f != format and no match.
  248. */
  249. return((f == format) && (s >= str));
  250. }