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.

270 lines
7.5 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 <stdio.h>
  11. #include <ctype.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include "rcpptype.h"
  15. #include "getflags.h"
  16. #include "rcppdecl.h"
  17. #include "rcppext.h"
  18. /************************************************************************/
  19. /* Define function specific macros and global vars */
  20. /************************************************************************/
  21. static char *ErrString; /* Store string pointer in case of error */
  22. /************************************************************************/
  23. /* Local Function Prototypes */
  24. /************************************************************************/
  25. int getnumber (char *);
  26. int isita (char *, char);
  27. void substr (struct cmdtab *, char *, int);
  28. int tailmatch (char *, char *);
  29. /************************************************************************
  30. * crack_cmd(table, string, func, dup)
  31. * set flags determined by the string based on table.
  32. * func will get the next word.
  33. * if dup is set, any strings stored away will get pstrduped
  34. * see getflags.h for specific matching and setting operators
  35. *
  36. * for flags which take parameters, a 'char' following the flag where 'char' is
  37. * '#' : says the parameter string may be separated from the option.
  38. * ie, "-M#" accepts "-Mabc" and "-M abc"
  39. * '*' : says the parameter must be concatenated with the flag
  40. * ie, "-A*" accepts only "-Axyz" not "-A xyz"
  41. * if neither is specified a space is required between parameter and flag
  42. * ie, "-o" accepts only "-o file" and not "-ofile"
  43. *
  44. * Modified by: Dave Weil D001
  45. * recognize '-' and '/' as equivalent on MSDOS
  46. *
  47. ************************************************************************/
  48. int crack_cmd(struct cmdtab *tab, char *string, char *(*next)(void), int _dup)
  49. {
  50. register char *format, *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 '#':
  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 '*':
  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, (char *)0, _dup);
  85. }
  86. return(tab->retval);
  87. break;
  88. case '-': /* D001 */
  89. if ('-' == *str) {
  90. str++; /* D001 */
  91. format++; /* D001 */
  92. continue; /* D001 */
  93. } /* D001 */
  94. else /* D001 */
  95. goto notmatch; /* D001 */
  96. default:
  97. if (*format++ == *str++)
  98. continue;
  99. goto notmatch;
  100. }
  101. /* sorry. we need to break out two levels of loop */
  102. notmatch:
  103. ;
  104. }
  105. return(0);
  106. }
  107. /************************************************************************/
  108. /* set the appropriate flag(s). called only when we know we have a match */
  109. /************************************************************************/
  110. void substr(struct cmdtab *tab, register char *str, int _dup)
  111. {
  112. register struct subtab *q;
  113. LIST * list;
  114. char *string = str;
  115. switch (tab->type) {
  116. case FLAG:
  117. *(int *)(tab->flag) = 1;
  118. return;
  119. case UNFLAG:
  120. *(int *)(tab->flag) = 0;
  121. return;
  122. case NOVSTR:
  123. if (*(char **)(tab->flag)) {
  124. /* before we print it out in the error message get rid of the
  125. * arg specifier (e.g. #) at the end of the format.
  126. */
  127. string = _strdup(tab->format);
  128. if (!string) {
  129. Msg_Temp = GET_MSG (1002);
  130. SET_MSG (Msg_Text, Msg_Temp);
  131. error(1002);
  132. return;
  133. }
  134. string[strlen(string)-1] = '\0';
  135. Msg_Temp = GET_MSG(1046);
  136. SET_MSG (Msg_Text, Msg_Temp, string,*(char **)(tab->flag),str);
  137. fatal(1046);
  138. return;
  139. }
  140. /* fall through */
  141. case STRING:
  142. *(char **)(tab->flag) = (_dup ? _strdup(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 ? _strdup(str) : str);
  151. else {
  152. Msg_Temp = GET_MSG(1047);
  153. SET_MSG (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 == (char)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, 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 getnumber (char *str)
  191. {
  192. long i = 0;
  193. char *ptr = str;
  194. for (; isspace(*ptr); ptr++)
  195. ;
  196. if (!isdigit(*ptr) || (((i = atol(ptr)) >= 65535) || i < 0)) {
  197. Msg_Temp = GET_MSG(1049);
  198. SET_MSG (Msg_Text, Msg_Temp, str);
  199. fatal(1049); /* invalid numerical argument, 'str' */
  200. }
  201. return ((int) i);
  202. }
  203. /************************************************************************/
  204. /* is the letter in the string? */
  205. /************************************************************************/
  206. int isita (register char *str, register char let)
  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 tailmatch (char *format, char *str)
  220. {
  221. register char *f = format;
  222. register char *s = str;
  223. if (f[1] == 0) /* wild card is the last thing in the format, it matches */
  224. return(1);
  225. while (f[1]) /* find char in front of null in format */
  226. f++;
  227. while (s[1]) /* find char in front of null in string to check */
  228. s++;
  229. while (*s == *f) { /* check chars walking towards front */
  230. s--;
  231. f--;
  232. }
  233. /*
  234. ** if we're back at the beginning of the format
  235. ** and
  236. ** the string is either at the beginning or somewhere inside
  237. ** then we have a match.
  238. **
  239. ** ex format == "*.c", str == "file.c"
  240. ** at this point *f = '*' and *s == 'e', since we've kicked out of the above
  241. ** loop. since f==format and s>=str this is a match.
  242. ** but if format == "*.c" and str == "file.asm" then
  243. ** *f == 'c' and *s = 'm', f != format and no match.
  244. */
  245. return((f == format) && (s >= str));
  246. }