PageRenderTime 43ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/pr_lex.c

http://github.com/lbsmith/ProQCC
C | 705 lines | 453 code | 82 blank | 170 comment | 147 complexity | a984e889cc8be1ffd09efda92391a252 MD5 | raw file
  1. #include "qcc.h"
  2. #include "screen.h"
  3. int pr_source_line;
  4. char *pr_file_p;
  5. char *pr_line_start; /*
  6. * start of current source line
  7. */
  8. int pr_bracelevel;
  9. char pr_token[2048];
  10. token_type_t pr_token_type;
  11. type_t *pr_immediate_type;
  12. eval_t pr_immediate;
  13. char pr_immediate_string[2048];
  14. int pr_error_count;
  15. char *pr_punctuation[] =
  16. /*
  17. * longer symbols must be before a shorter partial match
  18. */
  19. {"&&", "||", "<=", ">=", "==", "!=", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", ".", "<", ">", "#", "&", "|", NULL};
  20. /*
  21. * simple types. function types are dynamically allocated
  22. */
  23. type_t type_void =
  24. {ev_void, &def_void};
  25. type_t type_string =
  26. {ev_string, &def_string};
  27. type_t type_float =
  28. {ev_float, &def_float};
  29. type_t type_vector =
  30. {ev_vector, &def_vector};
  31. type_t type_entity =
  32. {ev_entity, &def_entity};
  33. type_t type_field =
  34. {ev_field, &def_field};
  35. type_t type_function =
  36. {ev_function, &def_function, NULL, &type_void};
  37. /* type_function is a void() function used for state defs */
  38. type_t type_pointer =
  39. {ev_pointer, &def_pointer};
  40. type_t type_floatfield =
  41. {ev_field, &def_field, NULL, &type_float};
  42. int type_size[8] =
  43. {1, 1, 1, 3, 1, 1, 1, 1};
  44. def_t def_void =
  45. {&type_void, "temp"};
  46. def_t def_string =
  47. {&type_string, "temp"};
  48. def_t def_float =
  49. {&type_float, "temp"};
  50. def_t def_vector =
  51. {&type_vector, "temp"};
  52. def_t def_entity =
  53. {&type_entity, "temp"};
  54. def_t def_field =
  55. {&type_field, "temp"};
  56. def_t def_function =
  57. {&type_function, "temp"};
  58. def_t def_pointer =
  59. {&type_pointer, "temp"};
  60. def_t def_ret, def_parms[MAX_PARMS];
  61. def_t *def_for_type[8] =
  62. {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer};
  63. void PR_LexWhitespace(void);
  64. /*
  65. * ==============
  66. * PR_PrintNextLine
  67. * ==============
  68. */
  69. void
  70. PR_PrintNextLine(void)
  71. {
  72. char *t;
  73. printf("%3i:", pr_source_line);
  74. for (t = pr_line_start; *t && *t != '\n'; t++)
  75. printf("%c", *t);
  76. printf("\n");
  77. }
  78. /*
  79. * ==============
  80. * PR_NewLine
  81. *
  82. * Call at start of file and when *pr_file_p == '\n'
  83. * ==============
  84. */
  85. void
  86. PR_NewLine(void)
  87. {
  88. boolean m;
  89. if (*pr_file_p == '\n') {
  90. pr_file_p++;
  91. m = true;
  92. } else
  93. m = false;
  94. pr_source_line++;
  95. pr_line_start = pr_file_p;
  96. /*
  97. if (pr_dumpasm)
  98. PR_PrintNextLine();
  99. */
  100. if (m)
  101. pr_file_p--;
  102. }
  103. /*
  104. * ==============
  105. * PR_LexString
  106. *
  107. * Parses a quoted string
  108. * ==============
  109. */
  110. void
  111. PR_LexString(void)
  112. {
  113. int c;
  114. int len;
  115. len = 0;
  116. pr_file_p++;
  117. do {
  118. c = *pr_file_p++;
  119. if (!c)
  120. PR_ParseError("EOF inside quote");
  121. if (c == '\n')
  122. PR_ParseError("newline inside quote");
  123. if (c == '\\') { /*
  124. * escape char
  125. */
  126. c = *pr_file_p++;
  127. if (!c)
  128. PR_ParseError("EOF inside quote");
  129. if (c == 'n')
  130. c = '\n';
  131. else if (c == '"')
  132. c = '"';
  133. else
  134. PR_ParseError("Unknown escape char");
  135. } else if (c == '\"') {
  136. pr_token[len] = 0;
  137. pr_token_type = tt_immediate;
  138. pr_immediate_type = &type_string;
  139. strcpy(pr_immediate_string, pr_token);
  140. return;
  141. }
  142. pr_token[len] = c;
  143. len++;
  144. } while (1);
  145. }
  146. /*
  147. * ==============
  148. * PR_LexNumber
  149. * ==============
  150. */
  151. float
  152. PR_LexNumber(void)
  153. {
  154. int c;
  155. int len;
  156. len = 0;
  157. c = *pr_file_p;
  158. do {
  159. pr_token[len] = c;
  160. len++;
  161. pr_file_p++;
  162. c = *pr_file_p;
  163. } while ((c >= '0' && c <= '9') || c == '.');
  164. pr_token[len] = 0;
  165. return (float)atof(pr_token);
  166. }
  167. /*
  168. * ==============
  169. * PR_LexVector
  170. *
  171. * Parses a single quoted vector
  172. * ==============
  173. */
  174. void
  175. PR_LexVector(void)
  176. {
  177. int i;
  178. pr_file_p++;
  179. pr_token_type = tt_immediate;
  180. pr_immediate_type = &type_vector;
  181. for (i = 0; i < 3; i++) {
  182. pr_immediate.vector[i] = PR_LexNumber();
  183. PR_LexWhitespace();
  184. }
  185. if (*pr_file_p != '\'')
  186. PR_ParseError("Bad vector");
  187. pr_file_p++;
  188. }
  189. /*
  190. * ==============
  191. * PR_LexName
  192. *
  193. * Parses an identifier
  194. * ==============
  195. */
  196. void
  197. PR_LexName(void)
  198. {
  199. int c;
  200. int len;
  201. len = 0;
  202. c = *pr_file_p;
  203. do {
  204. pr_token[len] = c;
  205. len++;
  206. pr_file_p++;
  207. c = *pr_file_p;
  208. } while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
  209. || (c >= '0' && c <= '9'));
  210. pr_token[len] = 0;
  211. pr_token_type = tt_name;
  212. }
  213. /*
  214. * ==============
  215. * PR_LexPunctuation
  216. * ==============
  217. */
  218. void
  219. PR_LexPunctuation(void)
  220. {
  221. int i;
  222. int len;
  223. char *p;
  224. pr_token_type = tt_punct;
  225. for (i = 0; (p = pr_punctuation[i]) != NULL; i++) {
  226. len = strlen(p);
  227. if (!strncmp(p, pr_file_p, len)) {
  228. strcpy(pr_token, p);
  229. if (p[0] == '{')
  230. pr_bracelevel++;
  231. else if (p[0] == '}')
  232. pr_bracelevel--;
  233. pr_file_p += len;
  234. return;
  235. }
  236. }
  237. PR_ParseError("Unknown punctuation");
  238. }
  239. /*
  240. * ==============
  241. * PR_LexWhitespace
  242. * ==============
  243. */
  244. void
  245. PR_LexWhitespace(void)
  246. {
  247. int c;
  248. while (1) {
  249. /*
  250. * skip whitespace
  251. */
  252. while ((c = *pr_file_p) <= ' ') {
  253. if (c == '\n')
  254. PR_NewLine();
  255. if (c == 0)
  256. return; /*
  257. * end of file
  258. */
  259. pr_file_p++;
  260. }
  261. /*
  262. * skip // comments
  263. */
  264. if (c == '/' && pr_file_p[1] == '/') {
  265. while (*pr_file_p && *pr_file_p != '\n')
  266. pr_file_p++;
  267. PR_NewLine();
  268. pr_file_p++;
  269. continue;
  270. }
  271. /* skip / * * / comments */
  272. if (c == '/' && pr_file_p[1] == '*') {
  273. do {
  274. pr_file_p++;
  275. if (pr_file_p[0] == '\n')
  276. PR_NewLine();
  277. if (pr_file_p[1] == 0)
  278. return;
  279. } while (pr_file_p[-1] != '*' || pr_file_p[0] != '/');
  280. pr_file_p++;
  281. continue;
  282. }
  283. break; /*
  284. * a real character has been found
  285. */
  286. }
  287. }
  288. /*============================================================================*/
  289. #define MAX_FRAMES 256
  290. char pr_framemacros[MAX_FRAMES][16];
  291. int pr_nummacros;
  292. void
  293. PR_ClearGrabMacros(void)
  294. {
  295. pr_nummacros = 0;
  296. }
  297. void
  298. PR_FindMacro(void)
  299. {
  300. int i;
  301. for (i = 0; i < pr_nummacros; i++)
  302. if (!strcmp(pr_token, pr_framemacros[i])) {
  303. sprintf(pr_token, "%d", i);
  304. pr_token_type = tt_immediate;
  305. pr_immediate_type = &type_float;
  306. pr_immediate._float = (float)i;
  307. return;
  308. }
  309. PR_ParseError("Unknown frame macro $%s", pr_token);
  310. }
  311. /* just parses text, returning false if an eol is reached */
  312. boolean
  313. PR_SimpleGetToken(void)
  314. {
  315. int c;
  316. int i;
  317. /* skip whitespace */
  318. while ((c = *pr_file_p) <= ' ') {
  319. if (c == '\n' || c == 0)
  320. return false;
  321. pr_file_p++;
  322. }
  323. i = 0;
  324. while ((c = *pr_file_p) > ' ' && c != ',' && c != ';') {
  325. pr_token[i] = c;
  326. i++;
  327. pr_file_p++;
  328. }
  329. pr_token[i] = 0;
  330. return true;
  331. }
  332. void
  333. PR_ParseFrame(void)
  334. {
  335. while (PR_SimpleGetToken()) {
  336. strcpy(pr_framemacros[pr_nummacros], pr_token);
  337. pr_nummacros++;
  338. }
  339. }
  340. /*
  341. * ==============
  342. * PR_LexGrab
  343. *
  344. * Deals with counting sequence numbers and replacing frame macros
  345. * ==============
  346. */
  347. void
  348. PR_LexGrab(void)
  349. {
  350. pr_file_p++; /* skip the $ */
  351. if (!PR_SimpleGetToken())
  352. PR_ParseError("hanging $");
  353. /*
  354. * check for $frame
  355. */
  356. if (!strcmp(pr_token, "frame")) {
  357. PR_ParseFrame();
  358. PR_Lex();
  359. }
  360. /* ignore other known $commands */
  361. else if (!strcmp(pr_token, "cd")
  362. || !strcmp(pr_token, "origin")
  363. || !strcmp(pr_token, "base")
  364. || !strcmp(pr_token, "flags")
  365. || !strcmp(pr_token, "scale")
  366. || !strcmp(pr_token, "skin")) { /* skip to end of line */
  367. while (PR_SimpleGetToken()) ;
  368. PR_Lex();
  369. }
  370. /* look for a frame name macro */
  371. else
  372. PR_FindMacro();
  373. }
  374. /*============================================================================*/
  375. /*
  376. * ==============
  377. * PR_Lex
  378. *
  379. * Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
  380. * ==============
  381. */
  382. void
  383. PR_Lex(void)
  384. {
  385. int c;
  386. pr_token[0] = 0;
  387. if (!pr_file_p) {
  388. pr_token_type = tt_eof;
  389. return;
  390. }
  391. PR_LexWhitespace();
  392. c = *pr_file_p;
  393. if (!c) {
  394. pr_token_type = tt_eof;
  395. return;
  396. }
  397. /* handle quoted strings as a unit */
  398. if (c == '\"') {
  399. PR_LexString();
  400. return;
  401. }
  402. /* handle quoted vectors as a unit */
  403. if (c == '\'') {
  404. PR_LexVector();
  405. return;
  406. }
  407. /* if the first character is a valid identifier, parse until a non-id */
  408. /* character is reached */
  409. if ((c >= '0' && c <= '9') || (c == '-' && pr_file_p[1] >= '0' && pr_file_p[1] <= '9')) {
  410. pr_token_type = tt_immediate;
  411. pr_immediate_type = &type_float;
  412. pr_immediate._float = PR_LexNumber();
  413. return;
  414. }
  415. if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') {
  416. PR_LexName();
  417. return;
  418. }
  419. if (c == '$') {
  420. PR_LexGrab();
  421. return;
  422. }
  423. /* parse symbol strings until a non-symbol is found */
  424. PR_LexPunctuation();
  425. }
  426. /*============================================================================*/
  427. /*
  428. * ============
  429. * PR_ParseError
  430. *
  431. * Aborts the current file load
  432. * ============
  433. */
  434. void
  435. PR_ParseError(char *error,...)
  436. {
  437. va_list argptr;
  438. char string[1024];
  439. va_start(argptr, error);
  440. vsprintf(string, error, argptr);
  441. va_end(argptr);
  442. MoveCurs(2, ScrnHeight - 2);
  443. ShowWarningEntry("%s:%i:%s\n", strings + s_file, pr_source_line, string);
  444. MoveCurs(0, ScrnHeight);
  445. ShowCurs();
  446. longjmp(pr_parse_abort, 1);
  447. }
  448. /*
  449. * =============
  450. * PR_Expect
  451. *
  452. * Issues an error if the current token isn't equal to string
  453. * Gets the next token
  454. * =============
  455. */
  456. #ifndef INLINE
  457. void
  458. PR_Expect(char *string)
  459. {
  460. if (DefCmp(string, pr_token))
  461. PR_ParseError("expected %s, found %s", string, pr_token);
  462. PR_Lex();
  463. }
  464. #endif
  465. /*
  466. * =============
  467. * PR_Check
  468. *
  469. * Returns true and gets the next token if the current token equals string
  470. * Returns false and does nothing otherwise
  471. * =============
  472. */
  473. #ifndef INLINE
  474. boolean
  475. PR_Check(char *string)
  476. {
  477. if (DefCmp(string, pr_token))
  478. return false;
  479. PR_Lex();
  480. return true;
  481. }
  482. #endif
  483. /*
  484. * ============
  485. * PR_ParseName
  486. *
  487. * Checks to see if the current token is a valid name
  488. * ============
  489. */
  490. char *
  491. PR_ParseName(void)
  492. {
  493. static char ident[MAX_NAME];
  494. if (pr_token_type != tt_name)
  495. PR_ParseError("not a name");
  496. if (strlen(pr_token) >= MAX_NAME - 1)
  497. PR_ParseError("name too long");
  498. strcpy(ident, pr_token);
  499. PR_Lex();
  500. return ident;
  501. }
  502. /*
  503. * ============
  504. * PR_FindType
  505. *
  506. * Returns a preexisting complex type that matches the parm, or allocates
  507. * a new one and copies it out.
  508. * ============
  509. */
  510. type_t *
  511. PR_FindType(type_t * type)
  512. {
  513. def_t *def;
  514. type_t *check;
  515. int i;
  516. for (check = pr.types; check; check = check->next) {
  517. if (check->type != type->type
  518. || check->aux_type != type->aux_type
  519. || check->num_parms != type->num_parms)
  520. continue;
  521. for (i = 0; i < type->num_parms; i++)
  522. if (check->parm_types[i] != type->parm_types[i])
  523. break;
  524. if (i == type->num_parms)
  525. return check;
  526. }
  527. /* allocate a new one */
  528. check = malloc(sizeof(*check));
  529. *check = *type;
  530. check->next = pr.types;
  531. pr.types = check;
  532. /* allocate a generic def for the type, so fields can reference it */
  533. def = malloc(sizeof(def_t));
  534. def->name = "COMPLEX TYPE";
  535. def->type = check;
  536. check->def = def;
  537. return check;
  538. }
  539. /*
  540. * ============
  541. * PR_SkipToSemicolon
  542. *
  543. * For error recovery, also pops out of nested braces
  544. * ============
  545. */
  546. void
  547. PR_SkipToSemicolon(void)
  548. {
  549. do {
  550. if (!pr_bracelevel && PR_Check(";"))
  551. return;
  552. PR_Lex();
  553. } while (pr_token[0]); /* eof will return a null token */
  554. }
  555. /*
  556. * ============
  557. * PR_ParseType
  558. *
  559. * Parses a variable type, including field and functions types
  560. * ============
  561. */
  562. char pr_parm_names[MAX_PARMS][MAX_NAME];
  563. type_t *
  564. PR_ParseType(void)
  565. {
  566. type_t new;
  567. type_t *type;
  568. char *name;
  569. if (PR_Check(".")) {
  570. memset(&new, 0, sizeof(new));
  571. new.type = ev_field;
  572. new.aux_type = PR_ParseType();
  573. return PR_FindType(&new);
  574. }
  575. if (!strcmp(pr_token, "float"))
  576. type = &type_float;
  577. else if (!strcmp(pr_token, "vector"))
  578. type = &type_vector;
  579. /*
  580. else if (!strcmp(pr_token, "float"))
  581. type = &type_float;
  582. */
  583. else if (!strcmp(pr_token, "entity"))
  584. type = &type_entity;
  585. else if (!strcmp(pr_token, "string"))
  586. type = &type_string;
  587. else if (!strcmp(pr_token, "void"))
  588. type = &type_void;
  589. else {
  590. PR_ParseError("\"%s\" is not a type", pr_token);
  591. type = &type_float; /*
  592. * shut up compiler warning
  593. */
  594. }
  595. PR_Lex();
  596. if (!PR_Check("("))
  597. return type;
  598. /*
  599. * function type
  600. */
  601. memset(&new, 0, sizeof(new));
  602. new.type = ev_function;
  603. new.aux_type = type; /*
  604. * return type
  605. */
  606. new.num_parms = 0;
  607. if (!PR_Check(")")) {
  608. if (PR_Check("..."))
  609. new.num_parms = -1; /*
  610. * variable args
  611. */
  612. else
  613. do {
  614. type = PR_ParseType();
  615. name = PR_ParseName();
  616. strcpy(pr_parm_names[new.num_parms], name);
  617. new.parm_types[new.num_parms] = type;
  618. new.num_parms++;
  619. } while (PR_Check(","));
  620. PR_Expect(")");
  621. }
  622. return PR_FindType(&new);
  623. }