pr_lex.c 12 KB

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