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