]> git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/fteqcc-src/qcc_pr_lex.c
Get VoreTournament code to compile with gmqcc. To be compiled with the same parameter...
[voretournament/voretournament.git] / misc / source / fteqcc-src / qcc_pr_lex.c
1 #ifndef MINIMAL
2
3 #include "qcc.h"
4 #ifdef QCC
5 #define print printf
6 #endif
7 #include "time.h"
8
9 #ifdef _WIN64
10         #ifdef _SDL
11                 #define snprintf linuxlike_snprintf
12                 int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
13                 #define vsnprintf linuxlike_vsnprintf
14                 int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
15                 //void *__imp__vsnprintf = vsnprintf;
16         #endif
17 #endif
18
19 #define MEMBERFIELDNAME "__m%s"
20
21 #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1))     //saves about 2-6 out of 120 - expansion of idea from fastqcc
22
23 void QCC_PR_ConditionCompilation(void);
24 pbool QCC_PR_UndefineName(char *name);
25 char *QCC_PR_CheakCompConstString(char *def);
26 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def);
27 pbool QCC_Include(char *filename);
28
29 char *compilingfile;
30
31 int                     pr_source_line;
32
33 char            *pr_file_p;
34 char            *pr_line_start;         // start of current source line
35
36 int                     pr_bracelevel;
37
38 char            pr_token[8192];
39 token_type_t    pr_token_type;
40 QCC_type_t              *pr_immediate_type;
41 QCC_eval_t              pr_immediate;
42
43 char    pr_immediate_string[8192];
44
45 int             pr_error_count;
46 int             pr_warning_count;
47
48
49 CompilerConstant_t *CompilerConstant;
50 int numCompilerConstants;
51 extern pbool expandedemptymacro;
52
53
54
55 char    *pr_punctuation[] =
56 // longer symbols must be before a shorter partial match
57 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
58
59 char *pr_punctuationremap[] =   //a nice bit of evilness.
60 //(+) -> |=
61 //-> -> .
62 //(-) -> &~=
63 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=",  "&~=", "|=", "&~=", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
64
65 // simple types.  function types are dynamically allocated
66 QCC_type_t      *type_void;// = {ev_void/*, &def_void*/};
67 QCC_type_t      *type_string;// = {ev_string/*, &def_string*/};
68 QCC_type_t      *type_float;// = {ev_float/*, &def_float*/};
69 QCC_type_t      *type_vector;// = {ev_vector/*, &def_vector*/};
70 QCC_type_t      *type_entity;// = {ev_entity/*, &def_entity*/};
71 QCC_type_t      *type_field;// = {ev_field/*, &def_field*/};
72 QCC_type_t      *type_function;// = {ev_function/*, &def_function*/,NULL,&type_void};
73 // type_function is a void() function used for state defs
74 QCC_type_t      *type_pointer;// = {ev_pointer/*, &def_pointer*/};
75 QCC_type_t      *type_integer;// = {ev_integer/*, &def_integer*/};
76 QCC_type_t      *type_variant;// = {ev_integer/*, &def_integer*/};
77 QCC_type_t      *type_floatpointer;
78 QCC_type_t      *type_intpointer;
79
80 QCC_type_t      *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float};
81
82 /*QCC_def_t     def_void = {type_void, "temp"};
83 QCC_def_t       def_string = {type_string, "temp"};
84 QCC_def_t       def_float = {type_float, "temp"};
85 QCC_def_t       def_vector = {type_vector, "temp"};
86 QCC_def_t       def_entity = {type_entity, "temp"};
87 QCC_def_t       def_field = {type_field, "temp"};
88 QCC_def_t       def_function = {type_function, "temp"};
89 QCC_def_t       def_pointer = {type_pointer, "temp"};
90 QCC_def_t       def_integer = {type_integer, "temp"};
91 */
92 QCC_def_t       def_ret, def_parms[MAX_PARMS];
93
94 //QCC_def_t     *def_for_type[9] = {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer, &def_integer};
95
96 void QCC_PR_LexWhitespace (void);
97
98
99
100
101 //for compiler constants and file includes.
102
103 qcc_includechunk_t *currentchunk;
104 void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst)
105 {
106         qcc_includechunk_t *chunk = qccHunkAlloc(sizeof(qcc_includechunk_t));
107         chunk->prev = currentchunk;
108         currentchunk = chunk;
109
110         chunk->currentdatapoint = pr_file_p;
111         chunk->currentlinenumber = pr_source_line;
112         chunk->cnst = cnst;
113         if( cnst )
114         {
115                 cnst->inside++;
116         }
117
118         if (duplicate)
119         {
120                 pr_file_p = qccHunkAlloc(strlen(data)+1);
121                 strcpy(pr_file_p, data);
122         }
123         else
124                 pr_file_p = data;
125 }
126 void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename)
127 {
128         QCC_PR_IncludeChunkEx(data, duplicate, filename, NULL);
129 }
130
131 pbool QCC_PR_UnInclude(void)
132 {
133         if (!currentchunk)
134                 return false;
135
136         if( currentchunk->cnst )
137                 currentchunk->cnst->inside--;
138
139         pr_file_p = currentchunk->currentdatapoint;
140         pr_source_line = currentchunk->currentlinenumber;
141
142         currentchunk = currentchunk->prev;
143
144         return true;
145 }
146
147
148 /*
149 ==============
150 PR_PrintNextLine
151 ==============
152 */
153 void QCC_PR_PrintNextLine (void)
154 {
155         char    *t;
156
157         printf ("%3i:",pr_source_line);
158         for (t=pr_line_start ; *t && *t != '\n' ; t++)
159                 printf ("%c",*t);
160         printf ("\n");
161 }
162
163 extern char qccmsourcedir[];
164 //also meant to include it.
165 void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
166 {
167         char fullname[1024];
168         int doubledots;
169
170         char *end = fullname;
171
172         if (!*newfile)
173                 return;
174
175         doubledots = 0;
176         /*count how far up we need to go*/
177         while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
178         {
179                 newfile+=3;
180                 doubledots++;
181         }
182
183         currentfile += strlen(rootpath);        //could this be bad?
184
185         strcpy(fullname, rootpath);
186         end = fullname+strlen(end);
187         if (*fullname && end[-1] != '/')
188         {
189                 strcpy(end, "/");
190                 end = end+strlen(end);
191         }
192         strcpy(end, currentfile);
193         end = end+strlen(end);
194
195         while (end > fullname)
196         {
197                 end--;
198                 /*stop at the slash, unless we're meant to go further*/
199                 if (*end == '/' || *end == '\\')
200                 {
201                         if (!doubledots)
202                         {
203                                 end++;
204                                 break;
205                         }
206                         doubledots--;
207                 }
208         }
209
210         strcpy(end, newfile);
211
212         QCC_Include(fullname);
213 }
214
215 pbool defaultnoref;
216 pbool defaultstatic;
217 int ForcedCRC;
218 int QCC_PR_LexInteger (void);
219 void    QCC_AddFile (char *filename);
220 void QCC_PR_LexString (void);
221 pbool QCC_PR_SimpleGetToken (void);
222
223 int ParsePrecompilerIf(void)
224 {
225         CompilerConstant_t *c;
226         int eval = 0;
227         pbool notted = false;
228         
229         /*skip whitespace*/
230         while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n')
231         {
232                 pr_file_p++;
233         }
234         if (*pr_file_p == '!')
235         {
236                 pr_file_p++;
237                 notted = true;
238                 while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n')
239                 {
240                         pr_file_p++;
241                 }
242         }
243
244         if (!QCC_PR_SimpleGetToken())
245         {
246                 if (*pr_file_p == '(')
247                 {
248                         pr_file_p++;
249                         eval = ParsePrecompilerIf();
250                         while (*pr_file_p == ' ' || *pr_file_p == '\t')
251                                 pr_file_p++;
252                         if (*pr_file_p != ')')
253                                 QCC_PR_ParseError(ERR_EXPECTED, "unclosed bracket condition\n");
254                         pr_file_p++;
255                 }
256                 else
257                         QCC_PR_ParseError(ERR_EXPECTED, "expected bracket or constant\n");
258         }
259         else if (!strcmp(pr_token, "defined"))
260         {
261                 while (*pr_file_p == ' ' || *pr_file_p == '\t')
262                         pr_file_p++;
263                 if (*pr_file_p != '(')
264                         QCC_PR_ParseError(ERR_EXPECTED, "no opening bracket after defined\n");
265                 else
266                 {
267                         pr_file_p++;
268
269                         QCC_PR_SimpleGetToken();
270                         eval = !!QCC_PR_CheckCompConstDefined(pr_token);
271
272                         while (*pr_file_p == ' ' || *pr_file_p == '\t')
273                                 pr_file_p++;
274                         if (*pr_file_p != ')')
275                                 QCC_PR_ParseError(ERR_EXPECTED, "unclosed defined condition\n");
276                         pr_file_p++;
277                 }
278         }
279         else
280         {
281                 c = QCC_PR_CheckCompConstDefined(pr_token);
282                 if (!c)
283                         eval = atoi(pr_token);
284                 else
285                         eval = atoi(c->value);
286         }
287
288         if (notted)
289                 eval = !eval;
290
291         QCC_PR_SimpleGetToken();
292         if (!strcmp(pr_token, "||"))
293                 eval = ParsePrecompilerIf()||eval;
294         else if (!strcmp(pr_token, "&&"))
295                 eval = ParsePrecompilerIf()&&eval;
296         else if (!strcmp(pr_token, "<="))
297                 eval = eval <= ParsePrecompilerIf();
298         else if (!strcmp(pr_token, ">="))
299                 eval = eval >= ParsePrecompilerIf();
300         else if (!strcmp(pr_token, "<"))
301                 eval = eval < ParsePrecompilerIf();
302         else if (!strcmp(pr_token, ">"))
303                 eval = eval > ParsePrecompilerIf();
304         else if (!strcmp(pr_token, "!="))
305                 eval = eval != ParsePrecompilerIf();
306
307         return eval;
308 }
309 /*
310 ==============
311 QCC_PR_Precompiler
312 ==============
313
314 Runs precompiler stage
315 */
316 pbool QCC_PR_Precompiler(void)
317 {
318         char msg[1024];
319         int ifmode;
320         int a;
321         static int ifs = 0;
322         int level;      //#if level
323         pbool eval = false;
324
325         if (*pr_file_p == '#')
326         {
327                 char *directive;
328                 for (directive = pr_file_p+1; *directive; directive++)  //so #    define works
329                 {
330                         if (*directive == '\r' || *directive == '\n')
331                                 QCC_PR_ParseError(ERR_UNKNOWNPUCTUATION, "Hanging # with no directive\n");
332                         if (*directive > ' ')
333                                 break;
334                 }
335                 if (!strncmp(directive, "define", 6))
336                 {
337                         pr_file_p = directive;
338                         QCC_PR_ConditionCompilation();
339                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
340                         {
341                                 pr_file_p++;
342                         }
343                 }
344                 else if (!strncmp(directive, "undef", 5))
345                 {
346                         pr_file_p = directive+5;
347                         while(*pr_file_p <= ' ')
348                                 pr_file_p++;
349
350                         QCC_PR_SimpleGetToken ();
351                         QCC_PR_UndefineName(pr_token);
352
353         //              QCC_PR_ConditionCompilation();
354                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
355                         {
356                                 pr_file_p++;
357                         }
358                 }
359                 else if (!strncmp(directive, "if", 2))
360                 {
361                         int originalline = pr_source_line;
362                         pr_file_p = directive+2;
363                         if (!strncmp(pr_file_p, "def ", 4))
364                         {
365                                 ifmode = 0;
366                                 pr_file_p+=4;
367                         }
368                         else if (!strncmp(pr_file_p, "ndef ", 5))
369                         {
370                                 ifmode = 1;
371                                 pr_file_p+=5;
372                         }
373                         else
374                         {
375                                 ifmode = 2;
376                                 pr_file_p+=0;
377                                 //QCC_PR_ParseError("bad \"#if\" type");
378                         }
379
380                         if (ifmode == 2)
381                         {
382                                 eval = ParsePrecompilerIf();
383
384                                 if(*pr_file_p != '\n' && *pr_file_p != '\0')    //read on until the end of the line
385                                 {
386                                         QCC_PR_ParseError (ERR_NOENDIF, "junk on the end of #if line");
387                                 }
388                         }
389                         else
390                         {
391                                 QCC_PR_SimpleGetToken ();
392
393         //                      if (!STRCMP(pr_token, "COOP_MODE"))
394         //                              eval = false;
395                                 if (QCC_PR_CheckCompConstDefined(pr_token))
396                                         eval = true;
397
398                                 if (ifmode == 1)
399                                         eval = eval?false:true;
400                         }
401
402                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
403                         {
404                                 pr_file_p++;
405                         }
406                         level = 1;
407
408                         if (eval)
409                                 ifs+=1;
410                         else
411                         {
412                                 while (1)
413                                 {
414                                         while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
415                                                 pr_file_p++;
416
417                                         if (!*pr_file_p)
418                                         {
419                                                 pr_source_line = originalline;
420                                                 QCC_PR_ParseError (ERR_NOENDIF, "#if with no endif");
421                                         }
422
423                                         if (*pr_file_p == '#')
424                                         {
425                                                 pr_file_p++;
426                                                 while(*pr_file_p==' ' || *pr_file_p == '\t')
427                                                         pr_file_p++;
428                                                 if (!strncmp(pr_file_p, "endif", 5))
429                                                         level--;
430                                                 if (!strncmp(pr_file_p, "if", 2))
431                                                         level++;
432                                                 if (!strncmp(pr_file_p, "else", 4) && level == 1)
433                                                 {
434                                                         ifs+=1;
435                                                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
436                                                         {
437                                                                 pr_file_p++;
438                                                         }
439                                                         break;
440                                                 }
441                                         }
442
443                                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
444                                         {
445                                                 pr_file_p++;
446                                         }
447                                         if (level <= 0)
448                                                 break;
449                                         pr_file_p++;    //next line
450                                         pr_source_line++;
451                                 }
452                         }
453                 }
454                 else if (!strncmp(directive, "else", 4))
455                 {
456                         int originalline = pr_source_line;
457
458                         ifs -= 1;
459                         level = 1;
460
461                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
462                         {
463                                 pr_file_p++;
464                         }
465                         while (1)
466                         {
467                                 while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
468                                         pr_file_p++;
469
470                                 if (!*pr_file_p)
471                                 {
472                                         pr_source_line = originalline;
473                                         QCC_PR_ParseError(ERR_NOENDIF, "#if with no endif");
474                                 }
475
476                                 if (*pr_file_p == '#')
477                                 {
478                                         pr_file_p++;
479                                         while(*pr_file_p==' ' || *pr_file_p == '\t')
480                                                 pr_file_p++;
481
482                                         if (!strncmp(pr_file_p, "endif", 5))
483                                                 level--;
484                                         if (!strncmp(pr_file_p, "if", 2))
485                                                         level++;
486                                         if (!strncmp(pr_file_p, "else", 4) && level == 1)
487                                         {
488                                                 ifs+=1;
489                                                 break;
490                                         }
491                                 }
492
493                                 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
494                                 {
495                                         pr_file_p++;
496                                 }
497                                 if (level <= 0)
498                                         break;
499                                 pr_file_p++;    //go off the end
500                                 pr_source_line++;
501                         }
502                 }
503                 else if (!strncmp(directive, "endif", 5))
504                 {
505                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
506                         {
507                                 pr_file_p++;
508                         }
509                         if (ifs <= 0)
510                                 QCC_PR_ParseError(ERR_NOPRECOMPILERIF, "unmatched #endif");
511                         else
512                                 ifs-=1;
513                 }
514                 else if (!strncmp(directive, "eof", 3))
515                 {
516                         pr_file_p = NULL;
517                         return true;
518                 }
519                 else if (!strncmp(directive, "error", 5))
520                 {
521                         pr_file_p = directive+5;
522                         for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
523                                 msg[a] = pr_file_p[a];
524
525                         msg[a] = '\0';
526
527                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line, yes, I KNOW we are going to register an error, and not properly leave this function tree, but...
528                         {
529                                 pr_file_p++;
530                         }
531
532                         QCC_PR_ParseError(ERR_HASHERROR, "#Error: %s", msg);
533                 }
534                 else if (!strncmp(directive, "warning", 7))
535                 {
536                         pr_file_p = directive+7;
537                         for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
538                                 msg[a] = pr_file_p[a];
539
540                         msg[a-1] = '\0';
541
542                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
543                         {
544                                 pr_file_p++;
545                         }
546
547                         QCC_PR_ParseWarning(WARN_PRECOMPILERMESSAGE, "#warning: %s", msg);
548                 }
549                 else if (!strncmp(directive, "message", 7))
550                 {
551                         pr_file_p = directive+7;
552                         for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
553                                 msg[a] = pr_file_p[a];
554
555                         msg[a-1] = '\0';
556
557                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
558                         {
559                                 pr_file_p++;
560                         }
561
562                         printf("#message: %s\n", msg);
563                 }
564                 else if (!strncmp(directive, "copyright", 9))
565                 {
566                         pr_file_p = directive+9;
567                         for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
568                                 msg[a] = pr_file_p[a];
569
570                         msg[a-1] = '\0';
571
572                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
573                         {
574                                 pr_file_p++;
575                         }
576
577                         if (strlen(msg) >= sizeof(QCC_copyright))
578                                 QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n");
579                         strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1);
580                 }
581                 else if (!strncmp(directive, "pack", 4))
582                 {
583                         ifmode = 0;
584                         pr_file_p=directive+4;
585                         if (!strncmp(pr_file_p, "id", 2))
586                                 pr_file_p+=3;
587                         else
588                         {
589                                 ifmode = QCC_PR_LexInteger();
590                                 if (ifmode == 0)
591                                         ifmode = 1;
592                                 pr_file_p++;
593                         }
594                         for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
595                                 msg[a] = pr_file_p[a];
596
597                         msg[a-1] = '\0';
598
599                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
600                         {
601                                 pr_file_p++;
602                         }
603
604                         if (ifmode == 0)
605                                 QCC_packid = atoi(msg);
606                         else if (ifmode <= 5)
607                                 strcpy(QCC_Packname[ifmode-1], msg);
608                         else
609                                 QCC_PR_ParseError(ERR_TOOMANYPACKFILES, "No more than 5 packs are allowed");
610                 }
611                 else if (!strncmp(directive, "forcecrc", 8))
612                 {
613                         pr_file_p=directive+8;
614
615                         ForcedCRC = QCC_PR_LexInteger();
616
617                         pr_file_p++;
618
619                         for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
620                                 msg[a] = pr_file_p[a];
621
622                         msg[a-1] = '\0';
623
624                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
625                         {
626                                 pr_file_p++;
627                         }
628                 }
629                 else if (!strncmp(directive, "includelist", 11))
630                 {
631                         pr_file_p=directive+11;
632
633                         while(*pr_file_p <= ' ')
634                                 pr_file_p++;
635
636                         while(1)
637                         {
638                                 QCC_PR_LexWhitespace();
639                                 if (!QCC_PR_SimpleGetToken())
640                                 {
641                                         if (!*pr_file_p)
642                                                 QCC_Error(ERR_EOF, "eof in includelist");
643                                         else
644                                         {
645                                                 pr_file_p++;
646                                                 pr_source_line++;
647                                         }
648                                         continue;
649                                 }
650                                 if (!strcmp(pr_token, "#endlist"))
651                                         break;
652
653                                 QCC_FindBestInclude(pr_token, compilingfile, qccmsourcedir);
654
655                                 if (*pr_file_p == '\r')
656                                         pr_file_p++;
657
658                                 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
659                                 {
660                                         pr_file_p++;
661                                 }
662                         }
663
664                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
665                         {
666                                 pr_file_p++;
667                         }
668                 }
669                 else if (!strncmp(directive, "include", 7))
670                 {
671                         char sm;
672
673                         pr_file_p=directive+7;
674
675                         while(*pr_file_p <= ' ')
676                                 pr_file_p++;
677
678                         msg[0] = '\0';
679                         if (*pr_file_p == '\"')
680                                 sm = '\"';
681                         else if (*pr_file_p == '<')
682                                 sm = '>';
683                         else
684                         {
685                                 QCC_PR_ParseError(0, "Not a string literal (on a #include)");
686                                 sm = 0;
687                         }
688                         pr_file_p++;
689                         a=0;
690                         while(*pr_file_p != sm)
691                         {
692                                 if (*pr_file_p == '\n')
693                                 {
694                                         QCC_PR_ParseError(0, "#include continued over line boundry\n");
695                                         break;
696                                 }
697                                 msg[a++] = *pr_file_p;
698                                 pr_file_p++;
699                         }
700                         msg[a] = 0;
701
702                         QCC_FindBestInclude(msg, compilingfile, qccmsourcedir);
703
704                         pr_file_p++;
705
706                         while(*pr_file_p != '\n' && *pr_file_p != '\0' && *pr_file_p <= ' ')
707                                 pr_file_p++;
708
709
710                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
711                         {
712                                 pr_file_p++;
713                         }
714                 }
715                 else if (!strncmp(directive, "datafile", 8))
716                 {
717                         pr_file_p=directive+8;
718
719                         while(*pr_file_p <= ' ')
720                                 pr_file_p++;
721
722                         QCC_PR_LexString();
723                         printf("Including datafile: %s\n", pr_token);
724                         QCC_AddFile(pr_token);
725
726                         pr_file_p++;
727
728                         for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
729                                 msg[a] = pr_file_p[a];
730
731                         msg[a-1] = '\0';
732
733                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
734                         {
735                                 pr_file_p++;
736                         }
737                 }
738                 else if (!strncmp(directive, "output", 6))
739                 {
740                         extern char             destfile[1024];
741                         pr_file_p=directive+6;
742
743                         while(*pr_file_p <= ' ')
744                                 pr_file_p++;
745
746                         QCC_PR_LexString();
747                         strcpy(destfile, pr_token);
748                         printf("Outputfile: %s\n", destfile);
749
750                         pr_file_p++;
751
752                         for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
753                                 msg[a] = pr_file_p[a];
754
755                         msg[a-1] = '\0';
756
757                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
758                         {
759                                 pr_file_p++;
760                         }
761                 }
762                 else if (!strncmp(directive, "pragma", 6))
763                 {
764                         pr_file_p=directive+6;
765                         while(*pr_file_p <= ' ')
766                                 pr_file_p++;
767
768                         qcc_token[0] = '\0';
769                         for(a = 0; *pr_file_p != '\n' && *pr_file_p != '\0'; pr_file_p++)       //read on until the end of the line
770                         {
771                                 if ((*pr_file_p == ' ' || *pr_file_p == '\t'|| *pr_file_p == '(') && !*qcc_token)
772                                 {
773                                         msg[a] = '\0';
774                                         strcpy(qcc_token, msg);
775                                         a=0;
776                                         continue;
777                                 }
778                                 msg[a++] = *pr_file_p;
779                         }
780
781                         msg[a] = '\0';
782                         {
783                                 char *end;
784                                 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
785                                         *end = '\0';
786                         }
787
788                         if (!*qcc_token)
789                         {
790                                 strcpy(qcc_token, msg);
791                                 msg[0] = '\0';
792                         }
793
794                         {
795                                 char *end;
796                                 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
797                                         *end = '\0';
798                         }
799
800                         if (!QC_strcasecmp(qcc_token, "DONT_COMPILE_THIS_FILE"))
801                         {
802                                 while (*pr_file_p)
803                                 {
804                                         while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
805                                                 pr_file_p++;
806
807                                         if (*pr_file_p == '\n')
808                                         {
809                                                 pr_file_p++;
810                                                 QCC_PR_NewLine(false);
811                                         }
812                                 }
813                         }
814                         else if (!QC_strcasecmp(qcc_token, "COPYRIGHT"))
815                         {
816                                 if (strlen(msg) >= sizeof(QCC_copyright))
817                                         QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n");
818                                 strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1);
819                         }
820                         else if (!strncmp(qcc_token, "compress", 8))
821                         {
822                                 extern pbool compressoutput;
823                                 compressoutput = atoi(msg);
824                         }
825                         else if (!strncmp(qcc_token, "forcecrc", 8))
826                         {
827                                 ForcedCRC = atoi(msg);
828                         }
829                         else if (!strncmp(qcc_token, "noref", 8))
830                         {
831                                 defaultnoref = atoi(msg);
832                         }
833                         else if (!strncmp(qcc_token, "defaultstatic", 13))
834                         {
835                                 defaultstatic = atoi(msg);
836                         }
837                         else if (!strncmp(qcc_token, "wrasm", 5))
838                         {
839                                 pbool on = atoi(msg);
840
841                                 if (asmfile && !on)
842                                 {
843                                         fclose(asmfile);
844                                         asmfile = NULL;
845                                 }                       
846                                 if (!asmfile && on)
847                                         asmfile = fopen("qc.asm", "wb");
848                         }
849                         else if (!strncmp(qcc_token, "sourcefile", 10))
850                         {
851         #define MAXSOURCEFILESLIST 8
852         extern char sourcefileslist[MAXSOURCEFILESLIST][1024];
853         //extern int currentsourcefile; // warning: unused variable Ã¢currentsourcefileâ
854         extern int numsourcefiles;
855
856                                 int i;
857
858                                 QCC_COM_Parse(msg);
859
860                                 for (i = 0; i < numsourcefiles; i++)
861                                 {
862                                         if (!strcmp(sourcefileslist[i], qcc_token))
863                                                 break;
864                                 }
865                                 if (i == numsourcefiles && numsourcefiles < MAXSOURCEFILESLIST)
866                                         strcpy(sourcefileslist[numsourcefiles++], qcc_token);
867                         }
868                         else if (!QC_strcasecmp(qcc_token, "TARGET"))
869                         {
870                                 if (qcc_targetformat == QCF_HEXEN2 && numstatements)
871                                         QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch from hexen2 target \'%s\'. Ignored.", msg);
872                                 else if (!QC_strcasecmp(msg, "H2") || !QC_strcasecmp(msg, "HEXEN2"))
873                                 {
874                                         if (numstatements)
875                                                 QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch to hexen2 target \'%s\'. Ignored.", msg);
876                                         else
877                                                 qcc_targetformat = QCF_HEXEN2;
878                                 }
879                                 else if (!QC_strcasecmp(msg, "KK7"))
880                                         qcc_targetformat = QCF_KK7;
881                                 else if (!QC_strcasecmp(msg, "DP") || !QC_strcasecmp(msg, "DARKPLACES"))
882                                         qcc_targetformat = QCF_DARKPLACES;
883                                 else if (!QC_strcasecmp(msg, "FTEDEBUG"))
884                                         qcc_targetformat = QCF_FTEDEBUG;
885                                 else if (!QC_strcasecmp(msg, "FTE"))
886                                         qcc_targetformat = QCF_FTE;
887                                 else if (!QC_strcasecmp(msg, "STANDARD") || !QC_strcasecmp(msg, "ID"))
888                                         qcc_targetformat = QCF_STANDARD;
889                                 else if (!QC_strcasecmp(msg, "DEBUG"))
890                                         qcc_targetformat = QCF_FTEDEBUG;
891                                 else if (!QC_strcasecmp(msg, "QTEST"))
892                                         qcc_targetformat = QCF_QTEST;
893                                 else
894                                         QCC_PR_ParseWarning(WARN_BADTARGET, "Unknown target \'%s\'. Ignored.", msg);
895                         }
896                         else if (!QC_strcasecmp(qcc_token, "PROGS_SRC"))
897                         {       //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
898                         }
899                         else if (!QC_strcasecmp(qcc_token, "PROGS_DAT"))
900                         {       //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
901                                 extern char             destfile[1024];
902 #ifndef QCCONLY
903                                 extern char qccmfilename[1024];
904                                 int p;
905                                 char *s, *s2;
906 #endif
907                                 QCC_COM_Parse(msg);
908
909 #ifndef QCCONLY
910         p=0;
911         s2 = qcc_token;
912         if (!strncmp(s2, "./", 2))
913                 s2+=2;
914         else
915         {
916                 while(!strncmp(s2, "../", 3))
917                 {
918                         s2+=3;
919                         p++;
920                 }
921         }
922         strcpy(qccmfilename, qccmsourcedir);
923         for (s=qccmfilename+strlen(qccmfilename);p && s>=qccmfilename; s--)
924         {
925                 if (*s == '/' || *s == '\\')
926                 {
927                         *(s+1) = '\0';
928                         p--;
929                 }
930         }
931         sprintf(destfile, "%s", s2);
932
933         while (p>0)
934         {
935                 memmove(destfile+3, destfile, strlen(destfile)+1);
936                 destfile[0] = '.';
937                 destfile[1] = '.';
938                 destfile[2] = '/';
939                 p--;
940         }
941 #else
942
943                                 strcpy(destfile, qcc_token);
944 #endif
945                                 printf("Outputfile: %s\n", destfile);
946                         }
947                         else if (!QC_strcasecmp(qcc_token, "keyword") || !QC_strcasecmp(qcc_token, "flag"))
948                         {
949                                 char *s;
950                                 int st;
951                                 s = QCC_COM_Parse(msg);
952                                 if (!QC_strcasecmp(qcc_token, "enable") || !QC_strcasecmp(qcc_token, "on"))
953                                         st = 1;
954                                 else if (!QC_strcasecmp(qcc_token, "disable") || !QC_strcasecmp(qcc_token, "off"))
955                                         st = 0;
956                                 else
957                                 {
958                                         QCC_PR_ParseWarning(WARN_BADPRAGMA, "compiler flag state not recognised");
959                                         st = -1;
960                                 }
961                                 if (st < 0)
962                                         QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
963                                 else
964                                 {
965                                         int f;
966                                         s = QCC_COM_Parse(s);
967
968                                         for (f = 0; compiler_flag[f].enabled; f++)
969                                         {
970                                                 if (!QC_strcasecmp(compiler_flag[f].abbrev, qcc_token))
971                                                 {
972                                                         if (compiler_flag[f].flags & FLAG_MIDCOMPILE)
973                                                                 *compiler_flag[f].enabled = st;
974                                                         else
975                                                                 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Cannot enable/disable keyword/flag via a pragma");
976                                                         break;
977                                                 }
978                                         }
979                                         if (!compiler_flag[f].enabled)
980                                                 QCC_PR_ParseWarning(WARN_BADPRAGMA, "keyword/flag not recognised");
981
982                                 }
983                         }
984                         else if (!QC_strcasecmp(qcc_token, "warning"))
985                         {
986                                 int st;
987                                 char *s;
988                                 s = QCC_COM_Parse(msg);
989                                 if (!stricmp(qcc_token, "enable") || !stricmp(qcc_token, "on"))
990                                         st = 0;
991                                 else if (!stricmp(qcc_token, "disable") || !stricmp(qcc_token, "off"))
992                                         st = 1;
993                                 else if (!stricmp(qcc_token, "toggle"))
994                                         st = 2;
995                                 else
996                                 {
997                                         QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning state not recognised");
998                                         st = -1;
999                                 }
1000                                 if (st>=0)
1001                                 {
1002                                         int wn;
1003                                         s = QCC_COM_Parse(s);
1004                                         wn = QCC_WarningForName(qcc_token);
1005                                         if (wn < 0)
1006                                                 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
1007                                         else
1008                                         {
1009                                                 if (st == 2)    //toggle
1010                                                         qccwarningdisabled[wn] = true - qccwarningdisabled[wn];
1011                                                 else
1012                                                         qccwarningdisabled[wn] = st;
1013                                         }
1014                                 }
1015                         }
1016                         else
1017                                 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Unknown pragma \'%s\'", qcc_token);
1018                 }
1019                 return true;
1020         }
1021
1022         return false;
1023 }
1024
1025 /*
1026 ==============
1027 PR_NewLine
1028
1029 Call at start of file and when *pr_file_p == '\n'
1030 ==============
1031 */
1032 void QCC_PR_NewLine (pbool incomment)
1033 {
1034         pr_source_line++;
1035         pr_line_start = pr_file_p;
1036         while(*pr_file_p==' ' || *pr_file_p == '\t')
1037                 pr_file_p++;
1038         if (incomment)  //no constants if in a comment.
1039         {
1040         }
1041         else if (QCC_PR_Precompiler())
1042         {
1043         }
1044
1045 //      if (pr_dumpasm)
1046 //              PR_PrintNextLine ();
1047 }
1048
1049 /*
1050 ==============
1051 PR_LexString
1052
1053 Parses a quoted string
1054 ==============
1055 */
1056 #if 0
1057 void QCC_PR_LexString (void)
1058 {
1059         int             c;
1060         int             len;
1061         char tmpbuf[2048];
1062
1063         char *text;
1064         char *oldf;
1065         int oldline;
1066
1067         bool fromfile = true;
1068
1069         len = 0;
1070
1071         text = pr_file_p;
1072         do
1073         {
1074                 QCC_COM_Parse(text);
1075 //              print("Next token is \"%s\"\n", com_token);
1076                 if (*text == '\"')
1077                 {
1078                         text++;
1079                         if (fromfile) pr_file_p++;
1080                 }
1081         do
1082         {
1083                 c = *text++;
1084                 if (fromfile) pr_file_p++;
1085                 if (!c)
1086                         QCC_PR_ParseError ("EOF inside quote");
1087                 if (c=='\n')
1088                         QCC_PR_ParseError ("newline inside quote");
1089                 if (c=='\\')
1090                 {       // escape char
1091                         c = *text++;
1092                         if (fromfile) pr_file_p++;
1093                         if (!c)
1094                                 QCC_PR_ParseError ("EOF inside quote");
1095                         if (c == 'n')
1096                                 c = '\n';
1097                         else if (c == '"')
1098                                 c = '"';
1099                         else if (c == '\\')
1100                                 c = '\\';
1101                         else
1102                                 QCC_PR_ParseError ("Unknown escape char");
1103                 }
1104                 else if (c=='\"')
1105                 {
1106                         if (fromfile) pr_file_p++;
1107                         break;
1108                 }
1109                 tmpbuf[len] = c;
1110                 len++;
1111         } while (1);
1112                 tmpbuf[len] = 0;
1113 //              if (fromfile) pr_file_p++;
1114
1115                 pr_immediate_type=NULL;
1116                 oldline=pr_source_line;
1117                 oldf=pr_file_p;
1118                 QCC_PR_Lex();
1119                 if (pr_immediate_type == &type_string)
1120                 {
1121 //                      print("Appending \"%s\" to \"%s\"\n", pr_immediate_string, tmpbuf);
1122                         strcat(tmpbuf, pr_immediate_string);
1123                         len+=strlen(pr_immediate_string);
1124                 }
1125                 else
1126                 {
1127                         pr_source_line = oldline;
1128                         pr_file_p = oldf-1;
1129                         QCC_PR_LexWhitespace();
1130                         if (*pr_file_p != '\"') //annother string
1131                                 break;
1132                 }
1133
1134                 QCC_PR_LexWhitespace();
1135                 text = pr_file_p;
1136
1137         } while (1);
1138
1139         strcpy(pr_token, tmpbuf);
1140         pr_token_type = tt_immediate;
1141         pr_immediate_type = &type_string;
1142         strcpy (pr_immediate_string, pr_token);
1143
1144 //      print("Found \"%s\"\n", pr_immediate_string);
1145 }
1146 #else
1147 void QCC_PR_LexString (void)
1148 {
1149         int             c;
1150         int             len;
1151         char    *end, *cnst;
1152
1153         int texttype=0;
1154
1155         len = 0;
1156         pr_file_p++;
1157         do
1158         {
1159                 c = *pr_file_p++;
1160                 if (!c)
1161                         QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1162                 if (c=='\n')
1163                         QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "newline inside quote");
1164                 if (c=='\\')
1165                 {       // escape char
1166                         c = *pr_file_p++;
1167                         if (!c)
1168                                 QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1169                         if (c == 'n')
1170                                 c = '\n';
1171                         else if (c == 'r')
1172                                 c = '\r';
1173                         else if (c == '"')
1174                                 c = '"';
1175                         else if (c == 't')
1176                                 c = '\t';
1177                         else if (c == 'a')
1178                                 c = '\a';
1179                         else if (c == 'v')
1180                                 c = '\v';
1181                         else if (c == 'f')
1182                                 c = '\f';
1183                         else if (c == 's' || c == 'b')
1184                         {
1185                                 texttype ^= 128;
1186                                 continue;
1187                         }
1188                         else if (c == '[')
1189                                 c = 16;
1190                         else if (c == ']')
1191                                 c = 17;
1192                         else if (c == '{')
1193                         {
1194                                 int d;
1195                                 c = 0;
1196                                 while ((d = *pr_file_p++) != '}')
1197                                 {
1198                                         c = c * 10 + d - '0';
1199                                         if (d < '0' || d > '9' || c > 255)
1200                                                 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1201                                 }
1202                         }
1203                         else if (c == '<')
1204                                 c = 29;
1205                         else if (c == '-')
1206                                 c = 30;
1207                         else if (c == '>')
1208                                 c = 31;
1209                         else if (c == 'x' || c == 'X')
1210                         {
1211                                 int d;
1212                                 c = 0;
1213
1214                                 d = (unsigned char)*pr_file_p++;
1215                                 if (d >= '0' && d <= '9')
1216                                         c += d - '0';
1217                                 else if (d >= 'A' && d <= 'F')
1218                                         c += d - 'A' + 10;
1219                                 else if (d >= 'a' && d <= 'f')
1220                                         c += d - 'a' + 10;
1221                                 else
1222                                         QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1223
1224                                 c *= 16;
1225
1226                                 d = (unsigned char)*pr_file_p++;
1227                                 if (d >= '0' && d <= '9')
1228                                         c += d - '0';
1229                                 else if (d >= 'A' && d <= 'F')
1230                                         c += d - 'A' + 10;
1231                                 else if (d >= 'a' && d <= 'f')
1232                                         c += d - 'a' + 10;
1233                                 else
1234                                         QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1235                         }
1236                         else if (c == '\\')
1237                                 c = '\\';
1238                         else if (c == '\'')
1239                                 c = '\'';
1240                         else if (c >= '0' && c <= '9')
1241                                 c = 18 + c - '0';
1242                         else if (c == '\r')
1243                         {       //sigh
1244                                 c = *pr_file_p++;
1245                                 if (c != '\n')
1246                                         QCC_PR_ParseWarning(WARN_HANGINGSLASHR, "Hanging \\\\\r");
1247                                 pr_source_line++;
1248                         }
1249                         else if (c == '\n')
1250                         {       //sigh
1251                                 pr_source_line++;
1252                         }
1253                         else
1254                                 QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "Unknown escape char %c", c);
1255                 }
1256                 else if (c=='\"')
1257                 {
1258                         if (len >= sizeof(pr_immediate_string)-1)
1259                                 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
1260
1261                         while(*pr_file_p && *pr_file_p <= ' ')
1262                         {
1263                                 if (*pr_file_p == '\n')
1264                                 {
1265                                         pr_file_p++;
1266                                         QCC_PR_NewLine(false);
1267                                 }
1268                                 else
1269                                         pr_file_p++;
1270                         }
1271                         if (*pr_file_p == '\"') //have annother go
1272                         {
1273                                 pr_file_p++;
1274                                 continue;
1275                         }
1276                         pr_token[len] = 0;
1277                         pr_token_type = tt_immediate;
1278                         pr_immediate_type = type_string;
1279                         strcpy (pr_immediate_string, pr_token);
1280                         return;
1281                 }
1282                 else if (c == '#')
1283                 {
1284                         for (end = pr_file_p; ; end++)
1285                         {
1286                                 if (*end <= ' ')
1287                                         break;
1288
1289                                 if (*end == ')'
1290                                         ||      *end == '('
1291                                         ||      *end == '+'
1292                                         ||      *end == '-'
1293                                         ||      *end == '*'
1294                                         ||      *end == '/'
1295                                         ||      *end == '\\'
1296                                         ||      *end == '|'
1297                                         ||      *end == '&'
1298                                         ||      *end == '='
1299                                         ||      *end == '^'
1300                                         ||      *end == '~'
1301                                         ||      *end == '['
1302                                         ||      *end == ']'
1303                                         ||      *end == '\"'
1304                                         ||      *end == '{'
1305                                         ||      *end == '}'
1306                                         ||      *end == ';'
1307                                         ||      *end == ':'
1308                                         ||      *end == ','
1309                                         ||      *end == '.'
1310                                         ||      *end == '#')
1311                                                 break;
1312                         }
1313
1314                         c = *end;
1315                         *end = '\0';
1316                         cnst = QCC_PR_CheakCompConstString(pr_file_p);
1317                         if (cnst==pr_file_p)
1318                                 cnst=NULL;
1319                         *end = c;
1320                         c = '#';        //undo
1321                         if (cnst)
1322                         {
1323                                 QCC_PR_ParseWarning(WARN_MACROINSTRING, "Macro expansion in string");
1324
1325                                 if (len+strlen(cnst) >= sizeof(pr_token)-1)
1326                                         QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1327
1328                                 strcpy(pr_token+len, cnst);
1329                                 len+=strlen(cnst);
1330                                 pr_file_p = end;
1331                                 continue;
1332                         }
1333                 }
1334                 else if (c == 0x7C && flag_acc) //reacc support... reacc is strange.
1335                         c = '\n';
1336                 else
1337                         c |= texttype;
1338
1339                 pr_token[len] = c;
1340                 len++;
1341                 if (len >= sizeof(pr_token)-1)
1342                         QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1343         } while (1);
1344 }
1345 #endif
1346
1347 /*
1348 ==============
1349 PR_LexNumber
1350 ==============
1351 */
1352 int QCC_PR_LexInteger (void)
1353 {
1354         int             c;
1355         int             len;
1356
1357         len = 0;
1358         c = *pr_file_p;
1359         if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1360         {
1361                 pr_token[0] = '0';
1362                 pr_token[1] = 'x';
1363                 len = 2;
1364                 c = *(pr_file_p+=2);
1365         }
1366         do
1367         {
1368                 pr_token[len] = c;
1369                 len++;
1370                 pr_file_p++;
1371                 c = *pr_file_p;
1372         } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.') || (c>='a' && c <= 'f'));
1373         pr_token[len] = 0;
1374         return atoi (pr_token);
1375 }
1376
1377 void QCC_PR_LexNumber (void)
1378 {
1379         int tokenlen = 0;
1380         int num=0;
1381         int base=0;
1382         int c;
1383         int sign=1;
1384         if (*pr_file_p == '-')
1385         {
1386                 sign=-1;
1387                 pr_file_p++;
1388
1389                 pr_token[tokenlen++] = '-';
1390         }
1391         if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1392         {
1393                 pr_file_p+=2;
1394                 base = 16;
1395
1396                 pr_token[tokenlen++] = '0';
1397                 pr_token[tokenlen++] = 'x';
1398         }
1399
1400         pr_immediate_type = NULL;
1401         //assume base 10 if not stated
1402         if (!base)
1403                 base = 10;
1404
1405         while((c = *pr_file_p))
1406         {
1407                 if (c >= '0' && c <= '9')
1408                 {
1409                         pr_token[tokenlen++] = c;
1410                         num*=base;
1411                         num += c-'0';
1412                 }
1413                 else if (c >= 'a' && c <= 'f' && base > 10)
1414                 {
1415                         pr_token[tokenlen++] = c;
1416                         num*=base;
1417                         num += c -'a'+10;
1418                 }
1419                 else if (c >= 'A' && c <= 'F' && base > 10)
1420                 {
1421                         pr_token[tokenlen++] = c;
1422                         num*=base;
1423                         num += c -'A'+10;
1424                 }
1425                 else if (c == '.' && pr_file_p[1]!='.')
1426                 {
1427                         pr_token[tokenlen++] = c;
1428                         pr_file_p++;
1429                         pr_immediate_type = type_float;
1430                         while(1)
1431                         {
1432                                 c = *pr_file_p;
1433                                 if (c >= '0' && c <= '9')
1434                                 {
1435                                         pr_token[tokenlen++] = c;
1436                                 }
1437                                 else if (c == 'f')
1438                                 {
1439                                         pr_file_p++;
1440                                         break;
1441                                 }
1442                                 else
1443                                 {
1444                                         break;
1445                                 }
1446                                 pr_file_p++;
1447                         }
1448                         pr_token[tokenlen++] = 0;
1449                         pr_immediate._float = (float)atof(pr_token);
1450                         return;
1451                 }
1452                 else if (c == 'f')
1453                 {
1454                         pr_token[tokenlen++] = c;
1455                         pr_token[tokenlen++] = 0;
1456                         pr_file_p++;
1457                         pr_immediate_type = type_float;
1458                         pr_immediate._float = num*sign;
1459                         return;
1460                 }
1461                 else if (c == 'i')
1462                 {
1463                         pr_token[tokenlen++] = c;
1464                         pr_token[tokenlen++] = 0;
1465                         pr_file_p++;
1466                         pr_immediate_type = type_integer;
1467                         pr_immediate._int = num*sign;
1468                         return;
1469                 }
1470                 else
1471                         break;
1472                 pr_file_p++;
1473         }
1474         pr_token[tokenlen++] = 0;
1475
1476         if (!pr_immediate_type)
1477         {
1478                 if (flag_assume_integer)
1479                         pr_immediate_type = type_integer;
1480                 else
1481                         pr_immediate_type = type_float;
1482         }
1483
1484         if (pr_immediate_type == type_integer)
1485         {
1486                 pr_immediate_type = type_integer;
1487                 pr_immediate._int = num*sign;
1488         }
1489         else
1490         {
1491                 pr_immediate_type = type_float;
1492                 // at this point, we know there's no . in it, so the NaN bug shouldn't happen
1493                 // and we cannot use atof on tokens like 0xabc, so use num*sign, it SHOULD be safe
1494                 //pr_immediate._float = atof(pr_token);
1495                 pr_immediate._float = (float)(num*sign);
1496         }
1497 }
1498
1499
1500 float QCC_PR_LexFloat (void)
1501 {
1502         int             c;
1503         int             len;
1504
1505         len = 0;
1506         c = *pr_file_p;
1507         do
1508         {
1509                 pr_token[len] = c;
1510                 len++;
1511                 pr_file_p++;
1512                 c = *pr_file_p;
1513         } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.'));       //only allow a . if the next isn't too...
1514         if (*pr_file_p == 'f')
1515                 pr_file_p++;
1516         pr_token[len] = 0;
1517         return (float)atof (pr_token);
1518 }
1519
1520 /*
1521 ==============
1522 PR_LexVector
1523
1524 Parses a single quoted vector
1525 ==============
1526 */
1527 void QCC_PR_LexVector (void)
1528 {
1529         int             i;
1530
1531         pr_file_p++;
1532
1533         if (*pr_file_p == '\\')
1534         {//extended character constant
1535                 pr_token_type = tt_immediate;
1536                 pr_immediate_type = type_float;
1537                 pr_file_p++;
1538                 switch(*pr_file_p)
1539                 {
1540                 case 'n':
1541                         pr_immediate._float = '\n';
1542                         break;
1543                 case 'r':
1544                         pr_immediate._float = '\r';
1545                         break;
1546                 case 't':
1547                         pr_immediate._float = '\t';
1548                         break;
1549                 case '\'':
1550                         pr_immediate._float = '\'';
1551                         break;
1552                 case '\"':
1553                         pr_immediate._float = '\"';
1554                         break;
1555                 case '\\':
1556                         pr_immediate._float = '\\';
1557                         break;
1558                 default:
1559                         QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
1560                 }
1561                 pr_file_p++;
1562                 if (*pr_file_p != '\'')
1563                         QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
1564                 pr_file_p++;
1565                 return;
1566         }
1567         if (pr_file_p[1] == '\'')
1568         {//character constant
1569                 pr_token_type = tt_immediate;
1570                 pr_immediate_type = type_float;
1571                 pr_immediate._float = pr_file_p[0];
1572                 pr_file_p+=2;
1573                 return;
1574         }
1575         pr_token_type = tt_immediate;
1576         pr_immediate_type = type_vector;
1577         QCC_PR_LexWhitespace ();
1578         for (i=0 ; i<3 ; i++)
1579         {
1580                 pr_immediate.vector[i] = QCC_PR_LexFloat ();
1581                 QCC_PR_LexWhitespace ();
1582
1583                 if (*pr_file_p == '\'' && i == 1)
1584                 {
1585                         if (i < 2)
1586                                 QCC_PR_ParseWarning (WARN_FTE_SPECIFIC, "Bad vector");
1587
1588                         for (i++ ; i<3 ; i++)
1589                                 pr_immediate.vector[i] = 0;
1590                         break;
1591                 }
1592         }
1593         if (*pr_file_p != '\'')
1594                 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad vector");
1595         pr_file_p++;
1596 }
1597
1598 /*
1599 ==============
1600 PR_LexName
1601
1602 Parses an identifier
1603 ==============
1604 */
1605 void QCC_PR_LexName (void)
1606 {
1607         int             c;
1608         int             len;
1609
1610         len = 0;
1611         c = *pr_file_p;
1612         do
1613         {
1614                 pr_token[len] = c;
1615                 len++;
1616                 pr_file_p++;
1617                 c = *pr_file_p;
1618         } while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
1619         || (c >= '0' && c <= '9'));
1620
1621         pr_token[len] = 0;
1622         pr_token_type = tt_name;
1623 }
1624
1625 /*
1626 ==============
1627 PR_LexPunctuation
1628 ==============
1629 */
1630 void QCC_PR_LexPunctuation (void)
1631 {
1632         int             i;
1633         int             len;
1634         char    *p;
1635
1636         pr_token_type = tt_punct;
1637
1638         for (i=0 ; (p = pr_punctuation[i]) != NULL ; i++)
1639         {
1640                 len = strlen(p);
1641                 if (!strncmp(p, pr_file_p, len) )
1642                 {
1643                         strcpy (pr_token, pr_punctuationremap[i]);
1644                         if (p[0] == '{')
1645                                 pr_bracelevel++;
1646                         else if (p[0] == '}')
1647                                 pr_bracelevel--;
1648                         pr_file_p += len;
1649                         return;
1650                 }
1651         }
1652
1653         QCC_PR_ParseError (ERR_UNKNOWNPUCTUATION, "Unknown punctuation");
1654 }
1655
1656
1657 /*
1658 ==============
1659 PR_LexWhitespace
1660 ==============
1661 */
1662 void QCC_PR_LexWhitespace (void)
1663 {
1664         int             c;
1665
1666         while (1)
1667         {
1668         // skip whitespace
1669                 while ( (c = *pr_file_p) <= ' ')
1670                 {
1671                         if (c=='\n')
1672                         {
1673                                 pr_file_p++;
1674                                 QCC_PR_NewLine (false);
1675                                 if (!pr_file_p)
1676                                         return;
1677                         }
1678                         else
1679                         {
1680                                 if (c == 0)
1681                                         return;         // end of file
1682                                 pr_file_p++;
1683                         }
1684                 }
1685
1686         // skip // comments
1687                 if (c=='/' && pr_file_p[1] == '/')
1688                 {
1689                         while (*pr_file_p && *pr_file_p != '\n')
1690                                 pr_file_p++;
1691
1692                         if (*pr_file_p == '\n')
1693                                 pr_file_p++;    //don't break on eof.
1694                         QCC_PR_NewLine(false);
1695                         continue;
1696                 }
1697
1698         // skip /* */ comments
1699                 if (c=='/' && pr_file_p[1] == '*')
1700                 {
1701                         pr_file_p+=2;
1702                         do
1703                         {
1704                                 if (pr_file_p[0]=='\n')
1705                                 {
1706                                         QCC_PR_NewLine(true);
1707                                 }
1708                                 if (pr_file_p[1] == 0)
1709                                 {
1710                                         QCC_PR_ParseError(0, "EOF inside comment\n");
1711                                         pr_file_p++;
1712                                         return;
1713                                 }
1714                                 pr_file_p++;
1715                         } while (pr_file_p[0] != '*' || pr_file_p[1] != '/');
1716                         pr_file_p+=2;
1717                         continue;
1718                 }
1719
1720                 break;          // a real character has been found
1721         }
1722 }
1723
1724 //============================================================================
1725
1726 #define MAX_FRAMES      8192
1727 char    pr_framemodelname[64];
1728 char    pr_framemacros[MAX_FRAMES][64];
1729 int             pr_framemacrovalue[MAX_FRAMES];
1730 int             pr_nummacros, pr_oldmacros;
1731 int             pr_macrovalue;
1732 int             pr_savedmacro;
1733
1734 void QCC_PR_ClearGrabMacros (void)
1735 {
1736         pr_oldmacros = pr_nummacros;
1737 //      pr_nummacros = 0;
1738         pr_macrovalue = 0;
1739         pr_savedmacro = -1;
1740 }
1741
1742 int QCC_PR_FindMacro (char *name)
1743 {
1744         int             i;
1745
1746         for (i=pr_nummacros-1 ; i>=0 ; i--)
1747         {
1748                 if (!STRCMP (name, pr_framemacros[i]))
1749                 {
1750                         return pr_framemacrovalue[i];
1751                 }
1752         }
1753         for (i=pr_nummacros-1 ; i>=0 ; i--)
1754         {
1755                 if (!stricmp (name, pr_framemacros[i]))
1756                 {
1757                         QCC_PR_ParseWarning(WARN_CASEINSENSATIVEFRAMEMACRO, "Case insensative frame macro");
1758                         return pr_framemacrovalue[i];
1759                 }
1760         }
1761         return -1;
1762 }
1763
1764 void QCC_PR_ExpandMacro(void)
1765 {
1766         int             i = QCC_PR_FindMacro(pr_token);
1767
1768         if (i < 0)
1769                 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "Unknown frame macro $%s", pr_token);
1770
1771         sprintf (pr_token,"%d", i);
1772         pr_token_type = tt_immediate;
1773         pr_immediate_type = type_float;
1774         pr_immediate._float = (float)i;
1775 }
1776
1777 // just parses text, returning false if an eol is reached
1778 pbool QCC_PR_SimpleGetToken (void)
1779 {
1780         int             c;
1781         int             i;
1782
1783         pr_token[0] = 0;
1784
1785 // skip whitespace
1786         while ( (c = *pr_file_p) <= ' ')
1787         {
1788                 if (c=='\n' || c == 0)
1789                         return false;
1790                 pr_file_p++;
1791         }
1792         if (pr_file_p[0] == '/')
1793         {
1794                 if (pr_file_p[1] == '/')
1795                 {       //comment alert
1796                         while(*pr_file_p && *pr_file_p != '\n')
1797                                 pr_file_p++;
1798                         return false;
1799                 }
1800                 if (pr_file_p[1] == '*')
1801                         return false;
1802         }
1803
1804         i = 0;
1805         while ( (c = *pr_file_p) > ' ' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']')
1806         {
1807                 pr_token[i] = c;
1808                 i++;
1809                 pr_file_p++;
1810         }
1811         pr_token[i] = 0;
1812         return i!=0;
1813 }
1814
1815 pbool QCC_PR_LexMacroName(void)
1816 {
1817         int             c;
1818         int             i;
1819
1820         pr_token[0] = 0;
1821
1822 // skip whitespace
1823         while ( (c = *pr_file_p) <= ' ')
1824         {
1825                 if (c=='\n' || c == 0)
1826                         return false;
1827                 pr_file_p++;
1828         }
1829         if (pr_file_p[0] == '/')
1830         {
1831                 if (pr_file_p[1] == '/')
1832                 {       //comment alert
1833                         while(*pr_file_p && *pr_file_p != '\n')
1834                                 pr_file_p++;
1835                         return false;
1836                 }
1837                 if (pr_file_p[1] == '*')
1838                         return false;
1839         }
1840
1841         i = 0;
1842         while ( (c = *pr_file_p) > ' ' && c != '\n' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']' && !(pr_file_p[0] == '.' && pr_file_p[1] == '.'))
1843         {
1844                 pr_token[i] = c;
1845                 i++;
1846                 pr_file_p++;
1847         }
1848         pr_token[i] = 0;
1849         return i!=0;
1850 }
1851
1852 void QCC_PR_MacroFrame(char *name, int value)
1853 {
1854         int i;
1855         for (i=pr_nummacros-1 ; i>=0 ; i--)
1856         {
1857                 if (!STRCMP (name, pr_framemacros[i]))
1858                 {
1859                         pr_framemacrovalue[i] = value;
1860                         if (i>=pr_oldmacros)
1861                                 QCC_PR_ParseWarning(WARN_DUPLICATEMACRO, "Duplicate macro defined (%s)", pr_token);
1862                         //else it's from an old file, and shouldn't be mentioned.
1863                         return;
1864                 }
1865         }
1866
1867         if (strlen(name)+1 > sizeof(pr_framemacros[0]))
1868                 QCC_PR_ParseWarning(ERR_TOOMANYFRAMEMACROS, "Name for frame macro %s is too long", name);
1869         else
1870         {
1871                 strcpy (pr_framemacros[pr_nummacros], name);
1872                 pr_framemacrovalue[pr_nummacros] = value;
1873                 pr_nummacros++;
1874                 if (pr_nummacros >= MAX_FRAMES)
1875                         QCC_PR_ParseError(ERR_TOOMANYFRAMEMACROS, "Too many frame macros defined");
1876         }
1877 }
1878
1879 void QCC_PR_ParseFrame (void)
1880 {
1881         while (QCC_PR_LexMacroName ())
1882         {
1883                 QCC_PR_MacroFrame(pr_token, pr_macrovalue++);
1884         }
1885 }
1886
1887 /*
1888 ==============
1889 PR_LexGrab
1890
1891 Deals with counting sequence numbers and replacing frame macros
1892 ==============
1893 */
1894 void QCC_PR_LexGrab (void)
1895 {
1896         pr_file_p++;    // skip the $
1897 //      if (!QCC_PR_SimpleGetToken ())
1898 //              QCC_PR_ParseError ("hanging $");
1899         if (*pr_file_p <= ' ')
1900                 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
1901         QCC_PR_LexMacroName();
1902         if (!*pr_token)
1903                 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
1904
1905 // check for $frame
1906         if (!STRCMP (pr_token, "frame") || !STRCMP (pr_token, "framesave"))
1907         {
1908                 QCC_PR_ParseFrame ();
1909                 QCC_PR_Lex ();
1910         }
1911 // ignore other known $commands - just for model/spritegen
1912         else if (!STRCMP (pr_token, "cd")
1913         || !STRCMP (pr_token, "origin")
1914         || !STRCMP (pr_token, "base")
1915         || !STRCMP (pr_token, "flags")
1916         || !STRCMP (pr_token, "scale")
1917         || !STRCMP (pr_token, "skin") )
1918         {       // skip to end of line
1919                 while (QCC_PR_LexMacroName ())
1920                 ;
1921                 QCC_PR_Lex ();
1922         }
1923         else if (!STRCMP (pr_token, "flush"))
1924         {
1925                 QCC_PR_ClearGrabMacros();
1926                 while (QCC_PR_LexMacroName ())
1927                 ;
1928                 QCC_PR_Lex ();
1929         }
1930         else if (!STRCMP (pr_token, "framevalue"))
1931         {
1932                 QCC_PR_LexMacroName ();
1933                 pr_macrovalue = atoi(pr_token);
1934
1935                 QCC_PR_Lex ();
1936         }
1937         else if (!STRCMP (pr_token, "framerestore"))
1938         {
1939                 QCC_PR_LexMacroName ();
1940                 QCC_PR_ExpandMacro();
1941                 pr_macrovalue = (int)pr_immediate._float;
1942
1943                 QCC_PR_Lex ();
1944         }
1945         else if (!STRCMP (pr_token, "modelname"))
1946         {
1947                 int i;
1948                 QCC_PR_LexMacroName ();
1949
1950                 if (*pr_framemodelname)
1951                         QCC_PR_MacroFrame(pr_framemodelname, pr_macrovalue);
1952
1953                 strncpy(pr_framemodelname, pr_token, sizeof(pr_framemodelname)-1);
1954                 pr_framemodelname[sizeof(pr_framemodelname)-1] = '\0';
1955
1956                 i = QCC_PR_FindMacro(pr_framemodelname);
1957                 if (i)
1958                         pr_macrovalue = i;
1959                 else
1960                         i = 0;
1961
1962                 QCC_PR_Lex ();
1963         }
1964 // look for a frame name macro
1965         else
1966                 QCC_PR_ExpandMacro ();
1967 }
1968
1969 //===========================
1970 //compiler constants    - dmw
1971
1972 pbool QCC_PR_UndefineName(char *name)
1973 {
1974 //      int a;
1975         CompilerConstant_t *c;
1976         c = pHash_Get(&compconstantstable, name);
1977         if (!c)
1978         {
1979                 QCC_PR_ParseWarning(WARN_UNDEFNOTDEFINED, "Precompiler constant %s was not defined", name);
1980                 return false;
1981         }
1982
1983         Hash_Remove(&compconstantstable, name);
1984         return true;
1985 }
1986
1987 CompilerConstant_t *QCC_PR_DefineName(char *name)
1988 {
1989         int i;
1990         CompilerConstant_t *cnst;
1991
1992 //      if (numCompilerConstants >= MAX_CONSTANTS)
1993 //              QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS);
1994
1995         if (strlen(name) >= MAXCONSTANTNAMELENGTH || !*name)
1996                 QCC_PR_ParseError(ERR_NAMETOOLONG, "Compiler constant name length is too long or short");
1997
1998         cnst = pHash_Get(&compconstantstable, name);
1999         if (cnst)
2000         {
2001                 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "Duplicate definition for Precompiler constant %s", name);
2002                 Hash_Remove(&compconstantstable, name);
2003         }
2004
2005         cnst = qccHunkAlloc(sizeof(CompilerConstant_t));
2006
2007         cnst->used = false;
2008         cnst->numparams = 0;
2009         strcpy(cnst->name, name);
2010         cnst->namelen = strlen(name);
2011         cnst->value = cnst->name + strlen(cnst->name);
2012         for (i = 0; i < MAXCONSTANTPARAMS; i++)
2013                 cnst->params[i][0] = '\0';
2014
2015         pHash_Add(&compconstantstable, cnst->name, cnst, qccHunkAlloc(sizeof(bucket_t)));
2016
2017         return cnst;
2018 }
2019
2020 void QCC_PR_Undefine(void)
2021 {
2022         QCC_PR_SimpleGetToken ();
2023
2024         QCC_PR_UndefineName(pr_token);
2025 //              QCC_PR_ParseError("%s was not defined.", pr_token);
2026 }
2027
2028 void QCC_PR_ConditionCompilation(void)
2029 {
2030         char *oldval;
2031         char *d;
2032         char *dbuf;
2033         int dbuflen;
2034         char *s;
2035         int quote=false;
2036         CompilerConstant_t *cnst;
2037
2038         QCC_PR_SimpleGetToken ();
2039
2040         if (!QCC_PR_SimpleGetToken ())
2041                 QCC_PR_ParseError(ERR_NONAME, "No name defined for compiler constant");
2042
2043         cnst = pHash_Get(&compconstantstable, pr_token);
2044         if (cnst)
2045         {
2046                 oldval = cnst->value;
2047                 Hash_Remove(&compconstantstable, pr_token);
2048         }
2049         else
2050                 oldval = NULL;
2051
2052         cnst = QCC_PR_DefineName(pr_token);
2053
2054         if (*pr_file_p == '(')
2055         {
2056                 s = pr_file_p+1;
2057                 while(*pr_file_p++)
2058                 {
2059                         if (*pr_file_p == ',')
2060                         {
2061                                 if (cnst->numparams >= MAXCONSTANTPARAMS)
2062                                         QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
2063                                 strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
2064                                 cnst->params[cnst->numparams][pr_file_p-s] = '\0';
2065                                 cnst->numparams++;
2066                                 pr_file_p++;
2067                                 s = pr_file_p;
2068                         }
2069                         if (*pr_file_p == ')')
2070                         {
2071                                 if (cnst->numparams >= MAXCONSTANTPARAMS)
2072                                         QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
2073                                 strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
2074                                 cnst->params[cnst->numparams][pr_file_p-s] = '\0';
2075                                 cnst->numparams++;
2076                                 pr_file_p++;
2077                                 break;
2078                         }
2079                 }
2080         }
2081         else cnst->numparams = -1;
2082
2083         s = pr_file_p;
2084         d = dbuf = NULL;
2085         dbuflen = 0;
2086         while(*s == ' ' || *s == '\t')
2087                 s++;
2088         while(1)
2089         {
2090                 if ((d - dbuf) + 2 >= dbuflen)
2091                 {
2092                         int len = d - dbuf;
2093                         dbuflen = (len+128) * 2;
2094                         dbuf = qccHunkAlloc(dbuflen);
2095                         memcpy(dbuf, d - len, len);
2096                         d = dbuf + len;
2097                 }
2098
2099                 if( *s == '\\' )
2100                 {
2101                         // read over a newline if necessary
2102                         if( s[1] == '\n' || s[1] == '\r' )
2103                         {
2104                                 s++;
2105                                 QCC_PR_NewLine(false);
2106                                 *d++ = *s++;
2107                                 if( s[-1] == '\r' && s[0] == '\n' )
2108                                 {
2109                                         *d++ = *s++;
2110                                 }
2111                         }
2112                 }
2113                 else if(*s == '\r' || *s == '\n' || *s == '\0')
2114                 {
2115                         break;
2116                 }
2117
2118                 if (!quote && s[0]=='/'&&(s[1]=='/'||s[1]=='*'))
2119                         break;
2120                 if (*s == '\"')
2121                         quote=!quote;
2122
2123                 *d = *s;
2124                 d++;
2125                 s++;
2126         }
2127         *d = '\0';
2128
2129         cnst->value = dbuf;
2130
2131         if (oldval)
2132         {       //we always warn if it was already defined
2133                 //we use different warning codes so that -Wno-mundane can be used to ignore identical redefinitions.
2134                 if (strcmp(oldval, cnst->value))
2135                         QCC_PR_ParseWarning(WARN_DUPLICATEPRECOMPILER, "Alternate precompiler definition of %s", pr_token);
2136                 else
2137                         QCC_PR_ParseWarning(WARN_IDENTICALPRECOMPILER, "Identical precompiler definition of %s", pr_token);
2138         }
2139
2140         pr_file_p = s;
2141 }
2142
2143 /* *buffer, *bufferlen and *buffermax should be NULL/0 at the start */
2144 static void QCC_PR_ExpandStrCat(char **buffer, int *bufferlen, int *buffermax,   char *newdata, int newlen)
2145 {
2146         int newmax = *bufferlen + newlen;
2147         if (newmax < *bufferlen)
2148         {
2149                 QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
2150                 return;
2151         }
2152         if (newmax > *buffermax)
2153         {
2154                 char *newbuf;
2155                 if (newmax < 64)
2156                         newmax = 64;
2157                 if (newmax < *bufferlen * 2)
2158                 {
2159                         newmax = *bufferlen * 2;
2160                         if (newmax < *bufferlen) /*overflowed?*/
2161                         {
2162                                 QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
2163                                 return;
2164                         }
2165                 }
2166                 newbuf = realloc(*buffer, newmax);
2167                 if (!newbuf)
2168                 {
2169                         QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
2170                         return; /*OOM*/
2171                 }
2172                 *buffer = newbuf;
2173                 *buffermax = newmax;
2174         }
2175         memcpy(*buffer + *bufferlen, newdata, newlen);
2176         *bufferlen += newlen;
2177         /*no null terminator, remember to cat one if required*/
2178 }
2179
2180 int QCC_PR_CheakCompConst(void)
2181 {
2182         char            *oldpr_file_p = pr_file_p;
2183         int whitestart;
2184
2185         CompilerConstant_t *c;
2186
2187         char *end;
2188         for (end = pr_file_p; ; end++)
2189         {
2190                 if (*end <= ' ')
2191                         break;
2192
2193                 if (*end == ')'
2194                         ||      *end == '('
2195                         ||      *end == '+'
2196                         ||      *end == '-'
2197                         ||      *end == '*'
2198                         ||      *end == '/'
2199                         ||      *end == '|'
2200                         ||      *end == '&'
2201                         ||      *end == '='
2202                         ||      *end == '^'
2203                         ||      *end == '~'
2204                         ||      *end == '['
2205                         ||      *end == ']'
2206                         ||      *end == '\"'
2207                         ||      *end == '{'
2208                         ||      *end == '}'
2209                         ||      *end == ';'
2210                         ||      *end == ':'
2211                         ||      *end == ','
2212                         ||      *end == '.'
2213                         ||      *end == '#')
2214                                 break;
2215         }
2216         strncpy(pr_token, pr_file_p, end-pr_file_p);
2217         pr_token[end-pr_file_p]='\0';
2218
2219 //      printf("%s\n", pr_token);
2220         c = pHash_Get(&compconstantstable, pr_token);
2221
2222         if (c && !c->inside)
2223         {
2224                 pr_file_p = oldpr_file_p+strlen(c->name);
2225                 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2226                         pr_file_p++;
2227                 if (c->numparams>=0)
2228                 {
2229                         if (*pr_file_p == '(')
2230                         {
2231                                 int p;
2232                                 char *start;
2233                                 char *starttok;
2234                                 char *buffer;
2235                                 int buffermax;
2236                                 int bufferlen;
2237                                 char *paramoffset[MAXCONSTANTPARAMS+1];
2238                                 int param=0;
2239                                 int plevel=0;
2240
2241                                 pr_file_p++;
2242                                 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2243                                         pr_file_p++;
2244                                 start = pr_file_p;
2245                                 while(1)
2246                                 {
2247                                         // handle strings correctly by ignoring them
2248                                         if (*pr_file_p == '\"')
2249                                         {
2250                                                 do {
2251                                                         pr_file_p++;
2252                                                 } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
2253                                         }
2254                                         if (*pr_file_p == '(')
2255                                                 plevel++;
2256                                         else if (!plevel && (*pr_file_p == ',' || *pr_file_p == ')'))
2257                                         {
2258                                                 paramoffset[param++] = start;
2259                                                 start = pr_file_p+1;
2260                                                 if (*pr_file_p == ')')
2261                                                 {
2262                                                         *pr_file_p = '\0';
2263                                                         pr_file_p++;
2264                                                         break;
2265                                                 }
2266                                                 *pr_file_p = '\0';
2267                                                 pr_file_p++;
2268                                                 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2269                                                 {
2270                                                         pr_file_p++;
2271                                                         start++;
2272                                                 }
2273                                                 // move back by one char because we move forward by one at the end of the loop
2274                                                 pr_file_p--;
2275                                                 if (param == MAXCONSTANTPARAMS)
2276                                                         QCC_PR_ParseError(ERR_TOOMANYPARAMS, "Too many parameters in macro call");
2277                                         } else if (*pr_file_p == ')' )
2278                                                 plevel--;
2279                                         else if(*pr_file_p == '\n')
2280                                                 QCC_PR_NewLine(false);
2281
2282                                         // see that *pr_file_p = '\0' up there? Must ++ BEFORE checking for !*pr_file_p
2283                                         pr_file_p++;
2284                                         if (!*pr_file_p)
2285                                                 QCC_PR_ParseError(ERR_EOF, "EOF on macro call");
2286                                 }
2287                                 if (param < c->numparams)
2288                                         QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Not enough macro parameters");
2289                                 paramoffset[param] = start;
2290
2291                                 buffer = NULL;
2292                                 bufferlen = 0;
2293                                 buffermax = 0;
2294
2295                                 oldpr_file_p = pr_file_p;
2296                                 pr_file_p = c->value;
2297                                 for(;;)
2298                                 {
2299                                         whitestart = bufferlen;
2300                                         starttok = pr_file_p;
2301                                         while(*pr_file_p <= ' ')        //copy across whitespace
2302                                         {
2303                                                 if (!*pr_file_p)
2304                                                         break;
2305                                                 pr_file_p++;
2306                                         }
2307                                         if (starttok != pr_file_p)
2308                                         {
2309                                                 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   starttok, pr_file_p - starttok);
2310                                         }
2311
2312                                         if(*pr_file_p == '\"')
2313                                         {
2314                                                 starttok = pr_file_p;
2315                                                 do
2316                                                 {
2317                                                         pr_file_p++;
2318                                                 } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
2319                                                 if(*pr_file_p == '\"')
2320                                                         pr_file_p++;
2321
2322                                                 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   starttok, pr_file_p - starttok);
2323                                                 continue;
2324                                         }
2325                                         else if (*pr_file_p == '#')     //if you ask for #a##b you will be shot. use #a #b instead, or chain macros.
2326                                         {
2327                                                 if (pr_file_p[1] == '#')
2328                                                 {       //concatinate (strip out whitespace before the token)
2329                                                         bufferlen = whitestart;
2330                                                         pr_file_p+=2;
2331                                                 }
2332                                                 else
2333                                                 {       //stringify
2334                                                         pr_file_p++;
2335                                                         pr_file_p = QCC_COM_Parse2(pr_file_p);
2336                                                         if (!pr_file_p)
2337                                                                 break;
2338
2339                                                         for (p = 0; p < param; p++)
2340                                                         {
2341                                                                 if (!STRCMP(qcc_token, c->params[p]))
2342                                                                 {
2343                                                                         QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "\"", 1);
2344                                                                         QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   paramoffset[p], strlen(paramoffset[p]));
2345                                                                         QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "\"", 1);
2346                                                                         break;
2347                                                                 }
2348                                                         }
2349                                                         if (p == param)
2350                                                         {
2351                                                                 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "#", 1);
2352                                                                 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   qcc_token, strlen(qcc_token));
2353                                                                 //QCC_PR_ParseWarning(0, "Stringification ignored");
2354                                                         }
2355                                                         continue;       //already did this one
2356                                                 }
2357                                         }
2358
2359                                         pr_file_p = QCC_COM_Parse2(pr_file_p);
2360                                         if (!pr_file_p)
2361                                                 break;
2362
2363                                         for (p = 0; p < param; p++)
2364                                         {
2365                                                 if (!STRCMP(qcc_token, c->params[p]))
2366                                                 {
2367                                                         QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   paramoffset[p], strlen(paramoffset[p]));
2368                                                         break;
2369                                                 }
2370                                         }
2371                                         if (p == param)
2372                                                 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   qcc_token, strlen(qcc_token));
2373                                 }
2374
2375                                 for (p = 0; p < param-1; p++)
2376                                         paramoffset[p][strlen(paramoffset[p])] = ',';
2377                                 paramoffset[p][strlen(paramoffset[p])] = ')';
2378
2379                                 pr_file_p = oldpr_file_p;
2380                                 if (!bufferlen)
2381                                         expandedemptymacro = true;
2382                                 else
2383                                 {
2384                                         QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax,   "\0", 1);
2385                                         QCC_PR_IncludeChunkEx(buffer, true, NULL, c);
2386                                 }
2387                                 free(buffer);
2388                         }
2389                         else
2390                                 QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without argument list");
2391                 }
2392                 else
2393                 {
2394                         if (!*c->value)
2395                                 expandedemptymacro = true;
2396                         QCC_PR_IncludeChunkEx(c->value, false, NULL, c);
2397                 }
2398
2399                 QCC_PR_Lex();
2400                 return true;
2401         }
2402
2403         if (!strncmp(pr_file_p, "__TIME__", 8))
2404         {
2405                 static char retbuf[128];
2406
2407                 time_t long_time;
2408                 time( &long_time );
2409                 strftime( retbuf, sizeof(retbuf),
2410                          "\"%H:%M\"", localtime( &long_time ));
2411
2412                 pr_file_p = retbuf;
2413                 QCC_PR_Lex();   //translate the macro's value
2414                 pr_file_p = oldpr_file_p+8;
2415
2416                 return true;
2417         }
2418         if (!strncmp(pr_file_p, "__DATE__", 8))
2419         {
2420                 static char retbuf[128];
2421
2422                 time_t long_time;
2423                 time( &long_time );
2424                 strftime( retbuf, sizeof(retbuf),
2425                          "\"%a %d %b %Y\"", localtime( &long_time ));
2426
2427                 pr_file_p = retbuf;
2428                 QCC_PR_Lex();   //translate the macro's value
2429                 pr_file_p = oldpr_file_p+8;
2430
2431                 return true;
2432         }
2433         if (!strncmp(pr_file_p, "__FILE__", 8))
2434         {
2435                 static char retbuf[256];
2436                 sprintf(retbuf, "\"%s\"", strings + s_file);
2437                 pr_file_p = retbuf;
2438                 QCC_PR_Lex();   //translate the macro's value
2439                 pr_file_p = oldpr_file_p+8;
2440
2441                 return true;
2442         }
2443         if (!strncmp(pr_file_p, "__LINE__", 8))
2444         {
2445                 static char retbuf[256];
2446                 sprintf(retbuf, "\"%i\"", pr_source_line);
2447                 pr_file_p = retbuf;
2448                 QCC_PR_Lex();   //translate the macro's value
2449                 pr_file_p = oldpr_file_p+8;
2450                 return true;
2451         }
2452         if (!strncmp(pr_file_p, "__FUNC__", 8))
2453         {
2454                 static char retbuf[256];
2455                 sprintf(retbuf, "\"%s\"",pr_scope->name);
2456                 pr_file_p = retbuf;
2457                 QCC_PR_Lex();   //translate the macro's value
2458                 pr_file_p = oldpr_file_p+8;
2459                 return true;
2460         }
2461         if (!strncmp(pr_file_p, "__NULL__", 8))
2462         {
2463                 static char retbuf[256];
2464                 sprintf(retbuf, "0i");
2465                 pr_file_p = retbuf;
2466                 QCC_PR_Lex();   //translate the macro's value
2467                 pr_file_p = oldpr_file_p+8;
2468                 return true;
2469         }
2470         return false;
2471 }
2472
2473 char *QCC_PR_CheakCompConstString(char *def)
2474 {
2475         char *s;
2476
2477         CompilerConstant_t *c;
2478
2479         c = pHash_Get(&compconstantstable, def);
2480
2481         if (c)
2482         {
2483                 s = QCC_PR_CheakCompConstString(c->value);
2484                 return s;
2485         }
2486         return def;
2487 }
2488
2489 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def)
2490 {
2491         CompilerConstant_t *c = pHash_Get(&compconstantstable, def);
2492         return c;
2493 }
2494
2495 //============================================================================
2496
2497 /*
2498 ==============
2499 PR_Lex
2500
2501 Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
2502 ==============
2503 */
2504 void QCC_PR_Lex (void)
2505 {
2506         int             c;
2507
2508         pr_token[0] = 0;
2509
2510         if (!pr_file_p)
2511         {
2512                 if (QCC_PR_UnInclude())
2513                 {
2514                         QCC_PR_Lex();
2515                         return;
2516                 }
2517                 pr_token_type = tt_eof;
2518                 return;
2519         }
2520
2521         QCC_PR_LexWhitespace ();
2522
2523         if (!pr_file_p)
2524         {
2525                 if (QCC_PR_UnInclude())
2526                 {
2527                         QCC_PR_Lex();
2528                         return;
2529                 }
2530                 pr_token_type = tt_eof;
2531                 return;
2532         }
2533
2534         c = *pr_file_p;
2535
2536         if (!c)
2537         {
2538                 if (QCC_PR_UnInclude())
2539                 {
2540                         QCC_PR_Lex();
2541                         return;
2542                 }
2543                 pr_token_type = tt_eof;
2544                 return;
2545         }
2546
2547 // handle quoted strings as a unit
2548         if (c == '\"')
2549         {
2550                 QCC_PR_LexString ();
2551                 return;
2552         }
2553
2554 // handle quoted vectors as a unit
2555         if (c == '\'')
2556         {
2557                 QCC_PR_LexVector ();
2558                 return;
2559         }
2560
2561 // if the first character is a valid identifier, parse until a non-id
2562 // character is reached
2563         if ( c == '~' || c == '%')      //let's see which one we make into an operator first... possibly both...
2564         {
2565                 QCC_PR_ParseWarning(0, "~ or %% prefixes to denote integers are deprecated. Please use a postfix of 'i'");
2566                 pr_file_p++;
2567                 pr_token_type = tt_immediate;
2568                 pr_immediate_type = type_integer;
2569                 pr_immediate._int = QCC_PR_LexInteger ();
2570                 return;
2571         }
2572         if ( c == '0' && pr_file_p[1] == 'x')
2573         {
2574                 pr_token_type = tt_immediate;
2575                 QCC_PR_LexNumber();
2576                 return;
2577         }
2578         if ( (c == '.'&&pr_file_p[1]!='.'&&pr_file_p[1] >='0' && pr_file_p[1] <= '9') || (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') )
2579         {
2580                 pr_token_type = tt_immediate;
2581                 QCC_PR_LexNumber ();
2582                 return;
2583         }
2584
2585         if (c == '#' && !(pr_file_p[1]=='-' || (pr_file_p[1]>='0' && pr_file_p[1] <='9')))      //hash and not number
2586         {
2587                 pr_file_p++;
2588                 if (!QCC_PR_CheakCompConst())
2589                 {
2590                         if (!QCC_PR_SimpleGetToken())
2591                                 strcpy(pr_token, "unknown");
2592                         QCC_PR_ParseError(ERR_CONSTANTNOTDEFINED, "Explicit precompiler usage when not defined %s", pr_token);
2593                 }
2594                 else
2595                         if (pr_token_type == tt_eof)
2596                                 QCC_PR_Lex();
2597
2598                 return;
2599         }
2600
2601         if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
2602         {
2603                 if (flag_hashonly || !QCC_PR_CheakCompConst())  //look for a macro.
2604                         QCC_PR_LexName ();
2605                 else
2606                         if (pr_token_type == tt_eof)
2607                         {
2608                                 if (QCC_PR_UnInclude())
2609                                 {
2610                                         QCC_PR_Lex();
2611                                         return;
2612                                 }
2613                                 pr_token_type = tt_eof;
2614                         }
2615                 return;
2616         }
2617
2618         if (c == '$')
2619         {
2620                 QCC_PR_LexGrab ();
2621                 return;
2622         }
2623
2624 // parse symbol strings until a non-symbol is found
2625         QCC_PR_LexPunctuation ();
2626 }
2627
2628 //=============================================================================
2629
2630
2631 void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
2632 {
2633         if (qccwarningdisabled[type])
2634                 return;
2635         if (def->s_file)
2636         {
2637                 if (flag_msvcstyle)
2638                         printf ("%s(%i) :    %s  is defined here\n", strings + def->s_file, def->s_line, def->name);
2639                 else
2640                         printf ("%s:%i:    %s  is defined here\n", strings + def->s_file, def->s_line, def->name);
2641         }
2642 }
2643 void *errorscope;
2644 void QCC_PR_PrintScope (void)
2645 {
2646         if (pr_scope)
2647         {
2648                 if (errorscope != pr_scope)
2649                         printf ("in function %s (line %i),\n", pr_scope->name, pr_scope->s_line);
2650                 errorscope = pr_scope;
2651         }
2652         else
2653         {
2654                 if (errorscope)
2655                         printf ("at global scope,\n");
2656                 errorscope = NULL;
2657         }
2658 }
2659 void QCC_PR_ResetErrorScope(void)
2660 {
2661         errorscope = NULL;
2662 }
2663 /*
2664 ============
2665 PR_ParseError
2666
2667 Aborts the current file load
2668 ============
2669 */
2670 #ifndef QCC
2671 void editbadfile(char *file, int line);
2672 #endif
2673 void VARGS QCC_PR_ParseError (int errortype, char *error, ...)
2674 {
2675         va_list         argptr;
2676         char            string[1024];
2677
2678         va_start (argptr,error);
2679         QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2680         va_end (argptr);
2681
2682 #ifndef QCC
2683         editbadfile(strings+s_file, pr_source_line);
2684 #endif
2685
2686         QCC_PR_PrintScope();
2687         if (flag_msvcstyle)
2688                 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2689         else
2690                 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2691
2692         longjmp (pr_parse_abort, 1);
2693 }
2694 void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...)
2695 {
2696         va_list         argptr;
2697         char            string[1024];
2698
2699         va_start (argptr,error);
2700         QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2701         va_end (argptr);
2702
2703 #ifndef QCC
2704         editbadfile(strings+s_file, pr_source_line);
2705 #endif
2706         QCC_PR_PrintScope();
2707         if (flag_msvcstyle)
2708                 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2709         else
2710                 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2711
2712         QCC_PR_ParsePrintDef(WARN_ERROR, def);
2713
2714         longjmp (pr_parse_abort, 1);
2715 }
2716 void VARGS QCC_PR_ParseWarning (int type, char *error, ...)
2717 {
2718         va_list         argptr;
2719         char            string[1024];
2720
2721         if (type < ERR_PARSEERRORS && qccwarningdisabled[type])
2722                 return;
2723
2724         va_start (argptr,error);
2725         QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2726         va_end (argptr);
2727
2728         QCC_PR_PrintScope();
2729         if (type >= ERR_PARSEERRORS)
2730         {
2731                 if (flag_msvcstyle)
2732                         printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2733                 else
2734                         printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2735                 pr_error_count++;
2736         }
2737         else
2738         {
2739                 if (flag_msvcstyle)
2740                         printf ("%s(%i) : warning: %s\n", strings + s_file, pr_source_line, string);
2741                 else
2742                         printf ("%s:%i: warning: %s\n", strings + s_file, pr_source_line, string);
2743                 pr_warning_count++;
2744         }
2745 }
2746
2747 void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...)
2748 {
2749                 va_list         argptr;
2750         char            string[1024];
2751
2752         if (qccwarningdisabled[type])
2753                 return;
2754
2755         va_start (argptr,error);
2756         QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2757         va_end (argptr);
2758
2759         QCC_PR_PrintScope();
2760         if (file)
2761         {
2762                 if (flag_msvcstyle)
2763                         printf ("%s(%i) : note: %s\n", file, line, string);
2764                 else
2765                         printf ("%s:%i: note: %s\n", file, line, string);
2766         }
2767         else
2768                 printf ("note: %s\n", string);
2769 }
2770
2771 pbool VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
2772 {
2773         va_list         argptr;
2774         char            string[1024];
2775
2776         if (qccwarningdisabled[type])
2777                 return false;
2778
2779         va_start (argptr,error);
2780         QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2781         va_end (argptr);
2782
2783         QCC_PR_PrintScope();
2784         if (file)
2785         {
2786                 if (flag_msvcstyle)
2787                         printf ("%s(%i) : warning: %s\n", file, line, string);
2788                 else
2789                         printf ("%s:%i: warning: %s\n", file, line, string);
2790         }
2791         else
2792                 printf ("warning: %s\n", string);
2793         pr_warning_count++;
2794
2795         return true;
2796 }
2797
2798
2799 /*
2800 =============
2801 PR_Expect
2802
2803 Issues an error if the current token isn't equal to string
2804 Gets the next token
2805 =============
2806 */
2807 #ifndef COMMONINLINES
2808 void QCC_PR_Expect (char *string)
2809 {
2810         if (STRCMP (string, pr_token))
2811                 QCC_PR_ParseError (ERR_EXPECTED, "expected %s, found %s",string, pr_token);
2812         QCC_PR_Lex ();
2813 }
2814 #endif
2815
2816
2817 /*
2818 =============
2819 PR_Check
2820
2821 Returns true and gets the next token if the current token equals string
2822 Returns false and does nothing otherwise
2823 =============
2824 */
2825 #ifndef COMMONINLINES
2826 pbool QCC_PR_CheckToken (char *string)
2827 {
2828         if (pr_token_type != tt_punct)
2829                 return false;
2830
2831         if (STRCMP (string, pr_token))
2832                 return false;
2833
2834         QCC_PR_Lex ();
2835         return true;
2836 }
2837
2838 pbool QCC_PR_CheckImmediate (char *string)
2839 {
2840         if (pr_token_type != tt_immediate)
2841                 return false;
2842
2843         if (STRCMP (string, pr_token))
2844                 return false;
2845
2846         QCC_PR_Lex ();
2847         return true;
2848 }
2849
2850 pbool QCC_PR_CheckName(char *string)
2851 {
2852         if (pr_token_type != tt_name)
2853                 return false;
2854         if (flag_caseinsensative)
2855         {
2856                 if (stricmp (string, pr_token))
2857                         return false;
2858         }
2859         else
2860         {
2861                 if (STRCMP(string, pr_token))
2862                         return false;
2863         }
2864         QCC_PR_Lex ();
2865         return true;
2866 }
2867
2868 pbool QCC_PR_CheckKeyword(int keywordenabled, char *string)
2869 {
2870         if (!keywordenabled)
2871                 return false;
2872         if (flag_caseinsensative)
2873         {
2874                 if (stricmp (string, pr_token))
2875                         return false;
2876         }
2877         else
2878         {
2879                 if (STRCMP(string, pr_token))
2880                         return false;
2881         }
2882         QCC_PR_Lex ();
2883         return true;
2884 }
2885 #endif
2886
2887
2888 /*
2889 ============
2890 PR_ParseName
2891
2892 Checks to see if the current token is a valid name
2893 ============
2894 */
2895 char *QCC_PR_ParseName (void)
2896 {
2897         static char     ident[MAX_NAME];
2898         char *ret;
2899
2900         if (pr_token_type != tt_name)
2901         {
2902                 if (pr_token_type == tt_eof)
2903                         QCC_PR_ParseError (ERR_EOF, "unexpected EOF", pr_token);
2904                 else
2905                         QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
2906         }
2907         if (strlen(pr_token) >= MAX_NAME-1)
2908                 QCC_PR_ParseError (ERR_NAMETOOLONG, "name too long");
2909         strcpy (ident, pr_token);
2910         QCC_PR_Lex ();
2911
2912         ret = qccHunkAlloc(strlen(ident)+1);
2913         strcpy(ret, ident);
2914         return ret;
2915 //      return ident;
2916 }
2917
2918 /*
2919 ============
2920 PR_FindType
2921
2922 Returns a preexisting complex type that matches the parm, or allocates
2923 a new one and copies it out.
2924 ============
2925 */
2926
2927 //0 if same
2928 int typecmp(QCC_type_t *a, QCC_type_t *b)
2929 {
2930         if (a == b)
2931                 return 0;
2932         if (!a || !b)
2933                 return 1;       //different (^ and not both null)
2934
2935         if (a->type != b->type)
2936                 return 1;
2937         if (a->num_parms != b->num_parms)
2938         {
2939                 return 1;
2940         }
2941
2942         if (a->size != b->size)
2943                 return 1;
2944 //      if (STRCMP(a->name, b->name))   //This isn't 100% clean.
2945 //              return 1;
2946
2947         if (typecmp(a->aux_type, b->aux_type))
2948                 return 1;
2949
2950         if (a->param || b->param)
2951         {
2952                 a = a->param;
2953                 b = b->param;
2954
2955                 while(a || b)
2956                 {
2957                         if (typecmp(a, b))
2958                                 return 1;
2959
2960                         a=a->next;
2961                         b=b->next;
2962                 }
2963         }
2964
2965         return 0;
2966 }
2967
2968 QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in)
2969 {
2970         QCC_type_t *out, *op, *ip;
2971         if (!in)
2972                 return NULL;
2973
2974         out = QCC_PR_NewType(in->name, in->type, false);
2975         out->aux_type = QCC_PR_DuplicateType(in->aux_type);
2976         out->param = QCC_PR_DuplicateType(in->param);
2977         ip = in->param;
2978         op = NULL;
2979         while(ip)
2980         {
2981                 if (!op)
2982                         out->param = op = QCC_PR_DuplicateType(ip);
2983                 else
2984                         op = (op->next = QCC_PR_DuplicateType(ip));
2985                 ip = ip->next;
2986         }
2987         out->arraysize = in->arraysize;
2988         out->size = in->size;
2989         out->num_parms = in->num_parms;
2990         out->ofs = in->ofs;
2991         out->name = in->name;
2992         out->parentclass = in->parentclass;
2993
2994         return out;
2995 }
2996
2997 char *TypeName(QCC_type_t *type)
2998 {
2999         static char buffer[2][512];
3000         static int op;
3001         char *ret;
3002
3003
3004         op++;
3005         ret = buffer[op&1];
3006         if (type->type == ev_field)
3007         {
3008                 type = type->aux_type;
3009                 *ret++ = '.';
3010         }
3011         *ret = 0;
3012
3013         if (type->type == ev_function)
3014         {
3015                 pbool varg = type->num_parms < 0;
3016                 int args = type->num_parms;
3017                 if (args < 0)
3018                         args = -(args+1);
3019                 strcat(ret, type->aux_type->name);
3020                 strcat(ret, " (");
3021                 type = type->param;
3022                 while(type)
3023                 {
3024                         if (args<=0)
3025                                 strcat(ret, "optional ");
3026                         args--;
3027
3028                         strcat(ret, type->name);
3029                         type = type->next;
3030
3031                         if (type || varg)
3032                                 strcat(ret, ", ");
3033                 }
3034                 if (varg)
3035                 {
3036                         strcat(ret, "...");
3037                 }
3038                 strcat(ret, ")");
3039         }
3040         else if (type->type == ev_entity && type->parentclass)
3041         {
3042                 ret = buffer[op&1];
3043                 *ret = 0;
3044                 strcat(ret, "class ");
3045                 strcat(ret, type->name);
3046 /*              strcat(ret, " {");
3047                 type = type->param;
3048                 while(type)
3049                 {
3050                         strcat(ret, type->name);
3051                         type = type->next;
3052
3053                         if (type)
3054                                 strcat(ret, ", ");
3055                 }
3056                 strcat(ret, "}");
3057 */
3058         }
3059         else
3060                 strcpy(ret, type->name);
3061
3062         return buffer[op&1];
3063 }
3064 //#define typecmp(a, b) (a && ((a)->type==(b)->type) && !STRCMP((a)->name, (b)->name))
3065
3066 QCC_type_t *QCC_PR_FindType (QCC_type_t *type)
3067 {
3068         int t;
3069         for (t = 0; t < numtypeinfos; t++)
3070         {
3071 //              check = &qcc_typeinfo[t];
3072                 if (typecmp(&qcc_typeinfo[t], type))
3073                         continue;
3074
3075
3076 //              c2 = check->next;
3077 //              n2 = type->next;
3078 //              for (i=0 ; n2&&c2 ; i++)
3079 //              {
3080 //                      if (!typecmp((c2), (n2)))
3081 //                              break;
3082 //                      c2=c2->next;
3083 //                      n2=n2->next;
3084 //              }
3085
3086 //              if (n2==NULL&&c2==NULL)
3087                 {
3088                         return &qcc_typeinfo[t];
3089                 }
3090         }
3091 QCC_Error(ERR_INTERNAL, "Error with type");
3092
3093         return type;
3094 }
3095 /*
3096 QCC_type_t *QCC_PR_NextSubType(QCC_type_t *type, QCC_type_t *prev)
3097 {
3098         int p;
3099         if (!prev)
3100                 return type->next;
3101
3102         for (p = prev->num_parms; p; p--)
3103                 prev = QCC_PR_NextSubType(prev, NULL);
3104         if (prev->num_parms)
3105
3106         switch(prev->type)
3107         {
3108         case ev_function:
3109
3110         }
3111
3112         return prev->next;
3113 }
3114 */
3115
3116 QCC_type_t *QCC_TypeForName(char *name)
3117 {
3118         int i;
3119
3120         for (i = 0; i < numtypeinfos; i++)
3121         {
3122                 if (!STRCMP(qcc_typeinfo[i].name, name))
3123                 {
3124                         return &qcc_typeinfo[i];
3125                 }
3126         }
3127
3128         return NULL;
3129 }
3130
3131 /*
3132 ============
3133 PR_SkipToSemicolon
3134
3135 For error recovery, also pops out of nested braces
3136 ============
3137 */
3138 void QCC_PR_SkipToSemicolon (void)
3139 {
3140         do
3141         {
3142                 if (!pr_bracelevel && QCC_PR_CheckToken (";"))
3143                         return;
3144                 QCC_PR_Lex ();
3145         } while (pr_token_type != tt_eof);
3146 }
3147
3148
3149 /*
3150 ============
3151 PR_ParseType
3152
3153 Parses a variable type, including field and functions types
3154 ============
3155 */
3156 #ifdef MAX_EXTRA_PARMS
3157 char    pr_parm_names[MAX_PARMS+MAX_EXTRA_PARMS][MAX_NAME];
3158 #else
3159 char    pr_parm_names[MAX_PARMS][MAX_NAME];
3160 #endif
3161
3162 pbool recursivefunctiontype;
3163
3164 //expects a ( to have already been parsed.
3165 QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
3166 {
3167         QCC_type_t      *ftype, *ptype, *nptype;
3168         char    *name;
3169         int definenames = !recursivefunctiontype;
3170         int optional = 0;
3171         int numparms = 0;
3172
3173         recursivefunctiontype++;
3174
3175         ftype = QCC_PR_NewType(type_function->name, ev_function, false);
3176
3177         ftype->aux_type = returntype;   // return type
3178         ftype->num_parms = 0;
3179         ptype = NULL;
3180
3181
3182         if (!QCC_PR_CheckToken (")"))
3183         {
3184                 if (QCC_PR_CheckToken ("..."))
3185                         ftype->num_parms = -1;  // variable args
3186                 else
3187                         do
3188                         {
3189                                 if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
3190                                         QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS);
3191
3192                                 if (QCC_PR_CheckToken ("..."))
3193                                 {
3194                                         if (optional)
3195                                                 numparms = optional-1;
3196                                         ftype->num_parms = (numparms * -1) - 1;
3197                                         break;
3198                                 }
3199
3200                                 if (QCC_PR_CheckKeyword(keyword_optional, "optional"))
3201                                 {
3202                                         if (!optional)
3203                                                 optional = numparms+1;
3204                                 }
3205                                 else if (optional)
3206                                         QCC_PR_ParseWarning(WARN_MISSINGOPTIONAL, "optional not specified on all optional args\n");
3207
3208                                 nptype = QCC_PR_ParseType(true, false);
3209
3210                                 if (nptype->type == ev_void)
3211                                         break;
3212                                 if (!ptype)
3213                                 {
3214                                         ptype = nptype;
3215                                         ftype->param = ptype;
3216                                 }
3217                                 else
3218                                 {
3219                                         ptype->next = nptype;
3220                                         ptype = ptype->next;
3221                                 }
3222 //                              type->name = "FUNC PARAMETER";
3223
3224
3225                                 if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")"))
3226                                 {
3227                                         name = QCC_PR_ParseName ();
3228                                         if (definenames)
3229                                                 strcpy (pr_parm_names[numparms], name);
3230                                 }
3231                                 else if (definenames)
3232                                         strcpy (pr_parm_names[numparms], "");
3233                                 numparms++;
3234                                 if (optional)
3235                                         ftype->num_parms = optional-1;
3236                                 else
3237                                         ftype->num_parms = numparms;
3238                         } while (QCC_PR_CheckToken (","));
3239
3240                 QCC_PR_Expect (")");
3241         }
3242         recursivefunctiontype--;
3243         if (newtype)
3244                 return ftype;
3245         return QCC_PR_FindType (ftype);
3246 }
3247 QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
3248 {
3249         QCC_type_t      *ftype, *ptype, *nptype;
3250         char    *name;
3251         char    argname[64];
3252         int definenames = !recursivefunctiontype;
3253
3254         recursivefunctiontype++;
3255
3256         ftype = QCC_PR_NewType(type_function->name, ev_function, false);
3257
3258         ftype->aux_type = returntype;   // return type
3259         ftype->num_parms = 0;
3260         ptype = NULL;
3261
3262
3263         if (!QCC_PR_CheckToken (")"))
3264         {
3265                 if (QCC_PR_CheckToken ("..."))
3266                         ftype->num_parms = -1;  // variable args
3267                 else
3268                         do
3269                         {
3270                                 if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
3271                                         QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS);
3272
3273                                 if (QCC_PR_CheckToken ("..."))
3274                                 {
3275                                         ftype->num_parms = (ftype->num_parms * -1) - 1;
3276                                         break;
3277                                 }
3278
3279                                 if (QCC_PR_CheckName("arg"))
3280                                 {
3281                                         sprintf(argname, "arg%i", ftype->num_parms);
3282                                         name = argname;
3283                                         nptype = QCC_PR_NewType("Variant", ev_variant, false);
3284                                 }
3285                                 else if (QCC_PR_CheckName("vect"))      //this can only be of vector sizes, so...
3286                                 {
3287                                         sprintf(argname, "arg%i", ftype->num_parms);
3288                                         name = argname;
3289                                         nptype = QCC_PR_NewType("Vector", ev_vector, false);
3290                                 }
3291                                 else
3292                                 {
3293                                         name = QCC_PR_ParseName();
3294                                         QCC_PR_Expect(":");
3295                                         nptype = QCC_PR_ParseType(true, false);
3296                                 }
3297
3298                                 if (nptype->type == ev_void)
3299                                         break;
3300                                 if (!ptype)
3301                                 {
3302                                         ptype = nptype;
3303                                         ftype->param = ptype;
3304                                 }
3305                                 else
3306                                 {
3307                                         ptype->next = nptype;
3308                                         ptype = ptype->next;
3309                                 }
3310 //                              type->name = "FUNC PARAMETER";
3311
3312                                 if (definenames)
3313                                         strcpy (pr_parm_names[ftype->num_parms], name);
3314                                 ftype->num_parms++;
3315                         } while (QCC_PR_CheckToken (";"));
3316
3317                 QCC_PR_Expect (")");
3318         }
3319         recursivefunctiontype--;
3320         if (newtype)
3321                 return ftype;
3322         return QCC_PR_FindType (ftype);
3323 }
3324 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
3325 {
3326         QCC_type_t      *ptype, *e;
3327         ptype = QCC_PR_NewType("ptr", ev_pointer, false);
3328         ptype->aux_type = pointsto;
3329         e = QCC_PR_FindType (ptype);
3330         if (e == ptype)
3331         {
3332                 char name[128];
3333                 sprintf(name, "ptr to %s", pointsto->name);
3334                 e->name = strdup(name);
3335         }
3336         return e;
3337 }
3338 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
3339 {
3340         QCC_type_t      *ptype;
3341         char name[128];
3342         sprintf(name, "FIELD TYPE(%s)", pointsto->name);
3343         ptype = QCC_PR_NewType(name, ev_field, false);
3344         ptype->aux_type = pointsto;
3345         ptype->size = ptype->aux_type->size;
3346         return QCC_PR_FindType (ptype);
3347 }
3348
3349 pbool type_inlinefunction;
3350 /*newtype=true: creates a new type always
3351   silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL
3352 */
3353 QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
3354 {
3355         QCC_type_t      *newparm;
3356         QCC_type_t      *newt;
3357         QCC_type_t      *type;
3358         char    *name;
3359         int i;
3360
3361         type_inlinefunction = false;    //doesn't really matter so long as its not from an inline function type
3362
3363 //      int ofs;
3364
3365         if (QCC_PR_CheckToken (".."))   //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges)
3366         {
3367                 newt = QCC_PR_NewType("FIELD TYPE", ev_field, false);
3368                 newt->aux_type = QCC_PR_ParseType (false, false);
3369
3370                 newt->size = newt->aux_type->size;
3371
3372                 newt = QCC_PR_FindType (newt);
3373
3374                 type = QCC_PR_NewType("FIELD TYPE", ev_field, false);
3375                 type->aux_type = newt;
3376
3377                 type->size = type->aux_type->size;
3378
3379                 if (newtype)
3380                         return type;
3381                 return QCC_PR_FindType (type);
3382         }
3383         if (QCC_PR_CheckToken ("."))
3384         {
3385                 newt = QCC_PR_NewType("FIELD TYPE", ev_field, false);
3386                 newt->aux_type = QCC_PR_ParseType (false, false);
3387
3388                 newt->size = newt->aux_type->size;
3389
3390                 if (newtype)
3391                         return newt;
3392                 return QCC_PR_FindType (newt);
3393         }
3394
3395         name = QCC_PR_CheakCompConstString(pr_token);
3396
3397         if (QCC_PR_CheckKeyword (keyword_class, "class"))
3398         {
3399 //              int parms;
3400                 QCC_type_t *fieldtype;
3401                 char membername[2048];
3402                 char *classname = QCC_PR_ParseName();
3403                 int forwarddeclaration;
3404
3405                 newt = 0;
3406
3407                 /* Don't advance the line number yet */
3408                 forwarddeclaration = pr_token[0] == ';';
3409
3410                 /* Look to see if this type is already defined */
3411                 for(i=0;i<numtypeinfos;i++)
3412                 {
3413                         if (!qcc_typeinfo[i].typedefed)
3414                                 continue;
3415                         if (STRCMP(qcc_typeinfo[i].name, classname) == 0)
3416                         {
3417                                 newt = &qcc_typeinfo[i];
3418                                 break;
3419                         }
3420                 }
3421
3422                 if (newt && forwarddeclaration)
3423                         QCC_PR_ParseError(ERR_REDECLARATION, "Forward declaration of already defined class %s", classname);
3424
3425                 if (newt && newt->num_parms != 0)
3426                         QCC_PR_ParseError(ERR_REDECLARATION, "Redeclaration of class %s", classname);
3427
3428                 if (!newt)
3429                         newt = QCC_PR_NewType(classname, ev_entity, true);
3430
3431                 newt->size=type_entity->size;
3432
3433                 type = NULL;
3434
3435                 if (forwarddeclaration)
3436                 {
3437                         QCC_PR_CheckToken(";");
3438                         return NULL;
3439                 }
3440
3441
3442
3443                 if (QCC_PR_CheckToken(":"))
3444                 {
3445                         char *parentname = QCC_PR_ParseName();
3446                         newt->parentclass = QCC_TypeForName(parentname);
3447                         if (!newt->parentclass)
3448                                 QCC_PR_ParseError(ERR_NOTANAME, "Parent class %s was not defined", parentname);
3449                 }
3450                 else
3451                         newt->parentclass = type_entity;
3452
3453
3454                 QCC_PR_Expect("{");
3455                 if (QCC_PR_CheckToken(","))
3456                         QCC_PR_ParseError(ERR_NOTANAME, "member missing name");
3457                 while (!QCC_PR_CheckToken("}"))
3458                 {
3459 //                      if (QCC_PR_CheckToken(","))
3460 //                              type->next = QCC_PR_NewType(type->name, type->type);
3461 //                      else
3462                                 newparm = QCC_PR_ParseType(true, false);
3463
3464                         if (newparm->type == ev_struct || newparm->type == ev_union)    //we wouldn't be able to handle it.
3465                                 QCC_PR_ParseError(ERR_INTERNAL, "Struct or union in class %s", classname);
3466
3467                         if (!QCC_PR_CheckToken(";"))
3468                         {
3469                                 newparm->name = QCC_CopyString(pr_token)+strings;
3470                                 QCC_PR_Lex();
3471                                 if (QCC_PR_CheckToken("["))
3472                                 {
3473                                         type->next->size*=atoi(pr_token);
3474                                         QCC_PR_Lex();
3475                                         QCC_PR_Expect("]");
3476                                 }
3477                                 QCC_PR_CheckToken(";");
3478                         }
3479                         else
3480                                 newparm->name = QCC_CopyString("")+strings;
3481
3482                         sprintf(membername, "%s::"MEMBERFIELDNAME, classname, newparm->name);
3483                         fieldtype = QCC_PR_NewType(newparm->name, ev_field, false);
3484                         fieldtype->aux_type = newparm;
3485                         fieldtype->size = newparm->size;
3486                         QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 0, false);
3487
3488
3489                         newparm->ofs = 0;//newt->size;
3490                         newt->num_parms++;
3491
3492                         if (type)
3493                                 type->next = newparm;
3494                         else
3495                                 newt->param = newparm;
3496
3497                         type = newparm;
3498                 }
3499
3500
3501                 QCC_PR_Expect(";");
3502                 return NULL;
3503         }
3504         if (QCC_PR_CheckKeyword (keyword_struct, "struct"))
3505         {
3506                 newt = QCC_PR_NewType("struct", ev_struct, false);
3507                 newt->size=0;
3508                 QCC_PR_Expect("{");
3509
3510                 type = NULL;
3511                 if (QCC_PR_CheckToken(","))
3512                         QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3513
3514                 newparm = NULL;
3515                 while (!QCC_PR_CheckToken("}"))
3516                 {
3517                         if (QCC_PR_CheckToken(","))
3518                         {
3519                                 if (!newparm)
3520                                         QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3521                                 newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
3522                         }
3523                         else
3524                                 newparm = QCC_PR_ParseType(true, false);
3525
3526                         if (!QCC_PR_CheckToken(";"))
3527                         {
3528                                 newparm->name = QCC_CopyString(pr_token)+strings;
3529                                 QCC_PR_Lex();
3530                                 if (QCC_PR_CheckToken("["))
3531                                 {
3532                                         newparm->arraysize=QCC_PR_IntConstExpr();
3533                                         QCC_PR_Expect("]");
3534                                 }
3535                                 QCC_PR_CheckToken(";");
3536                         }
3537                         else
3538                                 newparm->name = QCC_CopyString("")+strings;
3539                         newparm->ofs = newt->size;
3540                         newt->size += newparm->size*(newparm->arraysize?newparm->arraysize:1);
3541                         newt->num_parms++;
3542
3543                         if (type)
3544                                 type->next = newparm;
3545                         else
3546                                 newt->param = newparm;
3547                         type = newparm;
3548                 }
3549                 return newt;
3550         }
3551         if (QCC_PR_CheckKeyword (keyword_union, "union"))
3552         {
3553                 newt = QCC_PR_NewType("union", ev_union, false);
3554                 newt->size=0;
3555                 QCC_PR_Expect("{");
3556
3557                 type = NULL;
3558                 if (QCC_PR_CheckToken(","))
3559                         QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3560                 newparm = NULL;
3561                 while (!QCC_PR_CheckToken("}"))
3562                 {
3563                         int arraysize;
3564                         if (QCC_PR_CheckToken(","))
3565                         {
3566                                 if (!newparm)
3567                                         QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3568                                 newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
3569                         }
3570                         else
3571                                 newparm = QCC_PR_ParseType(true, false);
3572                         if (QCC_PR_CheckToken(";"))
3573                                 newparm->name = QCC_CopyString("")+strings;
3574                         else
3575                         {
3576                                 newparm->name = QCC_CopyString(pr_token)+strings;
3577                                 QCC_PR_Lex();
3578                                 if (QCC_PR_CheckToken("["))
3579                                 {
3580                                         newparm->arraysize=QCC_PR_IntConstExpr();
3581                                         QCC_PR_Expect("]");
3582                                 }
3583                                 QCC_PR_Expect(";");
3584                         }
3585                         newparm->ofs = 0;
3586                         arraysize = newparm->arraysize;
3587                         if (!arraysize)
3588                                 arraysize = 1;
3589                         if (newparm->size*arraysize > newt->size)
3590                                 newt->size = newparm->size*arraysize;
3591                         newt->num_parms++;
3592
3593                         if (type)
3594                                 type->next = newparm;
3595                         else
3596                                 newt->param = newparm;
3597                         type = newparm;
3598                 }
3599                 return newt;
3600         }
3601         type = NULL;
3602         for (i = 0; i < numtypeinfos; i++)
3603         {
3604                 if (!qcc_typeinfo[i].typedefed)
3605                         continue;
3606                 if (!STRCMP(qcc_typeinfo[i].name, name))
3607                 {
3608                         type = &qcc_typeinfo[i];
3609                         break;
3610                 }
3611         }
3612
3613         if (i == numtypeinfos)
3614         {
3615                 if (!*name)
3616                         return NULL;
3617                 if (!stricmp("Void", name))
3618                         type = type_void;
3619                 else if (!stricmp("Real", name))
3620                         type = type_float;
3621                 else if (!stricmp("Vector", name))
3622                         type = type_vector;
3623                 else if (!stricmp("Object", name))
3624                         type = type_entity;
3625                 else if (!stricmp("String", name))
3626                         type = type_string;
3627                 else if (!stricmp("PFunc", name))
3628                         type = type_function;
3629                 else
3630                 {
3631                         if (silentfail)
3632                                 return NULL;
3633
3634                         QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name);
3635                         type = type_float;      // shut up compiler warning
3636                 }
3637         }
3638         QCC_PR_Lex ();
3639
3640         while (QCC_PR_CheckToken("*"))
3641                 type = QCC_PointerTypeTo(type);
3642
3643         if (QCC_PR_CheckToken ("("))    //this is followed by parameters. Must be a function.
3644         {
3645                 type_inlinefunction = true;
3646                 type = QCC_PR_ParseFunctionType(newtype, type);
3647         }
3648         else
3649         {
3650                 if (newtype)
3651                 {
3652                         type = QCC_PR_DuplicateType(type);
3653                 }
3654         }
3655         return type;
3656 }
3657
3658 #endif
3659
3660
3661