1
2 #include "qcc.h"
3 #include "hash.h"
4
5
6 int pr_source_line;
7
8 char *pr_file_p;
9 char *pr_line_start; // start of current source line
10
11 int pr_bracelevel;
12
13 char pr_token[2048];
14
15 token_type_t pr_token_type;
16 type_t *pr_immediate_type;
17 eval_t pr_immediate;
18 int pr_immediate_index;
19
20 char pr_immediate_string[2048];
21 int pr_immediate_strlen;
22
23 int pr_error_count;
24
25 char *pr_punctuation[] =
26 // longer symbols must be before a shorter partial match
27 {"&=", "|=", "+=", "-=", "*=", "/=", "--", "++",";", "(", ")", "==", "=", ",", "...", ".", "{", "}",
28 "[", "]", "+", "*", "-", "!=", "!", "#", "&&", "&",
29 ">=", ">", "<=", "<", "||", "|", "/", ":", "@", "?" , NULL};
30
31 int pr_punct_length[] =
32 {2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1,
33 1, 1, 1, 1, 1, 2, 1, 1, 2, 1,
34 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 0};
35
36 // simple types. function types are dynamically allocated
37 type_t type_void = {ev_void, &def_void};
38 type_t type_string = {ev_string, &def_string};
39 type_t type_float = {ev_float, &def_float};
40 type_t type_vector = {ev_vector, &def_vector};
41 type_t type_entity = {ev_entity, &def_entity};
42 type_t type_field = {ev_field, &def_field};
43 type_t type_function = {ev_function, &def_function,NULL,&type_void};
44 // type_function is a void() function used for state defs
45 type_t type_pointer = {ev_pointer, &def_pointer};
46 // type_int -- FrikaC new
47 type_t type_int = {ev_int, &def_int};
48
49 type_t type_floatfield = {ev_field, &def_field, NULL, &type_float};
50
51 int type_size[9] = {1,1,1,3,1,1,1,1,1};
52
53 def_t def_void = {&type_void, "temp"};
54 def_t def_string = {&type_string, "temp"};
55 def_t def_float = {&type_float, "temp"};
56 def_t def_vector = {&type_vector, "temp"};
57 def_t def_entity = {&type_entity, "temp"};
58 def_t def_field = {&type_field, "temp"};
59 def_t def_function = {&type_function, "temp"};
60 def_t def_pointer = {&type_pointer, "temp"};
61 def_t def_int = {&type_int, "temp"};
62
63
64 def_t def_ret, def_parms[MAX_PARMS];
65
66 def_t *def_for_type[9] = {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer, &def_int};
67
68 void PR_LexWhitespace (void);
69
70 define_t pr_defines[MAX_DEFINES];
71 int macrohash[HSIZE1];
72 int num_defines;
73
74
75 /*
76 ==============
77 PR_PrintNextLine
78 ==============
79 */
PR_PrintNextLine(void)80 void PR_PrintNextLine (void)
81 {
82 char *t;
83
84 printf ("%3i:",pr_source_line);
85 for (t=pr_line_start ; *t && *t != '\n' ; t++)
86 printf ("%c",*t);
87 printf ("\n");
88 }
89
90 /*
91 ==============
92 PR_NewLine
93
94 Call at start of file and when *pr_file_p == '\n'
95 ==============
96 */
PR_NewLine(void)97 void PR_NewLine (void)
98 {
99
100 if (*pr_file_p == '\n')
101 pr_line_start = pr_file_p + 1;
102 else
103 pr_line_start = pr_file_p;
104 pr_source_line++;
105 }
106
107 /*
108 ==============
109 PR_LexString
110
111 Parses a quoted string
112 ==============
113 */
PR_LexString(void)114 void PR_LexString (void)
115 {
116 int c;
117 int mask1 = 0;
118 int mask2;
119
120 pr_immediate_strlen = 0;
121 pr_file_p++;
122 do
123 {
124
125 mask2 = 128;
126 c = *pr_file_p++;
127 if (!c)
128 PR_ParseError ("EOF inside quote");
129 if (c=='\n')
130 PR_ParseError ("newline inside quote");
131 if (c == '\r')
132 continue;
133 if (c=='\\')
134 { // escape char
135 mask2 = 0;
136 c = *pr_file_p++;
137 if (!c)
138 PR_ParseError ("EOF inside quote");
139 if (c == 'n')
140 c = '\n';
141 else if (c == '"')
142 c = '"' | mask1;
143 else if (c == '\\')
144 c = '\\' | mask1;
145 else if (c == 'b')
146 {
147 mask1 ^= 128;
148 continue;
149 }
150 else if (c == '[')
151 c = 16;
152 else if (c == ']')
153 c = 17;
154 else if (c == '.')
155 c = 28 | mask1;
156 else if (c == '\n' || c=='\r')
157 {
158 // FrikaC: Windoze/DOS have both CR & LF, so let's keep checking
159 // this has the side effect of potentially bumping the line num more than needed..
160 // FIXME
161 while(*pr_file_p == '\n' || *pr_file_p =='\r')
162 pr_file_p++;
163 pr_source_line++;
164 continue;
165 }
166 else if (c == '<')
167 c = 29;
168 else if (c == '-')
169 c = 30;
170 else if (c == '>')
171 c = 31;
172 else if (c >= '0' && c <= '9')
173 c = 18 + c - '0';
174 else if (c == '(')
175 c = 128;
176 else if (c == '=')
177 c = 129;
178 else if (c == ')')
179 c = 130;
180 else if (c == '{')
181 {
182 int d;
183 c = 0;
184 while ((d = *pr_file_p++) != '}')
185 {
186 c = c * 10 + d - '0';
187 if (d < '0' || d > '9' || c > 255)
188 PR_ParseError("Bad character code");
189 }
190 }
191 else
192 PR_ParseError ("Unknown escape char");
193 }
194 else if (c=='\"')
195 {
196 mask1 = 0;
197 PR_LexWhitespace ();
198 if (*pr_file_p == ':')
199 {
200 pr_file_p++;
201 pr_token[pr_immediate_strlen++] = 0;
202 PR_LexWhitespace();
203 }
204 if (*pr_file_p != '\"')
205 {
206 pr_token[pr_immediate_strlen++] = 0;
207 pr_token_type = tt_immediate;
208 pr_immediate_type = &type_string;
209 memcpy (pr_immediate_string, pr_token, pr_immediate_strlen);
210 return;
211 }
212 pr_file_p++;
213 continue;
214 }
215 pr_token[pr_immediate_strlen++] = c | (mask1 & mask2);
216 } while (1);
217 }
218
219 /*
220 ==============
221 PR_LexNumber
222 ==============
223 */
PR_LexNumber(void)224 float PR_LexNumber (void)
225 {
226 int c;
227 int len;
228
229 len = 0;
230 c = *pr_file_p;
231 do
232 {
233 pr_token[len] = c;
234 len++;
235 pr_file_p++;
236 c = *pr_file_p;
237 } while ((c >= '0' && c<= '9') || c == '.');
238 pr_token[len] = 0;
239 return atof (pr_token);
240 }
241
242 /*
243 ==============
244 PR_LexInt
245 ==============
246 */
PR_LexInt(void)247 unsigned int PR_LexInt (void)
248 {
249 int c;
250 int len;
251
252 len = 0;
253 c = *pr_file_p;
254 do
255 {
256 pr_token[len] = c;
257 len++;
258 pr_file_p++;
259 c = *pr_file_p;
260 } while ((c >= '0' && c<= '9') || c == '-');
261 pr_token[len] = 0;
262 return atoi (pr_token);
263 }
264
265 /*
266 ==============
267 PR_LexHex
268 ==============
269 */
PR_LexHex(void)270 unsigned int PR_LexHex (void)
271 {
272 unsigned int c;
273 int len;
274
275 len = 0;
276 pr_file_p += 2;
277 c = *pr_file_p;
278 do
279 {
280 pr_token[len] = c;
281 len++;
282 pr_file_p++;
283 c = *pr_file_p;
284 } while ((c >= '0' && c<= '9') || (c >= 'a' && c <= 'f'));
285 pr_token[len] = 0;
286 sscanf(pr_token, "%x", &c);
287 return c;
288 }
289
290 /*
291 ==============
292 PR_LexVector
293
294 Parses a single quoted vector
295 ==============
296 */
PR_LexVector(void)297 void PR_LexVector (void)
298 {
299 int i;
300
301 pr_file_p++;
302 pr_token_type = tt_immediate;
303 pr_immediate_type = &type_vector;
304 for (i=0 ; i<3 ; i++)
305 {
306 pr_immediate.vector[i] = PR_LexNumber ();
307 PR_LexWhitespace ();
308 }
309 if (*pr_file_p != '\'')
310 PR_ParseError ("Bad vector");
311 pr_file_p++;
312 }
313
314 boolean PR_FindMacro (void);
315 /*
316 ==============
317 PR_LexName
318
319 Parses an identifier
320 ==============
321 */
PR_LexName(void)322 void PR_LexName (void)
323 {
324 int c;
325 int len;
326 def_t *d;
327 len = 0;
328 c = *pr_file_p;
329
330 do
331 {
332 pr_token[len] = c;
333 len++;
334 pr_file_p++;
335 c = *pr_file_p;
336 } while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
337 || (c >= '0' && c <= '9'));
338
339 pr_token[len] = 0;
340 // PR_FindMacro();
341 pr_token_type = tt_name;
342
343 d = PR_GetDef(NULL, pr_token, pr_scope, false, 0, 0);
344 if (d)
345 {
346 memcpy (&pr_immediate, pr_globals + d->ofs, 4*type_size[d->type->type]);
347 pr_immediate_type = d->type;
348 }
349
350 }
351
352 /*
353 ==============
354 PR_LexPunctuation
355 ==============
356 */
PR_LexPunctuation(void)357 void PR_LexPunctuation (void)
358 {
359 int i;
360 char *p;
361 int len;
362
363 pr_token_type = tt_punct;
364
365 for (i=0; (p = pr_punctuation[i]) != NULL; i++)
366 {
367 len = pr_punct_length[i];
368 if (!STRNCMP(p, pr_file_p, len) )
369 {
370 memcpy(pr_token, p, len+1);
371 if (p[0] == '{')
372 pr_bracelevel++;
373 else if (p[0] == '}')
374 {
375 pr_bracelevel--;
376 if (pr_bracelevel < 0)
377 {
378 PR_ParseWarning(1, "Too many closing braces");
379 pr_bracelevel = 0;
380 }
381 }
382 pr_file_p += len;
383 return;
384 }
385 }
386
387 PR_ParseError ("Unknown punctuation");
388 }
389
390
391 /*
392 ==============
393 PR_LexWhitespace
394 ==============
395 */
PR_LexWhitespace(void)396 void PR_LexWhitespace (void)
397 {
398 int c;
399
400 while (1)
401 {
402 // skip whitespace
403 while ( (c = *pr_file_p) <= ' ')
404 {
405 if (c=='\n')
406 PR_NewLine ();
407 if (c == 0)
408 return; // end of file
409 pr_file_p++;
410 }
411
412 // skip // comments
413 if (c=='/' && pr_file_p[1] == '/')
414 {
415 // if (pr_file_p[2] == '^')
416 // pr_file_p++;
417 while (*pr_file_p && *pr_file_p != '\n')
418 pr_file_p++;
419 if (*pr_file_p == 0)
420 return;
421 PR_NewLine();
422 pr_file_p++;
423 continue;
424 }
425
426 // skip /* */ comments
427 if (c=='/' && pr_file_p[1] == '*')
428 {
429 do
430 {
431 pr_file_p++;
432 if (pr_file_p[0]=='\n')
433 PR_NewLine();
434 if (!*pr_file_p)
435 return;
436 } while (pr_file_p[-1] != '*' || pr_file_p[0] != '/');
437 pr_file_p++;
438 continue;
439 }
440
441 break; // a real character has been found
442 }
443 }
444
445 //============================================================================
446
447 // just parses text, returning false if an eol is reached
PR_SimpleGetToken(void)448 boolean PR_SimpleGetToken (void)
449 {
450 int c;
451 int i;
452
453 // skip whitespace
454 while ( (c = *pr_file_p) <= ' ')
455 {
456 if (c=='\n' || c == 0)
457 return false;
458 pr_file_p++;
459 }
460 i = 0;
461 while ( (c = *pr_file_p) > ' ' && c != ',' && c != ';' && c != ')')
462 {
463 pr_token[i] = c;
464 i++;
465 pr_file_p++;
466 }
467 pr_token[i] = 0;
468 return true;
469 }
470
471 int pr_nummacros;
472
PR_ClearGrabMacros(void)473 void PR_ClearGrabMacros (void)
474 {
475 pr_nummacros = 0;
476 }
477
PR_FindDefine(char * name)478 int PR_FindDefine (char *name)
479 {
480 int i, h;
481 h = hash(name);
482 i = macrohash[h];
483 if (i && !STRCMP(name, pr_defines[i].name))
484 return i;
485 for (i=num_defines ; i>0 ; i--)
486 {
487 if (!STRCMP (pr_token, pr_defines[i].name))
488 {
489 macrohash[h] = i;
490 return i;
491 }
492 }
493 return 0;
494 }
495
PR_FindMacro(void)496 boolean PR_FindMacro (void)
497 {
498 int i;
499 i = PR_FindDefine(pr_token);
500 if (!i)
501 return false;
502 pr_token_type = tt_immediate;
503 pr_immediate_type = pr_defines[i].type;
504 memcpy(&pr_immediate, &(pr_defines[i].value), sizeof(eval_t));
505 HashImmediate();
506 return true;
507 }
508
509
PR_ParseFrame(void)510 void PR_ParseFrame (void)
511 {
512 while (PR_SimpleGetToken ())
513 {
514 num_defines++;
515 macrohash[hash(pr_token)] = num_defines;
516 pr_defines[num_defines].name = (char *)PR_Malloc(strlen(pr_token) + 1);
517 strcpy(pr_defines[num_defines].name, pr_token);
518 pr_defines[num_defines].value._float = pr_nummacros;
519 pr_defines[num_defines].type = &type_float;
520 pr_nummacros++;
521
522 }
523 }
524
525 /*
526 ==============
527 PR_LexGrab
528
529 Deals with counting sequence numbers and replacing frame macros
530 ==============
531 */
PR_LexGrab(void)532 void PR_LexGrab (void)
533 {
534 pr_file_p++; // skip the $
535 if (!PR_SimpleGetToken ())
536 PR_ParseError ("hanging $");
537
538 // check for $frame
539 if (!STRCMP (pr_token, "frame"))
540 {
541 PR_ParseFrame ();
542 PR_Lex ();
543 }
544 // ignore other known $commands
545 else if (!STRCMP (pr_token, "cd")
546 || !STRCMP (pr_token, "origin")
547 || !STRCMP (pr_token, "base")
548 || !STRCMP (pr_token, "flags")
549 || !STRCMP (pr_token, "scale")
550 || !STRCMP (pr_token, "skin") )
551 { // skip to end of line
552 while (PR_SimpleGetToken ())
553 ;
554 PR_Lex ();
555 }
556 // hexen II commands
557 else if (!STRCMP (pr_token, "framevalue") || !STRCMP(pr_token, "framerestore"))
558 {
559 PR_Lex();
560 pr_nummacros = pr_immediate._float;
561 PR_Lex();
562 }
563 else if (!STRCMP (pr_token, "framesave"))
564 {
565 if (!PR_SimpleGetToken())
566 PR_ParseError("$framesave: bad bookmark");
567
568 num_defines++;
569 pr_defines[num_defines].name = (char *)PR_Malloc(strlen(pr_token) + 1);
570 strcpy(pr_defines[num_defines].name, pr_token);
571 macrohash[hash(pr_token)] = num_defines;
572 PR_Lex();
573 pr_defines[num_defines].type = &type_float;
574 pr_defines[num_defines].value._float = pr_nummacros;
575 PR_Lex();
576 }
577 // look for a frame name macro
578
579 else
580 {
581 if (!PR_FindMacro ())
582 PR_ParseError("Unknown frame macro %s", pr_token);
583
584 }
585 }
586 extern char sourcedir[1024];
587 extern char includedir[1024];
588 extern char destfile[1024];
589 char old_file[1024];
590 extern boolean pr_pause;
591 extern boolean logging;
592
593 //============================================================================
594
595 int ifdefdepth;
596 int ignoredepth;
597
PR_LexPrecomp(void)598 void PR_LexPrecomp (void)
599 {
600 char *oldpos;
601 char *src, *src2;
602 char filename[1024];
603 int backup_line, i;
604
605 // yeah it isn't quite Precompiler is it?
606 pr_file_p++; // skip the hash
607 if (!PR_SimpleGetToken ())
608 PR_ParseError ("invalid precompiler command"); // that's not possible
609
610 if (!STRCMP(pr_token, "ifdef"))
611 {
612
613 if (ifdefdepth > ignoredepth)
614 {
615 ifdefdepth++;
616 return;
617 }
618 ifdefdepth++;
619 ignoredepth = ifdefdepth;
620 PR_Lex();
621 if (!PR_FindDefine(pr_token))
622 {
623 ignoredepth--;
624 while(ifdefdepth > ignoredepth)
625 PR_Lex();
626 return;
627 }
628 PR_Lex();
629 return;
630 }
631 if (!STRCMP(pr_token, "ifndef"))
632 {
633 if (ifdefdepth > ignoredepth)
634 {
635 ifdefdepth++;
636 return;
637 }
638 ifdefdepth++;
639 ignoredepth = ifdefdepth;
640 PR_Lex();
641 if (PR_FindDefine(pr_token))
642 {
643 ignoredepth--;
644 while(ifdefdepth > ignoredepth)
645 PR_Lex();
646 return;
647 }
648 PR_Lex();
649 return;
650 }
651 if (!STRCMP(pr_token, "endif"))
652 {
653 ifdefdepth--;
654 if (ifdefdepth < 0)
655 PR_ParseWarning(1, "too many #endifs");
656 PR_Lex();
657 return;
658 }
659 if (!STRCMP(pr_token, "else"))
660 {
661 if (ifdefdepth != (ignoredepth + 1))
662 {
663 PR_Lex();
664 return;
665 }
666 ignoredepth = ifdefdepth > ignoredepth ? ifdefdepth : ifdefdepth - 1;
667
668 do
669 {
670 PR_Lex();
671 }
672 while(ifdefdepth > ignoredepth);
673 return;
674 }
675
676 if (ifdefdepth > ignoredepth)
677 {
678 // print("ignored %s on %s(%i)", pr_token, s_file + strings, pr_source_line);
679 return;
680 }
681 if (PR_Check("pragma"))
682 {
683 if (PR_Check("message"))
684 {
685 if (pr_immediate_type != &type_string)
686 PR_ParseError("message must be a string");
687 print("%s", pr_immediate_string);
688 PR_Lex();
689 return;
690 }
691
692 if (!STRCMP(pr_token, "PROGS_DAT"))
693 {
694 if (!PR_SimpleGetToken ())
695 PR_ParseError("mangled PROGS_DAT directive");
696 strcpy(destfile, pr_token);
697 // changed output..
698 PR_Lex();
699 return;
700
701 }
702 if (!STRCMP(pr_token, "incudedir"))
703 {
704 if(!PR_SimpleGetToken())
705 PR_ParseError("mangled includedir");
706 strcpy(includedir, pr_token);
707 PR_Lex();
708 return;
709 }
710 PR_ParseWarning(1, "unknown pragma %s", pr_token);
711 // skip to the end of the line
712 while (PR_SimpleGetToken ())
713 ;
714 PR_Lex ();
715 return;
716 }
717 if (!STRCMP(pr_token, "includelist"))
718 {
719
720 while(1)
721 {
722 if(PR_SimpleGetToken())
723 {
724 oldpos = pr_file_p;
725 backup_line = pr_source_line;
726 strcpy(old_file, strings + s_file);
727 if (!STRCMP(pr_token, "#endlist"))
728 break;
729 src2 = pr_token;
730 sprintf (filename, "%s%s", sourcedir, src2);
731 LoadFile (filename, (void **)&src2);
732 print("%s", filename);
733 if(!PR_CompileFile (src2, filename))
734 {
735 EndProgram(false);
736 return;
737 }
738
739 pr_file_p = oldpos; // uhhh
740 pr_source_line = backup_line;
741 s_file = old_file - strings;
742 }
743 else if(!*pr_file_p++)
744 {
745 PR_ParseError("eof in #includelist, terminate with #endlist");
746 }
747 }
748 pr_file_p = oldpos; // uhhh
749 pr_source_line = backup_line;
750 s_file = old_file - strings;
751 PR_Lex();
752 return;
753 }
754 if (!STRCMP(pr_token, "include"))
755 {
756 if(!PR_SimpleGetToken())
757 PR_ParseError("mangled include directive");
758 src2 = pr_token;
759
760 if (pr_token[0] == '\"')
761 {
762 if (pr_file_p[-1] != '\"')
763 PR_ParseError("invalid #include string");
764 src2++;
765 pr_token[strlen(pr_token) - 1] = 0; // testing?
766 sprintf (filename, "%s%s", sourcedir, src2);
767 }
768 else if (pr_token[0] == '<')
769 {
770 if (pr_file_p[-1] != '>')
771 PR_ParseError("invalid #include string");
772 src2++;
773 pr_token[strlen(pr_token) - 1] = 0; // testing?
774 sprintf (filename, "%s%s", includedir, src2);
775 }
776 else
777 sprintf (filename, "%s%s", sourcedir, src2);
778 // back up all global data on current file
779 strcpy(old_file, strings + s_file);
780 oldpos = pr_file_p;
781 backup_line = pr_source_line;
782 // printf ("including %s\n", filename);
783 LoadFile (filename, (void **)&src);
784 if(!PR_CompileFile (src, src2))
785 {
786 EndProgram(false);
787 return;
788 }
789 pr_file_p = oldpos; // uhhh
790 pr_source_line = backup_line;
791 s_file = old_file - strings;
792 PR_Lex();
793 return;
794 }
795 if (PR_Check("error"))
796 {
797 if (pr_immediate_type != &type_string)
798 PR_ParseError("error must be a string");
799 PR_ParseError(pr_immediate_string);
800 PR_Lex();
801 return;
802 }
803 if (PR_Check("warning"))
804 {
805 if (pr_immediate_type != &type_string)
806 PR_ParseError("warning must be a string");
807 PR_ParseWarning(1, pr_immediate_string);
808 PR_Lex();
809 return;
810 }
811 if (PR_Check("define"))
812 {
813 if (pr_token_type != tt_name)
814 PR_ParseError("#define: Invalid name");
815
816 backup_line = pr_source_line;
817 i = ++num_defines;
818 pr_defines[i].name = (char *)PR_Malloc(strlen(pr_token) + 1);
819 macrohash[hash(pr_token)] = i;
820 strcpy(pr_defines[i].name, pr_token);
821 PR_Lex();
822 if (pr_token_type == tt_immediate)
823 {
824 pr_defines[i].type = pr_immediate_type;
825 memcpy(&(pr_defines[i].value), &pr_immediate, sizeof(eval_t));
826 PR_Lex();
827 }
828
829 return;
830 }
831 if (PR_Check("undef"))
832 {
833
834 if (pr_token_type != tt_name)
835 PR_ParseError("#undef: Invalid name");
836 num_defines--;
837 backup_line = PR_FindDefine(pr_token);
838 for(i = backup_line; i <= num_defines; i++)
839 memcpy(&(pr_defines[i]), &(pr_defines[i+1]), sizeof(define_t));
840 for (i = 0; i < HSIZE1; i++)
841 {
842 if (macrohash[i] > backup_line)
843 macrohash[i]--;
844 else if (macrohash[i] == backup_line)
845 macrohash[i] = 0;
846 }
847 PR_Lex();
848 return;
849 }
850
851 if(!PR_FindMacro())
852 {
853 PR_ParseWarning(1, "unknown directive %s", pr_token);
854 }
855
856 }
857
858 /*
859 ==============
860 PR_Lex
861
862 Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
863 ==============
864 */
PR_Lex(void)865 void PR_Lex (void)
866 {
867 int c;
868
869 pr_token[0] = 0;
870 pr_immediate_index = -1;
871
872
873 if (!pr_file_p)
874 {
875 pr_token_type = tt_eof;
876 return;
877 }
878
879 PR_LexWhitespace ();
880
881 c = *pr_file_p;
882
883 if (!c)
884 {
885 pr_token_type = tt_eof;
886 return;
887 }
888
889 // handle quoted strings as a unit
890 if (c == '\"')
891 {
892 PR_LexString ();
893 HashImmediate();
894 return;
895 }
896 if (c == '%')
897 {
898 c = *++pr_file_p;
899 expectint = true;
900 }
901 // handle quoted vectors as a unit
902 if (c == '\'')
903 {
904 if (pr_file_p[2] == '\'')
905 {
906 pr_token_type = tt_immediate;
907 if (expectint)
908 {
909 pr_immediate_type = &type_int;
910 pr_immediate._int = pr_file_p[1];
911 }
912 else
913 {
914 pr_immediate_type = &type_float;
915 pr_immediate._float = pr_file_p[1];
916 }
917 expectint = false;
918 pr_file_p += 3;
919 }
920 else
921 PR_LexVector ();
922 HashImmediate();
923 return;
924 }
925
926 if (c == '0' && pr_file_p[1] == 'x')
927 {
928 pr_token_type = tt_immediate;
929 pr_immediate_type = &type_float;
930 pr_immediate._int = PR_LexHex ();
931 HashImmediate();
932 return;
933 }
934
935 // if the first character is a valid identifier, parse until a non-id
936 // character is reached
937
938 if ( (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') )
939 {
940 pr_token_type = tt_immediate;
941 if (expectint)
942 {
943 pr_immediate_type = &type_int;
944 pr_immediate._int = PR_LexInt ();
945 expectint = false;
946 }
947 else
948 {
949 pr_immediate_type = &type_float;
950 pr_immediate._float = PR_LexNumber ();
951 }
952
953
954 HashImmediate();
955 return;
956 }
957
958 if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
959 {
960 PR_LexName ();
961 return;
962 }
963
964 if (c == '$')
965 {
966 PR_LexGrab ();
967 return;
968 }
969 if (c == '#')
970 {
971 if ( (pr_file_p[1] >= 'a' && pr_file_p[1] <= 'z') || (pr_file_p[1] >= 'A' && pr_file_p[1] <= 'Z') || pr_file_p[1] == '_' )
972 {
973 PR_LexPrecomp();
974 return;
975 }
976 }
977 // parse symbol strings until a non-symbol is found
978 PR_LexPunctuation ();
979 }
980
981 //=============================================================================
982
983 /*
984 ================
985 ErrorLog
986 ================
987 */
988 FILE *logfile;
989
ErrorLog(char * fmt,...)990 void ErrorLog(char *fmt, ...)
991 {
992 va_list argptr;
993 static char data[1024];
994
995
996 va_start(argptr, fmt);
997 vsprintf(data, fmt, argptr);
998 va_end(argptr);
999 if (!logfile)
1000 logfile = Sys_fopen("error.log", "w");
1001 if (!logfile)
1002 Sys_Error("Error writing error.log: %s\nTry using -nolog" , strerror(errno));
1003
1004 fprintf(logfile, data);
1005 //close(f);
1006 }
1007 /*
1008 ============
1009 PR_ParseError
1010
1011 Aborts the current file load
1012 ============
1013 */
1014 boolean logging;
1015 extern char sourcedir[1024];
PR_ParseError(char * error,...)1016 void PR_ParseError (char *error, ...)
1017 {
1018 va_list argptr;
1019 char string[1024];
1020 // *(int *)-4 = 0; // dump to debugger
1021 va_start (argptr,error);
1022 vsprintf (string,error,argptr);
1023 va_end (argptr);
1024
1025 conditional = false;
1026 #ifdef WIN32GUI
1027 ErrorPrint(strings + s_file, pr_source_line, "Error %s(%i): %s", strings + s_file, pr_source_line, string);
1028 #else
1029 print("%s(%i): error: %s", strings + s_file, pr_source_line, string);
1030 #endif
1031 if (logging)
1032 ErrorLog("error: %s:%i:%s\n", strings + s_file, pr_source_line, string);
1033 if (Q_strcmp(s_file + strings, "LINK"))
1034 longjmp (pr_parse_abort, 1);
1035 else
1036 pr_error_count++;
1037
1038
1039 }
1040 /*
1041 ============
1042 PR_ParseWarning
1043
1044
1045 ============
1046 */
1047
1048 int pr_warning_count;
1049
PR_ParseWarning(int level,char * warn,...)1050 void PR_ParseWarning (int level, char *warn, ...)
1051 {
1052 va_list argptr;
1053 char string[1024];
1054 if (level > warninglevel)
1055 return;
1056 va_start (argptr,warn);
1057 vsprintf (string,warn,argptr);
1058 va_end (argptr);
1059
1060 pr_warning_count++;
1061 #ifdef WIN32GUI
1062 ErrorPrint(strings + s_file, pr_source_line, "Warning %s(%i): %s", strings + s_file, pr_source_line, string);
1063 #else
1064 print ("%s(%i): warning: %s", strings + s_file, pr_source_line, string);
1065 #endif
1066 if (logging)
1067 ErrorLog("warning: %s:%i:%s\n", strings + s_file, pr_source_line, string);
1068 }
1069
1070
1071 /*
1072 ============
1073 PR_ParseName
1074
1075 Checks to see if the current token is a valid name
1076 ============
1077 */
PR_ParseName(void)1078 char *PR_ParseName (void)
1079 {
1080 static char ident[MAX_NAME];
1081
1082 if (pr_token_type != tt_name)
1083 PR_ParseError ("\"%s\" is not a name", pr_token);
1084 if (strlen(pr_token) >= MAX_NAME-1)
1085 PR_ParseError ("name too long");
1086 strcpy (ident, pr_token);
1087 PR_Lex ();
1088
1089 return ident;
1090 }
1091
1092 /*
1093 ============
1094 PR_FindType
1095
1096 Returns a preexisting complex type that matches the parm, or allocates
1097 a new one and copies it out.
1098 ============
1099 */
PR_FindType(type_t * type)1100 type_t *PR_FindType (type_t *type)
1101 {
1102 def_t *def;
1103 type_t *check;
1104 int i;
1105
1106 for (check = pr.types ; check ; check = check->next)
1107 {
1108 if (check->type != type->type
1109 || check->aux_type != type->aux_type
1110 || check->num_parms != type->num_parms
1111 || type->arraysize)
1112 continue;
1113
1114 for (i=0 ; i< type->num_parms ; i++)
1115 if (check->parm_types[i] != type->parm_types[i])
1116 break;
1117
1118 if (i == type->num_parms)
1119 return check;
1120 }
1121
1122 // allocate a new one
1123 check = (struct type_s *) PR_Malloc (sizeof (*check));
1124 *check = *type;
1125 check->next = pr.types;
1126 pr.types = check;
1127
1128 // allocate a generic def for the type, so fields can reference it
1129 def = (struct def_s *) PR_Malloc (sizeof(def_t));
1130 def->name = "COMPLEX TYPE";
1131 def->type = check;
1132 check->def = def;
1133 return check;
1134 }
1135
1136
1137 /*
1138 ============
1139 PR_SkipToSemicolon
1140
1141 For error recovery, also pops out of nested braces
1142 ============
1143 */
PR_SkipToSemicolon(void)1144 void PR_SkipToSemicolon (void)
1145 {
1146 do
1147 {
1148 if (!pr_bracelevel)
1149 {
1150 if (PR_Check(";"))
1151 return;
1152 if (PR_Check("}"))
1153 {
1154 PR_Check(";");
1155 return;
1156 }
1157 }
1158
1159 PR_Lex ();
1160 } while (pr_token_type != tt_eof);
1161 }
1162
1163
1164 /*
1165 ============
1166 PR_ParseType
1167
1168 Parses a variable type, including field and functions types
1169 ============
1170 */
1171 char pr_parm_names[MAX_PARMS + MAX_EXTRA_PARMS][MAX_NAME];
1172 type_t *PR_ParseTypeFunction (type_t *type);
1173
PR_ParseType(void)1174 type_t *PR_ParseType (void)
1175 {
1176 type_t newtype;
1177 type_t *type, *insert, *t;
1178
1179 if (PR_Check ("."))
1180 {
1181 memset (&newtype, 0, sizeof(newtype));
1182 newtype.type = ev_field;
1183 newtype.aux_type = PR_ParseType ();
1184 if (newtype.aux_type->arraysize)
1185 PR_ParseError("field arrays not supported");
1186
1187 return PR_FindType (&newtype);
1188 }
1189
1190 if (!STRCMP (pr_token, "float") )
1191 type = &type_float;
1192 else if (!STRCMP (pr_token, "int") )
1193 type = &type_int;
1194 else if (!STRCMP (pr_token, "vector") )
1195 type = &type_vector;
1196 else if (!STRCMP (pr_token, "entity") )
1197 type = &type_entity;
1198 else if (!STRCMP (pr_token, "string") )
1199 type = &type_string;
1200 else if (!STRCMP (pr_token, "void") )
1201 type = &type_void;
1202 else
1203 {
1204 PR_ParseError ("\"%s\" is not a type", pr_token);
1205 type = &type_float; // shut up compiler error
1206 }
1207 PR_Lex ();
1208 if (PR_Check("field"))
1209 {
1210 memset (&newtype, 0, sizeof(newtype));
1211 newtype.type = ev_field;
1212 newtype.aux_type = type;
1213 type = PR_FindType (&newtype);
1214 }
1215 if (PR_Check ("("))
1216 type = PR_ParseTypeFunction (type);
1217 if (PR_Check ("["))
1218 {
1219 memset (&newtype, 0, sizeof(newtype));
1220 newtype.type = ev_void;
1221 if (pr_immediate._float <= 0)
1222 PR_ParseError("Cannot allocate an array of %i", pr_immediate._float);
1223 newtype.arraysize = pr_immediate._float;
1224 PR_Lex();
1225
1226 newtype.aux_type = type;
1227 PR_Expect("]");
1228
1229 type = PR_FindType (&newtype);
1230 insert = type;
1231 while(PR_Check("["))
1232 {
1233 memset (&newtype, 0, sizeof(newtype));
1234 newtype.type = ev_void;
1235 if (pr_immediate._float <= 0)
1236 PR_ParseError("Cannot allocate an array of %i", pr_immediate._float);
1237 newtype.arraysize = pr_immediate._float;
1238 PR_Lex();
1239
1240 newtype.aux_type = insert->aux_type;
1241 PR_Expect("]");
1242 insert->aux_type = PR_FindType (&newtype);
1243 insert = insert->aux_type;
1244 }
1245 }
1246 return type;
1247 }
1248
1249
PR_ParseTypeFunction(type_t * type)1250 type_t *PR_ParseTypeFunction (type_t *type)
1251 {
1252 type_t newtype;
1253 type_t *ttype;
1254 char *name;
1255 static int recurse = 0;
1256
1257 // function type
1258 memset (&newtype, 0, sizeof(newtype));
1259 newtype.type = ev_function;
1260 newtype.aux_type = type; // return type
1261 newtype.num_parms = 0;
1262 if (!PR_Check (")"))
1263 {
1264 do
1265 {
1266 if (PR_Check ("..."))
1267 {
1268 newtype.num_parms = -1 - newtype.num_parms; // variable args
1269 break;
1270 }
1271 else
1272 {
1273 recurse++;
1274 ttype = PR_ParseType ();
1275 recurse--;
1276
1277 if (ttype->type == ev_void)
1278 if (PR_Check(")"))
1279 return PR_FindType (&newtype);
1280 name = PR_ParseName ();
1281 if (!recurse)
1282 strcpy (pr_parm_names[newtype.num_parms], name);
1283 newtype.parm_types[newtype.num_parms] = ttype;
1284 newtype.num_parms++;
1285 }
1286 } while (PR_Check (","));
1287
1288 PR_Expect (")");
1289 }
1290
1291 return PR_FindType (&newtype);
1292 }