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.

561 lines
11 KiB

  1. /* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. #include <stdarg.h>
  6. #include <string.h>
  7. #include "defs.h"
  8. #include "parser.h"
  9. #define IS_IDENT(c) (isalpha(c) || c == '_' || c == '\'' || c == '\"')
  10. #ifdef YYDEBUG
  11. extern int yydebug;
  12. #endif
  13. enum {
  14. DeclSection,
  15. Union,
  16. Union1,
  17. State,
  18. State1,
  19. CCode,
  20. RuleSection,
  21. Arg,
  22. Action,
  23. CSection,
  24. End
  25. } state;
  26. int bufferpos;
  27. char *buffer = 0;
  28. int buffersize = 0;
  29. char *line = 0;
  30. int linesize = 0;
  31. int linelen = 0;
  32. char *cptr;
  33. int meteof = 0;
  34. int lineno;
  35. char filename[256];
  36. FILE *fin;
  37. void error(LLPOS *pos, char *fmt, ...);
  38. void
  39. addchar(char c)
  40. {
  41. if (bufferpos >= buffersize) {
  42. if (!buffersize) {
  43. buffersize = 4096;
  44. buffer = (char *)malloc(buffersize);
  45. } else {
  46. buffersize <<= 1;
  47. buffer = (char *)realloc(buffer, buffersize);
  48. }
  49. if (!buffer)
  50. error(NULL, "Out of memory");
  51. }
  52. buffer[bufferpos++] = c;
  53. }
  54. void
  55. memmove_fwd(char *dst, char *src, int len)
  56. {
  57. while (len--)
  58. *dst++ = *src++;
  59. }
  60. int
  61. read_line()
  62. {
  63. int nread;
  64. int left;
  65. if (!linesize) {
  66. linesize = 4096;
  67. cptr = line = (char *)malloc(linesize);
  68. linelen = 0;
  69. }
  70. if (!linelen && meteof)
  71. return 0;
  72. if (linelen && (cptr <= line || cptr > line + linelen || cptr[-1] != '\n'))
  73. abort();
  74. left = linelen - (int)(cptr - line);
  75. if (left && memchr(cptr, '\n', left))
  76. return 1;
  77. linelen = left;
  78. if (left)
  79. memmove_fwd(line, cptr, left);
  80. cptr = line;
  81. while ((!linelen || !memchr(line, '\n', linelen)) && !meteof) {
  82. if (linesize - linelen < 2048) {
  83. linesize <<= 1;
  84. line = (char *)realloc(line, linesize);
  85. cptr = line;
  86. }
  87. nread = fread(line + linelen, 1, linesize - linelen, fin);
  88. if (nread < linesize - linelen)
  89. meteof = 1;
  90. linelen += nread;
  91. }
  92. return linelen > 0;
  93. }
  94. int
  95. get_line()
  96. {
  97. int depth = 0;
  98. char *p;
  99. for (;;) {
  100. if (!read_line())
  101. return 0;
  102. if (!strncmp(cptr, "#line ", 6)) {
  103. lineno = strtol(cptr + 6, &cptr, 10) - 1;
  104. while (isspace(*cptr) && *cptr != '\n')
  105. cptr++;
  106. if (*cptr == '\"') {
  107. cptr++;
  108. for (p = filename; *cptr != '\n' && *cptr != '\"';) {
  109. *p++ = *cptr++;
  110. }
  111. *p = 0;
  112. }
  113. cptr = strchr(cptr, '\n') + 1;
  114. continue;
  115. }
  116. lineno++;
  117. if (!strncmp(cptr, "%comment", 8)) {
  118. cptr = strchr(cptr, '\n') + 1;
  119. depth++;
  120. continue;
  121. }
  122. if (!strncmp(cptr, "%endcomment", 11)) {
  123. cptr = strchr(cptr, '\n') + 1;
  124. depth--;
  125. continue;
  126. }
  127. if (!depth)
  128. return 1;
  129. cptr = strchr(cptr, '\n') + 1;
  130. }
  131. }
  132. int
  133. read_char()
  134. {
  135. for (;;) {
  136. if (!cptr) {
  137. if (!get_line())
  138. return EOF;
  139. continue;
  140. }
  141. if (*cptr == '\n') {
  142. cptr++;
  143. if (!get_line())
  144. return EOF;
  145. continue;
  146. }
  147. if (isspace(*cptr)) {
  148. cptr++;
  149. continue;
  150. }
  151. if (*cptr == '/' && cptr[1] == '/') {
  152. cptr = strchr(cptr, '\n') + 1;
  153. continue;
  154. }
  155. if (*cptr == '/' && cptr[1] == '*') {
  156. cptr += 2;
  157. do {
  158. while (*cptr != '*') {
  159. if (*cptr++ == '\n') {
  160. if (!get_line())
  161. error(NULL, "Unexpected EOF");
  162. }
  163. }
  164. } while (*++cptr != '/');
  165. cptr++;
  166. continue;
  167. }
  168. break;
  169. }
  170. return *cptr;
  171. }
  172. void
  173. get_identifier(LLPOS *pos)
  174. {
  175. int quote;
  176. bufferpos = 0;
  177. addchar(*cptr);
  178. if (*cptr == '\'' || *cptr == '\"') {
  179. quote = *cptr++;
  180. while (*cptr != quote) {
  181. if (*cptr == '\n')
  182. error(pos, "Missing closing quote");
  183. addchar(*cptr);
  184. if (*cptr++ == '\\')
  185. addchar(*cptr++);
  186. }
  187. addchar(*cptr++);
  188. } else {
  189. cptr++;
  190. while (isalnum(*cptr) || *cptr == '_')
  191. addchar(*cptr++);
  192. }
  193. addchar(0);
  194. }
  195. int
  196. get_token(LLSTYPE *lval, LLPOS *pos)
  197. {
  198. int c;
  199. int depth;
  200. c = read_char();
  201. pos->line = lineno;
  202. pos->column = cptr ? (int)(cptr - line) - 1 : 0;
  203. pos->file = strdup(filename);
  204. switch (state) {
  205. case DeclSection:
  206. if (!strncmp(cptr, "%%", 2)) {
  207. state = RuleSection;
  208. cptr += 2;
  209. return PERCENT_PERCENT;
  210. }
  211. if (!strncmp(cptr, "%token", 6)) {
  212. cptr += 6;
  213. return PERCENT_TOKEN;
  214. }
  215. if (!strncmp(cptr, "%type", 5)) {
  216. cptr += 5;
  217. return PERCENT_TYPE;
  218. }
  219. if (!strncmp(cptr, "%external", 9)) {
  220. cptr += 9;
  221. return PERCENT_EXTERNAL;
  222. }
  223. if (!strncmp(cptr, "%start", 6)) {
  224. cptr += 6;
  225. return PERCENT_START;
  226. }
  227. if (!strncmp(cptr, "%union", 6)) {
  228. state = Union;
  229. cptr += 6;
  230. return PERCENT_UNION;
  231. }
  232. if (!strncmp(cptr, "%state", 6)) {
  233. state = State;
  234. cptr += 6;
  235. return PERCENT_STATE;
  236. }
  237. if (!strncmp(cptr, "%prefix", 7)) {
  238. cptr += 7;
  239. return PERCENT_PREFIX;
  240. }
  241. if (!strncmp(cptr, "%module", 7)) {
  242. cptr += 7;
  243. return PERCENT_MODULE;
  244. }
  245. if (!strncmp(cptr, "%{", 2)) { /*}*/
  246. state = CCode;
  247. cptr += 2;
  248. return PERCENT_LBRACE;
  249. }
  250. if (!strncmp(cptr, "%}", 2)) { /*{*/
  251. cptr += 2;
  252. return PERCENT_RBRACE;
  253. }
  254. if (c == '<' || c == '>' || c == '=') {
  255. return *cptr++;
  256. }
  257. if (IS_IDENT(c)) {
  258. get_identifier(pos);
  259. lval->_string = strdup(buffer);
  260. return IDENTIFIER;
  261. }
  262. break;
  263. case Union:
  264. if (c == '{') { /*}*/
  265. state = Union1;
  266. cptr++;
  267. return c;
  268. }
  269. break;
  270. case Union1:
  271. bufferpos = 0;
  272. if (c == '}') { /*{*/
  273. state = DeclSection;
  274. cptr++;
  275. return c;
  276. }
  277. if (c == ';') {
  278. cptr++;
  279. return c;
  280. }
  281. while (*cptr != ';') {
  282. addchar(*cptr++);
  283. if (*cptr == '\n') {
  284. cptr++;
  285. if (!get_line())
  286. error(pos, "Unexpected EOF");
  287. }
  288. }
  289. addchar(0);
  290. lval->_string = strdup(buffer);
  291. return TAGDEF;
  292. case State:
  293. if (c == '{') { /*}*/
  294. state = State1;
  295. cptr++;
  296. return c;
  297. }
  298. break;
  299. case State1:
  300. bufferpos = 0;
  301. if (c == '}') { /*{*/
  302. state = DeclSection;
  303. cptr++;
  304. return c;
  305. }
  306. if (c == ';') {
  307. cptr++;
  308. return c;
  309. }
  310. while (*cptr != ';') {
  311. addchar(*cptr++);
  312. if (*cptr == '\n') {
  313. cptr++;
  314. if (!get_line())
  315. error(pos, "Unexpected EOF");
  316. }
  317. }
  318. addchar(0);
  319. lval->_string = strdup(buffer);
  320. return TAGDEF;
  321. case CCode:
  322. bufferpos = 0;
  323. for (;;) {
  324. if (*cptr == '%' && cptr[1] == '}') /*{*/
  325. break;
  326. addchar(*cptr);
  327. if (*cptr++ == '\n') {
  328. if (!get_line())
  329. error(pos, "Unexpected EOF");
  330. }
  331. }
  332. state = DeclSection;
  333. addchar(0);
  334. lval->_ccode = strdup(buffer);
  335. return CCODE;
  336. case RuleSection:
  337. if (IS_IDENT(c)) {
  338. get_identifier(pos);
  339. lval->_string = strdup(buffer);
  340. return IDENTIFIER;
  341. }
  342. if (c == '(') {
  343. state = Arg;
  344. cptr++;
  345. return c;
  346. }
  347. if (c == ':' || c == ';' || c == '|' || c == '}' || c == '+' ||
  348. c == '*' || c == '?' || c == '[' || c == ']') { /*{*/
  349. cptr++;
  350. return c;
  351. }
  352. if (c == '%' && cptr[1] == '%') {
  353. state = CSection;
  354. cptr += 2;
  355. return PERCENT_PERCENT;
  356. }
  357. if (c == '{') {
  358. state = Action;
  359. cptr++;
  360. return c;
  361. }
  362. break;
  363. case Arg:
  364. if (c == ')') {
  365. state = RuleSection;
  366. cptr++;
  367. return c;
  368. }
  369. if (c == ',') {
  370. cptr++;
  371. return c;
  372. }
  373. bufferpos = 0;
  374. depth = 0;
  375. for (;;) {
  376. switch (*cptr) {
  377. case '(':
  378. depth++;
  379. addchar(*cptr++);
  380. continue;
  381. case ')':
  382. if (depth > 0) {
  383. depth--;
  384. addchar(*cptr++);
  385. continue;
  386. }
  387. break;
  388. case ',':
  389. if (depth > 0) {
  390. addchar(*cptr++);
  391. continue;
  392. }
  393. break;
  394. case '\n':
  395. error(pos, "Unterminated argument");
  396. /*NOTREACHED*/
  397. default:
  398. addchar(*cptr++);
  399. continue;
  400. }
  401. break;
  402. }
  403. addchar(0);
  404. lval->_string = strdup(buffer);
  405. return ARG;
  406. case Action:
  407. bufferpos = 0;
  408. depth = 0;
  409. for (;;) {
  410. switch (*cptr) {
  411. case '{': /*}*/
  412. depth++;
  413. addchar(*cptr++);
  414. continue;
  415. case '}': /*{*/
  416. if (depth > 0) {
  417. depth--;
  418. addchar(*cptr++);
  419. continue;
  420. }
  421. break;
  422. case '\'':
  423. case '\"':
  424. c = *cptr++;
  425. addchar((char)c);
  426. while (*cptr != c) {
  427. addchar(*cptr);
  428. if (*cptr == '\n') {
  429. cptr++;
  430. get_line();
  431. continue;
  432. }
  433. if (*cptr == '\\')
  434. addchar(*++cptr);
  435. cptr++;
  436. }
  437. addchar((char)c);
  438. cptr++;
  439. continue;
  440. case '\n':
  441. addchar(*cptr++);
  442. if (!get_line())
  443. error(pos, "Unexpected EOF");
  444. continue;
  445. default:
  446. addchar(*cptr++);
  447. continue;
  448. }
  449. break;
  450. }
  451. state = RuleSection;
  452. addchar(0);
  453. lval->_ccode = strdup(buffer);
  454. return CCODE;
  455. case CSection:
  456. bufferpos = 0;
  457. if (c != EOF) {
  458. do {
  459. do {
  460. addchar(*cptr);
  461. } while (*cptr++ != '\n');
  462. } while (get_line());
  463. }
  464. state = End;
  465. addchar(0);
  466. lval->_ccode = strdup(buffer);
  467. return CCODE;
  468. case End:
  469. return EOF;
  470. }
  471. error(pos, "Syntax error");
  472. return EOF;
  473. /*NOTREACHED*/
  474. }
  475. void
  476. open_file(char *file)
  477. {
  478. strcpy(filename, file);
  479. lineno = 0;
  480. fin = fopen(filename, "r");
  481. if (!fin) {
  482. perror(file);
  483. exit(1);
  484. }
  485. }
  486. int
  487. llgettoken(int *token, LLSTYPE *lval, LLPOS *pos)
  488. {
  489. *token = get_token(lval, pos);
  490. return *token != EOF;
  491. }
  492. void
  493. llprinttoken(LLTERM *token, char *identifier, FILE *f)
  494. {
  495. switch (token->token) {
  496. case IDENTIFIER:
  497. printf("scanner: delivering token IDENTIFIER(%s)\n", token->lval._string);
  498. break;
  499. case ARG:
  500. printf("scanner: delivering token ARG(%s)\n", token->lval._string);
  501. break;
  502. case CCODE:
  503. printf("scanner: delivering token CCODE(%s)\n", token->lval._ccode);
  504. break;
  505. case TAGDEF:
  506. printf("scanner: delivering token TAGDEF(%s)\n", token->lval._string);
  507. break;
  508. case PERCENT_PERCENT:
  509. printf("scanner: delivering token %%%%\n");
  510. break;
  511. case PERCENT_TOKEN:
  512. printf("scanner: delivering token %%token\n");
  513. break;
  514. case PERCENT_TYPE:
  515. printf("scanner: delivering token %%type\n");
  516. break;
  517. case PERCENT_UNION:
  518. printf("scanner: delivering token %%union\n");
  519. break;
  520. case PERCENT_START:
  521. printf("scanner: delivering token %%start\n");
  522. break;
  523. case PERCENT_PREFIX:
  524. printf("scanner: delivering token %%prefix\n");
  525. break;
  526. case PERCENT_LBRACE:
  527. printf("scanner: delivering token %%{\n");
  528. break;
  529. case PERCENT_RBRACE:
  530. printf("scanner: delivering token %%}\n");
  531. break;
  532. case EOF:
  533. printf("scanner: delivering token EOF\n");
  534. break;
  535. default:
  536. printf("scanner: delivering token %c\n", token->token);
  537. break;
  538. }
  539. }