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 }