Windows NT 4.0 source code leak
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.

264 lines
7.3 KiB

4 years ago
  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. string[strlen(string)-1] = '\0';
  129. Msg_Temp = GET_MSG(1046);
  130. SET_MSG (Msg_Text, Msg_Temp, string,*(char **)(tab->flag),str);
  131. fatal(1046);
  132. return;
  133. }
  134. /* fall through */
  135. case STRING:
  136. *(char **)(tab->flag) = (_dup ? _strdup(str) : str);
  137. return;
  138. case NUMBER:
  139. *(int *)(tab->flag) = getnumber (str);
  140. return;
  141. case PSHSTR:
  142. list = (LIST * )(tab->flag);
  143. if (list->li_top > 0)
  144. list->li_defns[--list->li_top] = (_dup ? _strdup(str) : str);
  145. else {
  146. Msg_Temp = GET_MSG(1047);
  147. SET_MSG (Msg_Text, Msg_Temp, tab->format, str);
  148. fatal(1047);
  149. }
  150. return;
  151. case SUBSTR:
  152. for ( ; *str; ++str) { /* walk the substring */
  153. for (q = (struct subtab *)tab->flag; q->letter; q++) {
  154. /*
  155. ** for every member in the table
  156. */
  157. if (*str == (char)q->letter)
  158. switch (q->type) {
  159. case FLAG:
  160. *(q->flag) = 1;
  161. goto got_letter;
  162. case UNFLAG:
  163. *(q->flag) = 0;
  164. goto got_letter;
  165. default:
  166. goto got_letter;
  167. }
  168. }
  169. got_letter:
  170. if (!q->letter) {
  171. Msg_Temp = GET_MSG(1048);
  172. SET_MSG (Msg_Text, Msg_Temp, *str, ErrString);
  173. fatal(1048);
  174. }
  175. }
  176. return;
  177. default:
  178. return;
  179. }
  180. }
  181. /************************************************************************/
  182. /* Parse the string and return a number 0 <= x < 0xffff (64K) */
  183. /************************************************************************/
  184. int getnumber (char *str)
  185. {
  186. long i = 0;
  187. char *ptr = str;
  188. for (; isspace(*ptr); ptr++)
  189. ;
  190. if (!isdigit(*ptr) || (((i = atol(ptr)) >= 65535) || i < 0)) {
  191. Msg_Temp = GET_MSG(1049);
  192. SET_MSG (Msg_Text, Msg_Temp, str);
  193. fatal(1049); /* invalid numerical argument, 'str' */
  194. }
  195. return ((int) i);
  196. }
  197. /************************************************************************/
  198. /* is the letter in the string? */
  199. /************************************************************************/
  200. int isita (register char *str, register char let)
  201. {
  202. if (str)
  203. while (*str)
  204. if (*str++ == let)
  205. return(1);
  206. return(0);
  207. }
  208. /************************************************************************/
  209. /* compare a tail format (as in *.c) with a string. if there is no */
  210. /* tail, anything matches. (null strings are detected elsewhere) */
  211. /* the current implementation only allows one wild card */
  212. /************************************************************************/
  213. int tailmatch (char *format, char *str)
  214. {
  215. register char *f = format;
  216. register char *s = str;
  217. if (f[1] == 0) /* wild card is the last thing in the format, it matches */
  218. return(1);
  219. while (f[1]) /* find char in front of null in format */
  220. f++;
  221. while (s[1]) /* find char in front of null in string to check */
  222. s++;
  223. while (*s == *f) { /* check chars walking towards front */
  224. s--;
  225. f--;
  226. }
  227. /*
  228. ** if we're back at the beginning of the format
  229. ** and
  230. ** the string is either at the beginning or somewhere inside
  231. ** then we have a match.
  232. **
  233. ** ex format == "*.c", str == "file.c"
  234. ** at this point *f = '*' and *s == 'e', since we've kicked out of the above
  235. ** loop. since f==format and s>=str this is a match.
  236. ** but if format == "*.c" and str == "file.asm" then
  237. ** *f == 'c' and *s = 'm', f != format and no match.
  238. */
  239. return((f == format) && (s >= str));
  240. }