1 
2 #include "qcc.h"
3 #include "hash.h"
4 
5 int		pr_source_line;
6 
7 char		*pr_file_p;
8 char		*pr_line_start;		// start of current source line
9 
10 int			pr_bracelevel;
11 
12 char		pr_token[2048];
13 token_type_t	pr_token_type;
14 type_t		*pr_immediate_type;
15 eval_t		pr_immediate;
16 int			pr_immediate_index;
17 
18 char	pr_immediate_string[2048];
19 int		pr_immediate_strlen;
20 
21 int		pr_error_count;
22 
23 char	*pr_punctuation[] =
24 // longer symbols must be before a shorter partial match
25 {";", "(", ")", "==", "=", ",", "...", ".", "{", "}",
26 "[", "]", "+", "*", "-", "!=", "!", "#", "&&", "&",
27 ">=", ">", "<=", "<", "||", "|", "/", ":", "@", "^[", NULL};
28 
29 int	pr_punct_length[] =
30 {1, 1, 1, 2, 1, 1, 3, 1, 1, 1,
31 1, 1, 1, 1, 1, 2, 1, 1, 2, 1,
32 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 0};
33 
34 // simple types.  function types are dynamically allocated
35 type_t	type_void = {ev_void, &def_void};
36 type_t	type_string = {ev_string, &def_string};
37 type_t	type_float = {ev_float, &def_float};
38 type_t	type_vector = {ev_vector, &def_vector};
39 type_t	type_entity = {ev_entity, &def_entity};
40 type_t	type_field = {ev_field, &def_field};
41 type_t	type_function = {ev_function, &def_function,NULL,&type_void};
42 // type_function is a void() function used for state defs
43 type_t	type_pointer = {ev_pointer, &def_pointer};
44 
45 type_t	type_floatfield = {ev_field, &def_field, NULL, &type_float};
46 
47 int		type_size[8] = {1,1,1,3,1,1,1,1};
48 
49 def_t	def_void = {&type_void, "temp"};
50 def_t	def_string = {&type_string, "temp"};
51 def_t	def_float = {&type_float, "temp"};
52 def_t	def_vector = {&type_vector, "temp"};
53 def_t	def_entity = {&type_entity, "temp"};
54 def_t	def_field = {&type_field, "temp"};
55 def_t	def_function = {&type_function, "temp"};
56 def_t	def_pointer = {&type_pointer, "temp"};
57 
58 def_t	def_ret, def_parms[MAX_PARMS];
59 
60 def_t	*def_for_type[8] = {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer};
61 
62 void PR_LexWhitespace (void);
63 
64 
65 /*
66 ==============
67 PR_PrintNextLine
68 ==============
69 */
PR_PrintNextLine(void)70 void PR_PrintNextLine (void)
71 {
72 	char	*t;
73 
74 	printf ("%3i:",pr_source_line);
75 	for (t=pr_line_start ; *t && *t != '\n' ; t++)
76 		printf ("%c",*t);
77 	printf ("\n");
78 }
79 
80 /*
81 ==============
82 PR_NewLine
83 
84 Call at start of file and when *pr_file_p == '\n'
85 ==============
86 */
PR_NewLine(void)87 void PR_NewLine (void)
88 {
89 	boolean	m;
90 
91 	if (*pr_file_p == '\n')
92 	{
93 		pr_file_p++;
94 		m = true;
95 	}
96 	else
97 		m = false;
98 
99 	pr_source_line++;
100 	pr_line_start = pr_file_p;
101 
102 //	if (pr_dumpasm)
103 //		PR_PrintNextLine ();
104 	if (m)
105 		pr_file_p--;
106 }
107 
108 /*
109 ==============
110 PR_LexString
111 
112 Parses a quoted string
113 ==============
114 */
PR_LexString(void)115 void PR_LexString (void)
116 {
117 	int		c;
118 	int mask1 = 0;
119 	int mask2;
120 
121 	pr_immediate_strlen = 0;
122 	pr_file_p++;
123 	do
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=='\\')
132 		{	// escape char
133 			mask2 = 0;
134 			c = *pr_file_p++;
135 			if (!c)
136 				PR_ParseError ("EOF inside quote");
137 			if (c == 'n')
138 				c = '\n';
139 			else if (c == '"')
140 				c = '"' | mask1;
141 			else if (c == '\\')
142 				c = '\\' | mask1;
143 			else if (c == 'b')
144 			{
145 				mask1 ^= 128;
146 				continue;
147 			}
148 			else if (c == '[')
149 				c = 16;
150 			else if (c == ']')
151 				c = 17;
152 			else if (c == '.')
153 				c = 28 | mask1;
154 			else if (c == '<')
155 				c = 29;
156 			else if (c == '-')
157 				c = 30;
158 			else if (c == '>')
159 				c = 31;
160 			else if (c >= '0' && c <= '9')
161 				c = 18 + c - '0';
162 			else if (c == '(')
163 				c = 128;
164 			else if (c == '=')
165 				c = 129;
166 			else if (c == ')')
167 				c = 130;
168 			else if (c == '{')
169 			{
170 				int d;
171 				c = 0;
172 				while ((d = *pr_file_p++) != '}')
173 				{
174 					c = c * 10 + d - '0';
175 					if (d < '0' || d > '9' || c > 255)
176 						PR_ParseError("Bad character code");
177 				}
178 			}
179 			else
180 				PR_ParseError ("Unknown escape char");
181 		}
182 		else if (c=='\"')
183 		{
184 			mask1 = 0;
185 			PR_LexWhitespace ();
186 			if (*pr_file_p == ':')
187 			{
188 				pr_file_p++;
189 				pr_token[pr_immediate_strlen++] = 0;
190 				PR_LexWhitespace();
191 			}
192 			if (*pr_file_p != '\"')
193 			{
194 				pr_token[pr_immediate_strlen++] = 0;
195 				pr_token_type = tt_immediate;
196 				pr_immediate_type = &type_string;
197 				memcpy (pr_immediate_string, pr_token, pr_immediate_strlen);
198 				return;
199 			}
200 			pr_file_p++;
201 			continue;
202 		}
203 		pr_token[pr_immediate_strlen++] = c | (mask1 & mask2);
204 	} while (1);
205 }
206 
207 /*
208 ==============
209 PR_LexNumber
210 ==============
211 */
PR_LexNumber(void)212 float PR_LexNumber (void)
213 {
214 	int		c;
215 	int		len;
216 
217 	len = 0;
218 	c = *pr_file_p;
219 	do
220 	{
221 		pr_token[len] = c;
222 		len++;
223 		pr_file_p++;
224 		c = *pr_file_p;
225 	} while ((c >= '0' && c<= '9') || c == '.');
226 	pr_token[len] = 0;
227 	return atof (pr_token);
228 }
229 
230 /*
231 ==============
232 PR_LexInt
233 ==============
234 */
PR_LexInt(void)235 unsigned int PR_LexInt (void)
236 {
237 	int		c;
238 	int		len;
239 
240 	len = 0;
241 	c = *++pr_file_p;
242 	do
243 	{
244 		pr_token[len] = c;
245 		len++;
246 		pr_file_p++;
247 		c = *pr_file_p;
248 	} while ((c >= '0' && c<= '9') || c == '-');
249 	pr_token[len] = 0;
250 	return atoi (pr_token);
251 }
252 
253 /*
254 ==============
255 PR_LexHex
256 ==============
257 */
PR_LexHex(void)258 unsigned int PR_LexHex (void)
259 {
260 	unsigned int		c;
261 	int		len;
262 
263 	len = 0;
264 	pr_file_p += 2;
265 	c = *pr_file_p;
266 	do
267 	{
268 		pr_token[len] = c;
269 		len++;
270 		pr_file_p++;
271 		c = *pr_file_p;
272 	} while ((c >= '0' && c<= '9') || (c >= 'a' && c <= 'f'));
273 	pr_token[len] = 0;
274 	sscanf(pr_token, "%x", &c);
275 	return c;
276 }
277 
278 /*
279 ==============
280 PR_LexVector
281 
282 Parses a single quoted vector
283 ==============
284 */
PR_LexVector(void)285 void PR_LexVector (void)
286 {
287 	int		i;
288 
289 	pr_file_p++;
290 	pr_token_type = tt_immediate;
291 	pr_immediate_type = &type_vector;
292 	for (i=0 ; i<3 ; i++)
293 	{
294 		pr_immediate.vector[i] = PR_LexNumber ();
295 		PR_LexWhitespace ();
296 	}
297 	if (*pr_file_p != '\'')
298 		PR_ParseError ("Bad vector");
299 	pr_file_p++;
300 }
301 
302 /*
303 ==============
304 PR_LexName
305 
306 Parses an identifier
307 ==============
308 */
PR_LexName(void)309 void PR_LexName (void)
310 {
311 	int		c;
312 	int		len;
313 
314 	len = 0;
315 	c = *pr_file_p;
316 	do
317 	{
318 		pr_token[len] = c;
319 		len++;
320 		pr_file_p++;
321 		c = *pr_file_p;
322 	} while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
323 	|| (c >= '0' && c <= '9'));
324 	pr_token[len] = 0;
325 	pr_token_type = tt_name;
326 }
327 
328 /*
329 ==============
330 PR_LexPunctuation
331 ==============
332 */
PR_LexPunctuation(void)333 void PR_LexPunctuation (void)
334 {
335 	int	i;
336 	char	*p;
337 	int	len;
338 
339 	pr_token_type = tt_punct;
340 
341 	for (i=0; (p = pr_punctuation[i]) != NULL; i++)
342 	{
343 		len = pr_punct_length[i];
344 		if (!STRNCMP(p, pr_file_p, len) )
345 		{
346 			memcpy(pr_token, p, len+1);
347 			if (p[0] == '{')
348 				pr_bracelevel++;
349 			else if (p[0] == '}')
350 				pr_bracelevel--;
351 			pr_file_p += len;
352 			return;
353 		}
354 	}
355 
356 	PR_ParseError ("Unknown punctuation");
357 }
358 
359 
360 /*
361 ==============
362 PR_LexWhitespace
363 ==============
364 */
PR_LexWhitespace(void)365 void PR_LexWhitespace (void)
366 {
367 	int		c;
368 
369 	while (1)
370 	{
371 	// skip whitespace
372 		while ( (c = *pr_file_p) <= ' ')
373 		{
374 			if (c=='\n')
375 				PR_NewLine ();
376 			if (c == 0)
377 				return;		// end of file
378 			pr_file_p++;
379 		}
380 
381 	// skip // comments
382 		if (c=='/' && pr_file_p[1] == '/')
383 		{
384 			if (pr_file_p[2] == '^')
385 				pr_file_p++;
386 			while (*pr_file_p && *pr_file_p != '\n')
387 				pr_file_p++;
388 			PR_NewLine();
389 			pr_file_p++;
390 			continue;
391 		}
392 
393 	// skip /* */ comments
394 		if (c=='/' && pr_file_p[1] == '*')
395 		{
396 			do
397 			{
398 				pr_file_p++;
399 				if (pr_file_p[0]=='\n')
400 					PR_NewLine();
401 				if (pr_file_p[1] == 0)
402 					return;
403 			} while (pr_file_p[-1] != '*' || pr_file_p[0] != '/');
404 			pr_file_p++;
405 			continue;
406 		}
407 
408 		break;		// a real character has been found
409 	}
410 }
411 
412 //============================================================================
413 
414 #define	MAX_FRAMES	256
415 
416 char	pr_framemacros[MAX_FRAMES][16];
417 int		pr_nummacros;
418 
PR_ClearGrabMacros(void)419 void PR_ClearGrabMacros (void)
420 {
421 	pr_nummacros = 0;
422 }
423 
PR_FindMacro(void)424 void PR_FindMacro (void)
425 {
426 	int		i;
427 
428 	for (i=0 ; i<pr_nummacros ; i++)
429 		if (!strcmp (pr_token, pr_framemacros[i]))
430 		{
431 			sprintf (pr_token,"%d", i);
432 			pr_token_type = tt_immediate;
433 			pr_immediate_type = &type_float;
434 			pr_immediate._float = i;
435 			return;
436 		}
437 	PR_ParseError ("Unknown frame macro $%s", pr_token);
438 }
439 
440 // just parses text, returning false if an eol is reached
PR_SimpleGetToken(void)441 boolean PR_SimpleGetToken (void)
442 {
443 	int		c;
444 	int		i;
445 
446 // skip whitespace
447 	while ( (c = *pr_file_p) <= ' ')
448 	{
449 		if (c=='\n' || c == 0)
450 			return false;
451 		pr_file_p++;
452 	}
453 
454 	i = 0;
455 	while ( (c = *pr_file_p) > ' ' && c != ',' && c != ';')
456 	{
457 		pr_token[i] = c;
458 		i++;
459 		pr_file_p++;
460 	}
461 	pr_token[i] = 0;
462 	return true;
463 }
464 
PR_ParseFrame(void)465 void PR_ParseFrame (void)
466 {
467 	while (PR_SimpleGetToken ())
468 	{
469 		strcpy (pr_framemacros[pr_nummacros], pr_token);
470 		pr_nummacros++;
471 	}
472 }
473 
474 /*
475 ==============
476 PR_LexGrab
477 
478 Deals with counting sequence numbers and replacing frame macros
479 ==============
480 */
PR_LexGrab(void)481 void PR_LexGrab (void)
482 {
483 	pr_file_p++;	// skip the $
484 	if (!PR_SimpleGetToken ())
485 		PR_ParseError ("hanging $");
486 
487 // check for $frame
488 	if (!STRCMP (pr_token, "frame"))
489 	{
490 		PR_ParseFrame ();
491 		PR_Lex ();
492 	}
493 // ignore other known $commands
494 	else if (!STRCMP (pr_token, "cd")
495 	|| !STRCMP (pr_token, "origin")
496 	|| !STRCMP (pr_token, "base")
497 	|| !STRCMP (pr_token, "flags")
498 	|| !STRCMP (pr_token, "scale")
499 	|| !STRCMP (pr_token, "skin") )
500 	{	// skip to end of line
501 		while (PR_SimpleGetToken ())
502 		;
503 		PR_Lex ();
504 	}
505 // look for a frame name macro
506 	else
507 		PR_FindMacro ();
508 }
509 
510 //============================================================================
511 
512 /*
513 ==============
514 PR_Lex
515 
516 Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
517 ==============
518 */
PR_Lex(void)519 void PR_Lex (void)
520 {
521 	int		c;
522 
523 	pr_token[0] = 0;
524 	pr_immediate_index = -1;
525 
526 
527 	if (!pr_file_p)
528 	{
529 		pr_token_type = tt_eof;
530 		return;
531 	}
532 
533 	PR_LexWhitespace ();
534 
535 	c = *pr_file_p;
536 
537 	if (!c)
538 	{
539 		pr_token_type = tt_eof;
540 		return;
541 	}
542 
543 // handle quoted strings as a unit
544 	if (c == '\"')
545 	{
546 		PR_LexString ();
547 		HashImmediate();
548 		return;
549 	}
550 
551 // handle quoted vectors as a unit
552 	if (c == '\'')
553 	{
554 		if (pr_file_p[2] == '\'')
555 		{
556 			pr_token_type = tt_immediate;
557 			pr_immediate_type = &type_float;
558 			pr_immediate._int = pr_file_p[1];
559 			pr_file_p += 3;
560 		}
561 		else
562 			PR_LexVector ();
563 		HashImmediate();
564 		return;
565 	}
566 
567 	if (c == '0' && pr_file_p[1] == 'x')
568 	{
569 		pr_token_type = tt_immediate;
570 		pr_immediate_type = &type_float;
571 		pr_immediate._int = PR_LexHex ();
572 		HashImmediate();
573 		return;
574 	}
575 
576 // if the first character is a valid identifier, parse until a non-id
577 // character is reached
578 	if ( (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') )
579 	{
580 		pr_token_type = tt_immediate;
581 		pr_immediate_type = &type_float;
582 		pr_immediate._float = PR_LexNumber ();
583 		HashImmediate();
584 		return;
585 	}
586 
587 	if (c == '%')
588 	{
589 		pr_token_type = tt_immediate;
590 		pr_immediate_type = &type_float;
591 		pr_immediate._int = PR_LexInt ();
592 		HashImmediate();
593 		return;
594 	}
595 
596 	if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
597 	{
598 		PR_LexName ();
599 		return;
600 	}
601 
602 	if (c == '$')
603 	{
604 		PR_LexGrab ();
605 		if (pr_token_type == tt_immediate)
606 			HashImmediate();
607 		return;
608 	}
609 
610 // parse symbol strings until a non-symbol is found
611 	PR_LexPunctuation ();
612 }
613 
614 //=============================================================================
615 
616 /*
617 ============
618 PR_ParseError
619 
620 Aborts the current file load
621 ============
622 */
PR_ParseError(char * error,...)623 void PR_ParseError (char *error, ...)
624 {
625 	va_list		argptr;
626 	char		string[1024];
627 
628 	va_start (argptr,error);
629 	vsprintf (string,error,argptr);
630 	va_end (argptr);
631 
632 	printf ("%s:%i:%s\n", strings + s_file, pr_source_line, string);
633 
634 	longjmp (pr_parse_abort, 1);
635 }
636 
637 
638 /*
639 ============
640 PR_ParseName
641 
642 Checks to see if the current token is a valid name
643 ============
644 */
PR_ParseName(void)645 char *PR_ParseName (void)
646 {
647 	static char	ident[MAX_NAME];
648 
649 	if (pr_token_type != tt_name)
650 		PR_ParseError ("not a name");
651 	if (strlen(pr_token) >= MAX_NAME-1)
652 		PR_ParseError ("name too long");
653 	strcpy (ident, pr_token);
654 	PR_Lex ();
655 
656 	return ident;
657 }
658 
659 /*
660 ============
661 PR_FindType
662 
663 Returns a preexisting complex type that matches the parm, or allocates
664 a new one and copies it out.
665 ============
666 */
PR_FindType(type_t * type)667 type_t *PR_FindType (type_t *type)
668 {
669 	def_t	*def;
670 	type_t	*check;
671 	int		i;
672 
673 	for (check = pr.types ; check ; check = check->next)
674 	{
675 		if (check->type != type->type
676 		|| check->aux_type != type->aux_type
677 		|| check->num_parms != type->num_parms)
678 			continue;
679 
680 		for (i=0 ; i< type->num_parms ; i++)
681 			if (check->parm_types[i] != type->parm_types[i])
682 				break;
683 
684 		if (i == type->num_parms)
685 			return check;
686 	}
687 
688 // allocate a new one
689 	check = (struct type_s *) malloc (sizeof (*check));
690 	*check = *type;
691 	check->next = pr.types;
692 	pr.types = check;
693 
694 // allocate a generic def for the type, so fields can reference it
695 	def = (struct def_s *) malloc (sizeof(def_t));
696 	def->name = "COMPLEX TYPE";
697 	def->type = check;
698 	check->def = def;
699 	return check;
700 }
701 
702 
703 /*
704 ============
705 PR_SkipToSemicolon
706 
707 For error recovery, also pops out of nested braces
708 ============
709 */
PR_SkipToSemicolon(void)710 void PR_SkipToSemicolon (void)
711 {
712 	do
713 	{
714 		if (!pr_bracelevel && PR_Check (";"))
715 			return;
716 		PR_Lex ();
717 	} while (pr_token[0]);	// eof will return a null token
718 }
719 
720 
721 /*
722 ============
723 PR_ParseType
724 
725 Parses a variable type, including field and functions types
726 ============
727 */
728 char	pr_parm_names[MAX_PARMS][MAX_NAME];
729 
PR_ParseType(void)730 type_t *PR_ParseType (void)
731 {
732 	type_t	newtype;
733 	type_t	*type;
734 	char	*name;
735 	static int recurse = 0;
736 
737 	if (PR_Check ("."))
738 	{
739 		memset (&newtype, 0, sizeof(newtype));
740 		newtype.type = ev_field;
741 		newtype.aux_type = PR_ParseType ();
742 		return PR_FindType (&newtype);
743 	}
744 
745 	if (!strcmp (pr_token, "float") )
746 		type = &type_float;
747 	else if (!strcmp (pr_token, "vector") )
748 		type = &type_vector;
749 	else if (!strcmp (pr_token, "float") )
750 		type = &type_float;
751 	else if (!strcmp (pr_token, "entity") )
752 		type = &type_entity;
753 	else if (!strcmp (pr_token, "string") )
754 		type = &type_string;
755 	else if (!strcmp (pr_token, "void") )
756 		type = &type_void;
757 	else
758 	{
759 		PR_ParseError ("\"%s\" is not a type", pr_token);
760 		type = &type_float;	// shut up compiler warning
761 	}
762 	PR_Lex ();
763 
764 	if (!PR_Check ("("))
765 		return type;
766 
767 // function type
768 	memset (&newtype, 0, sizeof(newtype));
769 	newtype.type = ev_function;
770 	newtype.aux_type = type;	// return type
771 	newtype.num_parms = 0;
772 	if (!PR_Check (")"))
773 	{
774 		do
775 		{
776 			if (PR_Check ("..."))
777 			{
778 				newtype.num_parms = -1 - newtype.num_parms;	// variable args
779 				break;
780 			}
781 			else
782 			{
783 				recurse++;
784 				type = PR_ParseType ();
785 				recurse--;
786 				name = PR_ParseName ();
787 				if (!recurse)
788 					strcpy (pr_parm_names[newtype.num_parms], name);
789 				newtype.parm_types[newtype.num_parms] = type;
790 				newtype.num_parms++;
791 			}
792 		} while (PR_Check (","));
793 
794 		PR_Expect (")");
795 	}
796 
797 	return PR_FindType (&newtype);
798 }
799 
800