9 #define MEMBERFIELDNAME "__m%s"
11 #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc
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);
24 char *pr_line_start; // start of current source line
29 token_type_t pr_token_type;
30 QCC_type_t *pr_immediate_type;
31 QCC_eval_t pr_immediate;
33 char pr_immediate_string[8192];
39 CompilerConstant_t *CompilerConstant;
40 int numCompilerConstants;
41 extern pbool expandedemptymacro;
45 char *pr_punctuation[] =
46 // longer symbols must be before a shorter partial match
47 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
49 char *pr_punctuationremap[] = //a nice bit of evilness.
53 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
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*/};
68 QCC_type_t *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float};
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"};
80 QCC_def_t def_ret, def_parms[MAX_PARMS];
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};
84 void QCC_PR_LexWhitespace (void);
89 //for compiler constants and file includes.
91 typedef struct qcc_includechunk_s {
92 struct qcc_includechunk_s *prev;
94 char *currentdatapoint;
95 int currentlinenumber;
96 CompilerConstant_t *cnst;
98 qcc_includechunk_t *currentchunk;
99 void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst)
101 qcc_includechunk_t *chunk = qccHunkAlloc(sizeof(qcc_includechunk_t));
102 chunk->prev = currentchunk;
103 currentchunk = chunk;
105 chunk->currentdatapoint = pr_file_p;
106 chunk->currentlinenumber = pr_source_line;
115 pr_file_p = qccHunkAlloc(strlen(data)+1);
116 strcpy(pr_file_p, data);
121 void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename)
123 QCC_PR_IncludeChunkEx(data, duplicate, filename, NULL);
126 pbool QCC_PR_UnInclude(void)
131 if( currentchunk->cnst )
132 currentchunk->cnst->inside--;
134 pr_file_p = currentchunk->currentdatapoint;
135 pr_source_line = currentchunk->currentlinenumber;
137 currentchunk = currentchunk->prev;
148 void QCC_PR_PrintNextLine (void)
152 printf ("%3i:",pr_source_line);
153 for (t=pr_line_start ; *t && *t != '\n' ; t++)
158 extern char qccmsourcedir[];
159 //also meant to include it.
160 void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
162 char fullname[10248];
166 char *end = fullname;
172 while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
178 currentfile += strlen(rootpath); //could this be bad?
180 for(stripfrom = currentfile+strlen(currentfile)-1; stripfrom>currentfile; stripfrom--)
182 if (*stripfrom == '/' || *stripfrom == '\\')
193 strcpy(end, rootpath); end = end+strlen(end);
194 if (*fullname && end[-1] != '/')
197 end = end+strlen(end);
199 strncpy(end, currentfile, stripfrom - currentfile); end += stripfrom - currentfile; *end = '\0';
200 strcpy(end, newfile);
202 QCC_Include(fullname);
207 int QCC_PR_LexInteger (void);
208 void QCC_AddFile (char *filename);
209 void QCC_PR_LexString (void);
210 pbool QCC_PR_SimpleGetToken (void);
212 int ParsePrecompilerIf(void)
214 CompilerConstant_t *c;
216 char *start = pr_file_p;
217 if (!QCC_PR_SimpleGetToken())
219 if (*pr_file_p == '(')
221 eval = ParsePrecompilerIf();
222 while (*pr_file_p == ' ' || *pr_file_p == '\t')
224 if (*pr_file_p != ')')
225 QCC_PR_ParseError(ERR_EXPECTED, "unclosed bracket condition\n");
228 QCC_PR_ParseError(ERR_EXPECTED, "expected bracket or constant\n");
230 else if (!strcmp(pr_token, "defined"))
232 while (*pr_file_p == ' ' || *pr_file_p == '\t')
234 if (*pr_file_p != '(')
235 QCC_PR_ParseError(ERR_EXPECTED, "no opening bracket after defined\n");
240 QCC_PR_SimpleGetToken();
241 eval = !!QCC_PR_CheckCompConstDefined(pr_token);
243 while (*pr_file_p == ' ' || *pr_file_p == '\t')
245 if (*pr_file_p != ')')
246 QCC_PR_ParseError(ERR_EXPECTED, "unclosed defined condition\n");
252 c = QCC_PR_CheckCompConstDefined(pr_token);
254 eval = atoi(pr_token);
256 eval = atoi(c->value);
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();
282 Runs precompiler stage
284 pbool QCC_PR_Precompiler(void)
290 int level; //#if level
293 if (*pr_file_p == '#')
296 for (directive = pr_file_p+1; *directive; directive++) //so # define works
298 if (*directive == '\r' || *directive == '\n')
299 QCC_PR_ParseError(ERR_UNKNOWNPUCTUATION, "Hanging # with no directive\n");
300 if (*directive > ' ')
303 if (!strncmp(directive, "define", 6))
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
312 else if (!strncmp(directive, "undef", 5))
314 pr_file_p = directive+5;
315 while(*pr_file_p <= ' ')
318 QCC_PR_SimpleGetToken ();
319 QCC_PR_UndefineName(pr_token);
321 // QCC_PR_ConditionCompilation();
322 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
327 else if (!strncmp(directive, "if", 2))
329 int originalline = pr_source_line;
330 pr_file_p = directive+2;
331 if (!strncmp(pr_file_p, "def ", 4))
336 else if (!strncmp(pr_file_p, "ndef ", 5))
345 //QCC_PR_ParseError("bad \"#if\" type");
350 eval = ParsePrecompilerIf();
352 if(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
354 QCC_PR_ParseError (ERR_NOENDIF, "junk on the end of #if line");
359 QCC_PR_SimpleGetToken ();
361 // if (!STRCMP(pr_token, "COOP_MODE"))
363 if (QCC_PR_CheckCompConstDefined(pr_token))
367 eval = eval?false:true;
370 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
382 while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
387 pr_source_line = originalline;
388 QCC_PR_ParseError (ERR_NOENDIF, "#if with no endif");
391 if (*pr_file_p == '#')
394 while(*pr_file_p==' ' || *pr_file_p == '\t')
396 if (!strncmp(pr_file_p, "endif", 5))
398 if (!strncmp(pr_file_p, "if", 2))
400 if (!strncmp(pr_file_p, "else", 4) && level == 1)
403 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
411 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
417 pr_file_p++; //next line
422 else if (!strncmp(directive, "else", 4))
424 int originalline = pr_source_line;
429 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
435 while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
440 pr_source_line = originalline;
441 QCC_PR_ParseError(ERR_NOENDIF, "#if with no endif");
444 if (*pr_file_p == '#')
447 while(*pr_file_p==' ' || *pr_file_p == '\t')
450 if (!strncmp(pr_file_p, "endif", 5))
452 if (!strncmp(pr_file_p, "if", 2))
454 if (!strncmp(pr_file_p, "else", 4) && level == 1)
461 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
467 pr_file_p++; //go off the end
471 else if (!strncmp(directive, "endif", 5))
473 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
478 QCC_PR_ParseError(ERR_NOPRECOMPILERIF, "unmatched #endif");
482 else if (!strncmp(directive, "eof", 3))
487 else if (!strncmp(directive, "error", 5))
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];
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...
500 QCC_PR_ParseError(ERR_HASHERROR, "#Error: %s", msg);
502 else if (!strncmp(directive, "warning", 7))
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];
510 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
515 QCC_PR_ParseWarning(WARN_PRECOMPILERMESSAGE, "#warning: %s", msg);
517 else if (!strncmp(directive, "message", 7))
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];
525 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
530 printf("#message: %s\n", msg);
532 else if (!strncmp(directive, "copyright", 9))
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];
540 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
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);
549 else if (!strncmp(directive, "pack", 4))
552 pr_file_p=directive+4;
553 if (!strncmp(pr_file_p, "id", 2))
557 ifmode = QCC_PR_LexInteger();
562 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
563 msg[a] = pr_file_p[a];
567 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
573 QCC_packid = atoi(msg);
574 else if (ifmode <= 5)
575 strcpy(QCC_Packname[ifmode-1], msg);
577 QCC_PR_ParseError(ERR_TOOMANYPACKFILES, "No more than 5 packs are allowed");
579 else if (!strncmp(directive, "forcecrc", 8))
581 pr_file_p=directive+8;
583 ForcedCRC = QCC_PR_LexInteger();
587 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
588 msg[a] = pr_file_p[a];
592 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
597 else if (!strncmp(directive, "includelist", 11))
599 pr_file_p=directive+11;
601 while(*pr_file_p <= ' ')
606 QCC_PR_LexWhitespace();
607 if (!QCC_PR_SimpleGetToken())
610 QCC_Error(ERR_EOF, "eof in includelist");
618 if (!strcmp(pr_token, "#endlist"))
621 QCC_FindBestInclude(pr_token, compilingfile, qccmsourcedir);
623 if (*pr_file_p == '\r')
626 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
627 msg[a] = pr_file_p[a];
631 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
637 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
642 else if (!strncmp(directive, "include", 7))
646 pr_file_p=directive+7;
648 while(*pr_file_p <= ' ')
652 if (*pr_file_p == '\"')
654 else if (*pr_file_p == '<')
658 QCC_PR_ParseError(0, "Not a string literal (on a #include)");
663 while(*pr_file_p != sm)
665 if (*pr_file_p == '\n')
667 QCC_PR_ParseError(0, "#include continued over line boundy\n");
670 msg[a++] = *pr_file_p;
675 QCC_FindBestInclude(msg, compilingfile, qccmsourcedir);
679 while(*pr_file_p != '\n' && *pr_file_p != '\0' && *pr_file_p <= ' ')
683 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
688 else if (!strncmp(directive, "datafile", 8))
690 pr_file_p=directive+8;
692 while(*pr_file_p <= ' ')
696 printf("Including datafile: %s\n", pr_token);
697 QCC_AddFile(pr_token);
701 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
702 msg[a] = pr_file_p[a];
706 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
711 else if (!strncmp(directive, "output", 6))
713 extern char destfile[1024];
714 pr_file_p=directive+6;
716 while(*pr_file_p <= ' ')
720 strcpy(destfile, pr_token);
721 printf("Outputfile: %s\n", destfile);
725 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
726 msg[a] = pr_file_p[a];
730 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
735 else if (!strncmp(directive, "pragma", 6))
737 pr_file_p=directive+6;
738 while(*pr_file_p <= ' ')
742 for(a = 0; *pr_file_p != '\n' && *pr_file_p != '\0'; pr_file_p++) //read on until the end of the line
744 if ((*pr_file_p == ' ' || *pr_file_p == '\t'|| *pr_file_p == '(') && !*qcc_token)
747 strcpy(qcc_token, msg);
751 msg[a++] = *pr_file_p;
757 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
763 strcpy(qcc_token, msg);
769 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
773 if (!QC_strcasecmp(qcc_token, "DONT_COMPILE_THIS_FILE"))
777 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
780 if (*pr_file_p == '\n')
783 QCC_PR_NewLine(false);
787 else if (!QC_strcasecmp(qcc_token, "COPYRIGHT"))
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);
793 else if (!strncmp(qcc_token, "compress", 8))
795 extern pbool compressoutput;
796 compressoutput = atoi(msg);
798 else if (!strncmp(qcc_token, "forcecrc", 8))
800 ForcedCRC = atoi(msg);
802 else if (!strncmp(qcc_token, "defaultstatic", 13))
804 defaultstatic = atoi(msg);
806 else if (!strncmp(qcc_token, "sourcefile", 10))
808 #define MAXSOURCEFILESLIST 8
809 extern char sourcefileslist[MAXSOURCEFILESLIST][1024];
810 extern int currentsourcefile;
811 extern int numsourcefiles;
817 for (i = 0; i < numsourcefiles; i++)
819 if (!strcmp(sourcefileslist[i], qcc_token))
822 if (i == numsourcefiles)
823 strcpy(sourcefileslist[numsourcefiles++], qcc_token);
825 else if (!QC_strcasecmp(qcc_token, "TARGET"))
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"))
832 QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch from hexen2 target \'%s\'. Ignored.", msg);
834 qcc_targetformat = QCF_HEXEN2;
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;
849 QCC_PR_ParseWarning(WARN_BADTARGET, "Unknown target \'%s\'. Ignored.", msg);
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.
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];
858 extern char qccmfilename[1024];
867 if (!strncmp(s2, "./", 2))
871 while(!strncmp(s2, "../", 3))
877 strcpy(qccmfilename, qccmsourcedir);
878 for (s=qccmfilename+strlen(qccmfilename);p && s>=qccmfilename; s--)
880 if (*s == '/' || *s == '\\')
886 sprintf(destfile, "%s", s2);
890 memmove(destfile+3, destfile, strlen(destfile)+1);
898 strcpy(destfile, qcc_token);
900 printf("Outputfile: %s\n", destfile);
902 else if (!QC_strcasecmp(qcc_token, "keyword") || !QC_strcasecmp(qcc_token, "flag"))
906 s = QCC_COM_Parse(msg);
907 if (!QC_strcasecmp(qcc_token, "enable") || !QC_strcasecmp(qcc_token, "on"))
909 else if (!QC_strcasecmp(qcc_token, "disable") || !QC_strcasecmp(qcc_token, "off"))
913 QCC_PR_ParseWarning(WARN_BADPRAGMA, "compiler flag state not recognised");
917 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
921 s = QCC_COM_Parse(s);
923 for (f = 0; compiler_flag[f].enabled; f++)
925 if (!QC_strcasecmp(compiler_flag[f].abbrev, qcc_token))
927 if (compiler_flag[f].flags & FLAG_MIDCOMPILE)
928 *compiler_flag[f].enabled = st;
930 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Cannot enable/disable keyword/flag via a pragma");
934 if (!compiler_flag[f].enabled)
935 QCC_PR_ParseWarning(WARN_BADPRAGMA, "keyword/flag not recognised");
939 else if (!QC_strcasecmp(qcc_token, "warning"))
943 s = QCC_COM_Parse(msg);
944 if (!stricmp(qcc_token, "enable") || !stricmp(qcc_token, "on"))
946 else if (!stricmp(qcc_token, "disable") || !stricmp(qcc_token, "off"))
948 else if (!stricmp(qcc_token, "toggle"))
952 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning state not recognised");
958 s = QCC_COM_Parse(s);
959 wn = QCC_WarningForName(qcc_token);
961 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
964 if (st == 2) //toggle
965 qccwarningdisabled[wn] = true - qccwarningdisabled[wn];
967 qccwarningdisabled[wn] = st;
972 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Unknown pragma \'%s\'", qcc_token);
984 Call at start of file and when *pr_file_p == '\n'
987 void QCC_PR_NewLine (pbool incomment)
990 pr_line_start = pr_file_p;
991 while(*pr_file_p==' ' || *pr_file_p == '\t')
993 if (incomment) //no constants if in a comment.
996 else if (QCC_PR_Precompiler())
1001 // PR_PrintNextLine ();
1008 Parses a quoted string
1012 void QCC_PR_LexString (void)
1022 bool fromfile = true;
1029 QCC_COM_Parse(text);
1030 // print("Next token is \"%s\"\n", com_token);
1034 if (fromfile) pr_file_p++;
1039 if (fromfile) pr_file_p++;
1041 QCC_PR_ParseError ("EOF inside quote");
1043 QCC_PR_ParseError ("newline inside quote");
1047 if (fromfile) pr_file_p++;
1049 QCC_PR_ParseError ("EOF inside quote");
1057 QCC_PR_ParseError ("Unknown escape char");
1061 if (fromfile) pr_file_p++;
1068 // if (fromfile) pr_file_p++;
1070 pr_immediate_type=NULL;
1071 oldline=pr_source_line;
1074 if (pr_immediate_type == &type_string)
1076 // print("Appending \"%s\" to \"%s\"\n", pr_immediate_string, tmpbuf);
1077 strcat(tmpbuf, pr_immediate_string);
1078 len+=strlen(pr_immediate_string);
1082 pr_source_line = oldline;
1084 QCC_PR_LexWhitespace();
1085 if (*pr_file_p != '\"') //annother string
1089 QCC_PR_LexWhitespace();
1094 strcpy(pr_token, tmpbuf);
1095 pr_token_type = tt_immediate;
1096 pr_immediate_type = &type_string;
1097 strcpy (pr_immediate_string, pr_token);
1099 // print("Found \"%s\"\n", pr_immediate_string);
1102 void QCC_PR_LexString (void)
1116 QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1118 QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "newline inside quote");
1123 QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1138 else if (c == 's' || c == 'b')
1151 while ((d = *pr_file_p++) != '}')
1153 c = c * 10 + d - '0';
1154 if (d < '0' || d > '9' || c > 255)
1155 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1164 else if (c == 'x' || c == 'X')
1169 d = (unsigned char)*pr_file_p++;
1170 if (d >= '0' && d <= '9')
1172 else if (d >= 'A' && d <= 'F')
1174 else if (d >= 'a' && d <= 'f')
1177 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1181 d = (unsigned char)*pr_file_p++;
1182 if (d >= '0' && d <= '9')
1184 else if (d >= 'A' && d <= 'F')
1186 else if (d >= 'a' && d <= 'f')
1189 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1195 else if (c >= '0' && c <= '9')
1201 QCC_PR_ParseWarning(WARN_HANGINGSLASHR, "Hanging \\\\\r");
1209 QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "Unknown escape char %c", c);
1213 if (len >= sizeof(pr_immediate_string)-1)
1214 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
1216 while(*pr_file_p && *pr_file_p <= ' ')
1218 if (*pr_file_p == '\n')
1221 QCC_PR_NewLine(false);
1226 if (*pr_file_p == '\"') //have annother go
1232 pr_token_type = tt_immediate;
1233 pr_immediate_type = type_string;
1234 strcpy (pr_immediate_string, pr_token);
1239 for (end = pr_file_p; ; end++)
1271 cnst = QCC_PR_CheakCompConstString(pr_file_p);
1272 if (cnst==pr_file_p)
1278 QCC_PR_ParseWarning(WARN_MACROINSTRING, "Macro expansion in string");
1280 if (len+strlen(cnst) >= sizeof(pr_token)-1)
1281 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1283 strcpy(pr_token+len, cnst);
1289 else if (c == 0x7C && flag_acc) //reacc support... reacc is strange.
1296 if (len >= sizeof(pr_token)-1)
1297 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1307 int QCC_PR_LexInteger (void)
1314 if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1319 c = *(pr_file_p+=2);
1327 } while ((c >= '0' && c<= '9') || c == '.' || (c>='a' && c <= 'f'));
1329 return atoi (pr_token);
1332 void QCC_PR_LexNumber (void)
1339 if (*pr_file_p == '-')
1344 pr_token[tokenlen++] = '-';
1346 if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1351 pr_token[tokenlen++] = '0';
1352 pr_token[tokenlen++] = 'x';
1355 pr_immediate_type = NULL;
1356 //assume base 10 if not stated
1360 while((c = *pr_file_p))
1362 if (c >= '0' && c <= '9')
1364 pr_token[tokenlen++] = c;
1368 else if (c >= 'a' && c <= 'f' && base > 10)
1370 pr_token[tokenlen++] = c;
1374 else if (c >= 'A' && c <= 'F' && base > 10)
1376 pr_token[tokenlen++] = c;
1382 pr_token[tokenlen++] = c;
1384 pr_immediate_type = type_float;
1388 if (c >= '0' && c <= '9')
1390 pr_token[tokenlen++] = c;
1403 pr_token[tokenlen++] = 0;
1404 pr_immediate._float = (float)atof(pr_token);
1409 pr_token[tokenlen++] = c;
1410 pr_token[tokenlen++] = 0;
1412 pr_immediate_type = type_integer;
1413 pr_immediate._int = num*sign;
1420 pr_token[tokenlen++] = 0;
1422 if (!pr_immediate_type)
1424 if (flag_assume_integer)
1425 pr_immediate_type = type_integer;
1427 pr_immediate_type = type_float;
1430 if (pr_immediate_type == type_integer)
1432 pr_immediate_type = type_integer;
1433 pr_immediate._int = num*sign;
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);
1446 float QCC_PR_LexFloat (void)
1459 } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.')); //only allow a . if the next isn't too...
1461 return (float)atof (pr_token);
1468 Parses a single quoted vector
1471 void QCC_PR_LexVector (void)
1477 if (*pr_file_p == '\\')
1478 {//extended character constant
1479 pr_token_type = tt_immediate;
1480 pr_immediate_type = type_float;
1485 pr_immediate._float = '\n';
1488 pr_immediate._float = '\r';
1491 pr_immediate._float = '\t';
1494 pr_immediate._float = '\'';
1497 pr_immediate._float = '\"';
1500 pr_immediate._float = '\\';
1503 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
1505 if (*pr_file_p != '\'')
1506 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
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];
1518 pr_token_type = tt_immediate;
1519 pr_immediate_type = type_vector;
1520 QCC_PR_LexWhitespace ();
1521 for (i=0 ; i<3 ; i++)
1523 pr_immediate.vector[i] = QCC_PR_LexFloat ();
1524 QCC_PR_LexWhitespace ();
1526 if (*pr_file_p == '\'' && i == 1)
1529 QCC_PR_ParseWarning (WARN_FTE_SPECIFIC, "Bad vector");
1531 for (i++ ; i<3 ; i++)
1532 pr_immediate.vector[i] = 0;
1536 if (*pr_file_p != '\'')
1537 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad vector");
1545 Parses an identifier
1548 void QCC_PR_LexName (void)
1561 } while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
1562 || (c >= '0' && c <= '9'));
1565 pr_token_type = tt_name;
1573 void QCC_PR_LexPunctuation (void)
1579 pr_token_type = tt_punct;
1581 for (i=0 ; (p = pr_punctuation[i]) != NULL ; i++)
1584 if (!strncmp(p, pr_file_p, len) )
1586 strcpy (pr_token, pr_punctuationremap[i]);
1589 else if (p[0] == '}')
1596 QCC_PR_ParseError (ERR_UNKNOWNPUCTUATION, "Unknown punctuation");
1605 void QCC_PR_LexWhitespace (void)
1612 while ( (c = *pr_file_p) <= ' ')
1617 QCC_PR_NewLine (false);
1624 return; // end of file
1630 if (c=='/' && pr_file_p[1] == '/')
1632 while (*pr_file_p && *pr_file_p != '\n')
1635 if (*pr_file_p == '\n')
1636 pr_file_p++; //don't break on eof.
1637 QCC_PR_NewLine(false);
1641 // skip /* */ comments
1642 if (c=='/' && pr_file_p[1] == '*')
1647 if (pr_file_p[0]=='\n')
1649 QCC_PR_NewLine(true);
1651 if (pr_file_p[1] == 0)
1657 } while (pr_file_p[0] != '*' || pr_file_p[1] != '/');
1662 break; // a real character has been found
1666 //============================================================================
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;
1676 void QCC_PR_ClearGrabMacros (void)
1678 pr_oldmacros = pr_nummacros;
1679 // pr_nummacros = 0;
1684 int QCC_PR_FindMacro (char *name)
1688 for (i=pr_nummacros-1 ; i>=0 ; i--)
1690 if (!STRCMP (name, pr_framemacros[i]))
1692 return pr_framemacrovalue[i];
1695 for (i=pr_nummacros-1 ; i>=0 ; i--)
1697 if (!stricmp (name, pr_framemacros[i]))
1699 QCC_PR_ParseWarning(WARN_CASEINSENSATIVEFRAMEMACRO, "Case insensative frame macro");
1700 return pr_framemacrovalue[i];
1706 void QCC_PR_ExpandMacro(void)
1708 int i = QCC_PR_FindMacro(pr_token);
1711 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "Unknown frame macro $%s", pr_token);
1713 sprintf (pr_token,"%d", i);
1714 pr_token_type = tt_immediate;
1715 pr_immediate_type = type_float;
1716 pr_immediate._float = (float)i;
1719 // just parses text, returning false if an eol is reached
1720 pbool QCC_PR_SimpleGetToken (void)
1728 while ( (c = *pr_file_p) <= ' ')
1730 if (c=='\n' || c == 0)
1734 if (pr_file_p[0] == '/')
1736 if (pr_file_p[1] == '/')
1738 while(*pr_file_p && *pr_file_p != '\n')
1742 if (pr_file_p[1] == '*')
1747 while ( (c = *pr_file_p) > ' ' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']')
1757 pbool QCC_PR_LexMacroName(void)
1765 while ( (c = *pr_file_p) <= ' ')
1767 if (c=='\n' || c == 0)
1771 if (pr_file_p[0] == '/')
1773 if (pr_file_p[1] == '/')
1775 while(*pr_file_p && *pr_file_p != '\n')
1779 if (pr_file_p[1] == '*')
1784 while ( (c = *pr_file_p) > ' ' && c != '\n' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']' && !(pr_file_p[0] == '.' && pr_file_p[1] == '.'))
1794 void QCC_PR_MacroFrame(char *name, int value)
1797 for (i=pr_nummacros-1 ; i>=0 ; i--)
1799 if (!STRCMP (name, pr_framemacros[i]))
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.
1809 if (strlen(name)+1 > sizeof(pr_framemacros[0]))
1810 QCC_PR_ParseWarning(ERR_TOOMANYFRAMEMACROS, "Name for frame macro %s is too long", name);
1813 strcpy (pr_framemacros[pr_nummacros], name);
1814 pr_framemacrovalue[pr_nummacros] = value;
1816 if (pr_nummacros >= MAX_FRAMES)
1817 QCC_PR_ParseError(ERR_TOOMANYFRAMEMACROS, "Too many frame macros defined");
1821 void QCC_PR_ParseFrame (void)
1823 while (QCC_PR_LexMacroName ())
1825 QCC_PR_MacroFrame(pr_token, pr_macrovalue++);
1833 Deals with counting sequence numbers and replacing frame macros
1836 void QCC_PR_LexGrab (void)
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();
1845 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
1848 if (!STRCMP (pr_token, "frame") || !STRCMP (pr_token, "framesave"))
1850 QCC_PR_ParseFrame ();
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 ())
1865 else if (!STRCMP (pr_token, "flush"))
1867 QCC_PR_ClearGrabMacros();
1868 while (QCC_PR_LexMacroName ())
1872 else if (!STRCMP (pr_token, "framevalue"))
1874 QCC_PR_LexMacroName ();
1875 pr_macrovalue = atoi(pr_token);
1879 else if (!STRCMP (pr_token, "framerestore"))
1881 QCC_PR_LexMacroName ();
1882 QCC_PR_ExpandMacro();
1883 pr_macrovalue = (int)pr_immediate._float;
1887 else if (!STRCMP (pr_token, "modelname"))
1890 QCC_PR_LexMacroName ();
1892 if (*pr_framemodelname)
1893 QCC_PR_MacroFrame(pr_framemodelname, pr_macrovalue);
1895 strncpy(pr_framemodelname, pr_token, sizeof(pr_framemodelname)-1);
1896 pr_framemodelname[sizeof(pr_framemodelname)-1] = '\0';
1898 i = QCC_PR_FindMacro(pr_framemodelname);
1906 // look for a frame name macro
1908 QCC_PR_ExpandMacro ();
1911 //===========================
1912 //compiler constants - dmw
1914 pbool QCC_PR_UndefineName(char *name)
1917 CompilerConstant_t *c;
1918 c = pHash_Get(&compconstantstable, name);
1921 QCC_PR_ParseWarning(WARN_UNDEFNOTDEFINED, "Precompiler constant %s was not defined", name);
1925 Hash_Remove(&compconstantstable, name);
1928 a = c-CompilerConstant;
1929 // for (a = 0; a < numCompilerConstants; a++)
1931 // if (!STRCMP(name, CompilerConstant[a].name))
1933 memmove(&CompilerConstant[a], &CompilerConstant[a+1], sizeof(CompilerConstant_t) * (numCompilerConstants-a));
1934 numCompilerConstants--;
1939 if (!STRCMP(name, "OP_NODUP"))
1940 qccop_noduplicatestrings = false;
1942 if (!STRCMP(name, "OP_COMP_ALL")) //group
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");
1961 CompilerConstant_t *QCC_PR_DefineName(char *name)
1964 CompilerConstant_t *cnst;
1966 // if (numCompilerConstants >= MAX_CONSTANTS)
1967 // QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS);
1969 if (strlen(name) >= MAXCONSTANTLENGTH || !*name)
1970 QCC_PR_ParseError(ERR_CONSTANTTOOLONG, "Compiler constant name length is too long or short");
1972 cnst = pHash_Get(&compconstantstable, name);
1975 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "Duplicate definition for Precompiler constant %s", name);
1976 Hash_Remove(&compconstantstable, name);
1979 cnst = qccHunkAlloc(sizeof(CompilerConstant_t));
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';
1989 pHash_Add(&compconstantstable, cnst->name, cnst, qccHunkAlloc(sizeof(bucket_t)));
1991 if (!STRCMP(name, "OP_NODUP"))
1992 opt_noduplicatestrings = true;
1995 if (!STRCMP(name, "OP_TIME")) //group - optimize for a fast compiler
1997 QCC_PR_UndefineName("OP_SIZE");
1998 QCC_PR_UndefineName("OP_SPEED");
2000 QCC_PR_UndefineName("OP_NODUP");
2001 QCC_PR_UndefineName("OP_COMP_ALL");
2004 if (!STRCMP(name, "OP_SPEED")) //group - optimize run speed
2006 QCC_PR_UndefineName("OP_SIZE");
2007 QCC_PR_UndefineName("OP_TIME");
2009 // QCC_PR_UndefineName("OP_NODUP");
2010 QCC_PR_UndefineName("OP_COMP_ALL");
2013 if (!STRCMP(name, "OP_SIZE")) //group - produce small output.
2015 QCC_PR_UndefineName("OP_SPEED");
2016 QCC_PR_UndefineName("OP_TIME");
2018 QCC_PR_DefineName("OP_NODUP");
2019 QCC_PR_DefineName("OP_COMP_ALL");
2022 if (!STRCMP(name, "OP_COMP_ALL")) //group - compress the output
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");
2039 void QCC_PR_Undefine(void)
2041 QCC_PR_SimpleGetToken ();
2043 QCC_PR_UndefineName(pr_token);
2044 // QCC_PR_ParseError("%s was not defined.", pr_token);
2047 void QCC_PR_ConditionCompilation(void)
2053 CompilerConstant_t *cnst;
2055 QCC_PR_SimpleGetToken ();
2057 if (!QCC_PR_SimpleGetToken ())
2058 QCC_PR_ParseError(ERR_NONAME, "No name defined for compiler constant");
2060 cnst = pHash_Get(&compconstantstable, pr_token);
2063 oldval = cnst->value;
2064 Hash_Remove(&compconstantstable, pr_token);
2069 cnst = QCC_PR_DefineName(pr_token);
2071 if (*pr_file_p == '(')
2076 if (*pr_file_p == ',')
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';
2086 if (*pr_file_p == ')')
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';
2098 else cnst->numparams = -1;
2102 while(*s == ' ' || *s == '\t')
2108 // read over a newline if necessary
2109 if( s[1] == '\n' || s[1] == '\r' )
2112 QCC_PR_NewLine(false);
2114 if( s[-1] == '\r' && s[0] == '\n' )
2120 else if(*s == '\r' || *s == '\n' || *s == '\0')
2125 if (!quote && s[0]=='/'&&(s[1]=='/'||s[1]=='*'))
2136 while(*d<= ' ' && d >= cnst->value)
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));
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);
2147 QCC_PR_ParseWarning(WARN_IDENTICALPRECOMPILER, "Identical precompiler definition of %s", pr_token);
2153 int QCC_PR_CheakCompConst(void)
2155 char *oldpr_file_p = pr_file_p;
2158 CompilerConstant_t *c;
2161 for (end = pr_file_p; ; end++)
2189 strncpy(pr_token, pr_file_p, end-pr_file_p);
2190 pr_token[end-pr_file_p]='\0';
2192 // printf("%s\n", pr_token);
2193 c = pHash_Get(&compconstantstable, pr_token);
2195 if (c && !c->inside)
2197 pr_file_p = oldpr_file_p+strlen(c->name);
2198 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2200 if (c->numparams>=0)
2202 if (*pr_file_p == '(')
2207 char *paramoffset[MAXCONSTANTPARAMS+1];
2212 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2217 // handle strings correctly by ignoring them
2218 if (*pr_file_p == '\"')
2222 } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
2224 if (*pr_file_p == '(')
2226 else if (!plevel && (*pr_file_p == ',' || *pr_file_p == ')'))
2228 paramoffset[param++] = start;
2229 start = pr_file_p+1;
2230 if (*pr_file_p == ')')
2238 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2243 // move back by one char because we move forward by one at the end of the loop
2245 if (param == MAXCONSTANTPARAMS)
2246 QCC_PR_ParseError(ERR_TOOMANYPARAMS, "Too many parameters in macro call");
2247 } else if (*pr_file_p == ')' )
2249 else if(*pr_file_p == '\n')
2250 QCC_PR_NewLine(false);
2252 // see that *pr_file_p = '\0' up there? Must ++ BEFORE checking for !*pr_file_p
2255 QCC_PR_ParseError(ERR_EOF, "EOF on macro call");
2257 if (param < c->numparams)
2258 QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Not enough macro parameters");
2259 paramoffset[param] = start;
2263 oldpr_file_p = pr_file_p;
2264 pr_file_p = c->value;
2267 whitestart = p = strlen(buffer);
2268 while(*pr_file_p <= ' ') //copy across whitespace
2272 buffer[p++] = *pr_file_p++;
2276 if(*pr_file_p == '\"')
2280 buffer[p++] = *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
2285 ++pr_file_p; // and skip it
2288 else if (*pr_file_p == '#') //if you ask for #a##b you will be shot. use #a #b instead, or chain macros.
2290 if (pr_file_p[1] == '#')
2291 { //concatinate (srip out whitespace)
2292 buffer[whitestart] = '\0';
2298 pr_file_p = QCC_COM_Parse2(pr_file_p);
2302 for (p = 0; p < param; p++)
2304 if (!STRCMP(qcc_token, c->params[p]))
2306 strcat(buffer, "\"");
2307 strcat(buffer, paramoffset[p]);
2308 strcat(buffer, "\"");
2314 strcat(buffer, "#");
2315 strcat(buffer, qcc_token);
2316 //QCC_PR_ParseWarning(0, "Stringification ignored");
2318 continue; //already did this one
2322 pr_file_p = QCC_COM_Parse2(pr_file_p);
2326 for (p = 0; p < param; p++)
2328 if (!STRCMP(qcc_token, c->params[p]))
2330 strcat(buffer, paramoffset[p]);
2335 strcat(buffer, qcc_token);
2338 for (p = 0; p < param-1; p++)
2339 paramoffset[p][strlen(paramoffset[p])] = ',';
2340 paramoffset[p][strlen(paramoffset[p])] = ')';
2342 pr_file_p = oldpr_file_p;
2344 expandedemptymacro = true;
2345 QCC_PR_IncludeChunkEx(buffer, true, NULL, c);
2348 QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without opening brace");
2353 expandedemptymacro = true;
2354 QCC_PR_IncludeChunkEx(c->value, false, NULL, c);
2361 if (!strncmp(pr_file_p, "__TIME__", 8))
2363 static char retbuf[128];
2367 strftime( retbuf, sizeof(retbuf),
2368 "\"%H:%M\"", localtime( &long_time ));
2371 QCC_PR_Lex(); //translate the macro's value
2372 pr_file_p = oldpr_file_p+8;
2376 if (!strncmp(pr_file_p, "__DATE__", 8))
2378 static char retbuf[128];
2382 strftime( retbuf, sizeof(retbuf),
2383 "\"%a %d %b %Y\"", localtime( &long_time ));
2386 QCC_PR_Lex(); //translate the macro's value
2387 pr_file_p = oldpr_file_p+8;
2391 if (!strncmp(pr_file_p, "__FILE__", 8))
2393 static char retbuf[256];
2394 sprintf(retbuf, "\"%s\"", strings + s_file);
2396 QCC_PR_Lex(); //translate the macro's value
2397 pr_file_p = oldpr_file_p+8;
2401 if (!strncmp(pr_file_p, "__LINE__", 8))
2403 static char retbuf[256];
2404 sprintf(retbuf, "\"%i\"", pr_source_line);
2406 QCC_PR_Lex(); //translate the macro's value
2407 pr_file_p = oldpr_file_p+8;
2410 if (!strncmp(pr_file_p, "__FUNC__", 8))
2412 static char retbuf[256];
2413 sprintf(retbuf, "\"%s\"",pr_scope->name);
2415 QCC_PR_Lex(); //translate the macro's value
2416 pr_file_p = oldpr_file_p+8;
2419 if (!strncmp(pr_file_p, "__NULL__", 8))
2421 static char retbuf[256];
2422 sprintf(retbuf, "0i");
2424 QCC_PR_Lex(); //translate the macro's value
2425 pr_file_p = oldpr_file_p+8;
2431 char *QCC_PR_CheakCompConstString(char *def)
2435 CompilerConstant_t *c;
2437 c = pHash_Get(&compconstantstable, def);
2441 s = QCC_PR_CheakCompConstString(c->value);
2447 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def)
2449 CompilerConstant_t *c = pHash_Get(&compconstantstable, def);
2452 for (a = 0; a < numCompilerConstants; a++)
2454 if (!strncmp(def, CompilerConstant[a].name, CompilerConstant[a].namelen+1))
2455 return &CompilerConstant[a];
2461 //============================================================================
2467 Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
2470 void QCC_PR_Lex (void)
2478 if (QCC_PR_UnInclude())
2483 pr_token_type = tt_eof;
2487 QCC_PR_LexWhitespace ();
2491 if (QCC_PR_UnInclude())
2496 pr_token_type = tt_eof;
2504 if (QCC_PR_UnInclude())
2509 pr_token_type = tt_eof;
2513 // handle quoted strings as a unit
2516 QCC_PR_LexString ();
2520 // handle quoted vectors as a unit
2523 QCC_PR_LexVector ();
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...
2531 QCC_PR_ParseWarning(0, "~ or %% prefixes to denote integers are deprecated. Please use a postfix of 'i'");
2533 pr_token_type = tt_immediate;
2534 pr_immediate_type = type_integer;
2535 pr_immediate._int = QCC_PR_LexInteger ();
2538 if ( c == '0' && pr_file_p[1] == 'x')
2540 pr_token_type = tt_immediate;
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') )
2546 pr_token_type = tt_immediate;
2547 QCC_PR_LexNumber ();
2551 if (c == '#' && !(pr_file_p[1]=='-' || (pr_file_p[1]>='0' && pr_file_p[1] <='9'))) //hash and not number
2554 if (!QCC_PR_CheakCompConst())
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);
2561 if (pr_token_type == tt_eof)
2567 if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
2569 if (flag_hashonly || !QCC_PR_CheakCompConst()) //look for a macro.
2572 if (pr_token_type == tt_eof)
2574 if (QCC_PR_UnInclude())
2579 pr_token_type = tt_eof;
2590 // parse symbol strings until a non-symbol is found
2591 QCC_PR_LexPunctuation ();
2594 //=============================================================================
2597 void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
2599 if (qccwarningdisabled[type])
2604 printf ("%s(%i) : %s is defined here\n", strings + def->s_file, def->s_line, def->name);
2606 printf ("%s:%i: %s is defined here\n", strings + def->s_file, def->s_line, def->name);
2610 void QCC_PR_PrintScope (void)
2614 if (errorscope != pr_scope)
2615 printf ("in function %s (line %i),\n", pr_scope->name, pr_scope->s_line);
2616 errorscope = pr_scope;
2621 printf ("at global scope,\n");
2625 void QCC_PR_ResetErrorScope(void)
2633 Aborts the current file load
2637 void editbadfile(char *file, int line);
2639 void VARGS QCC_PR_ParseError (int errortype, char *error, ...)
2644 va_start (argptr,error);
2645 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2649 editbadfile(strings+s_file, pr_source_line);
2652 QCC_PR_PrintScope();
2654 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2656 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2658 longjmp (pr_parse_abort, 1);
2660 void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...)
2665 va_start (argptr,error);
2666 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2670 editbadfile(strings+s_file, pr_source_line);
2672 QCC_PR_PrintScope();
2674 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2676 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2678 QCC_PR_ParsePrintDef(WARN_ERROR, def);
2680 longjmp (pr_parse_abort, 1);
2682 void VARGS QCC_PR_ParseWarning (int type, char *error, ...)
2687 if (type < ERR_PARSEERRORS && qccwarningdisabled[type])
2690 va_start (argptr,error);
2691 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2694 QCC_PR_PrintScope();
2695 if (type >= ERR_PARSEERRORS)
2698 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2700 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2706 printf ("%s(%i) : warning: %s\n", strings + s_file, pr_source_line, string);
2708 printf ("%s:%i: warning: %s\n", strings + s_file, pr_source_line, string);
2713 void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
2718 if (qccwarningdisabled[type])
2721 va_start (argptr,error);
2722 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2725 QCC_PR_PrintScope();
2729 printf ("%s(%i) : warning: %s\n", file, line, string);
2731 printf ("%s:%i: warning: %s\n", file, line, string);
2734 printf ("warning: %s\n", string);
2743 Issues an error if the current token isn't equal to string
2747 #ifndef COMMONINLINES
2748 void QCC_PR_Expect (char *string)
2750 if (STRCMP (string, pr_token))
2751 QCC_PR_ParseError (ERR_EXPECTED, "expected %s, found %s",string, pr_token);
2761 Returns true and gets the next token if the current token equals string
2762 Returns false and does nothing otherwise
2765 #ifndef COMMONINLINES
2766 pbool QCC_PR_CheckToken (char *string)
2768 if (pr_token_type != tt_punct)
2771 if (STRCMP (string, pr_token))
2778 pbool QCC_PR_CheckImmediate (char *string)
2780 if (pr_token_type != tt_immediate)
2783 if (STRCMP (string, pr_token))
2790 pbool QCC_PR_CheckName(char *string)
2792 if (pr_token_type != tt_name)
2794 if (flag_caseinsensative)
2796 if (stricmp (string, pr_token))
2801 if (STRCMP(string, pr_token))
2808 pbool QCC_PR_CheckKeyword(int keywordenabled, char *string)
2810 if (!keywordenabled)
2812 if (flag_caseinsensative)
2814 if (stricmp (string, pr_token))
2819 if (STRCMP(string, pr_token))
2832 Checks to see if the current token is a valid name
2835 char *QCC_PR_ParseName (void)
2837 static char ident[MAX_NAME];
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);
2847 ret = qccHunkAlloc(strlen(ident)+1);
2857 Returns a preexisting complex type that matches the parm, or allocates
2858 a new one and copies it out.
2863 QCC_type_t *QCC_PR_NewType (char *name, int basictype);
2864 int typecmp(QCC_type_t *a, QCC_type_t *b)
2869 return 1; //different (^ and not both null)
2871 if (a->type != b->type)
2873 if (a->num_parms != b->num_parms)
2876 if (a->size != b->size)
2878 // if (STRCMP(a->name, b->name)) //This isn't 100% clean.
2881 if (typecmp(a->aux_type, b->aux_type))
2884 if (a->param || b->param)
2902 QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in)
2904 QCC_type_t *out, *op, *ip;
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);
2916 out->param = op = QCC_PR_DuplicateType(ip);
2918 op = (op->next = QCC_PR_DuplicateType(ip));
2921 out->size = in->size;
2922 out->num_parms = in->num_parms;
2924 out->name = in->name;
2925 out->parentclass = in->parentclass;
2930 char *TypeName(QCC_type_t *type)
2932 static char buffer[2][512];
2939 if (type->type == ev_field)
2941 type = type->aux_type;
2946 if (type->type == ev_function)
2948 strcat(ret, type->aux_type->name);
2953 strcat(ret, type->name);
2961 else if (type->type == ev_entity && type->parentclass)
2965 strcat(ret, "class ");
2966 strcat(ret, type->name);
2967 /* strcat(ret, " {");
2971 strcat(ret, type->name);
2981 strcpy(ret, type->name);
2983 return buffer[op&1];
2985 //#define typecmp(a, b) (a && ((a)->type==(b)->type) && !STRCMP((a)->name, (b)->name))
2987 QCC_type_t *QCC_PR_FindType (QCC_type_t *type)
2990 for (t = 0; t < numtypeinfos; t++)
2992 // check = &qcc_typeinfo[t];
2993 if (typecmp(&qcc_typeinfo[t], type))
2997 // c2 = check->next;
2999 // for (i=0 ; n2&&c2 ; i++)
3001 // if (!typecmp((c2), (n2)))
3007 // if (n2==NULL&&c2==NULL)
3009 return &qcc_typeinfo[t];
3012 QCC_Error(ERR_INTERNAL, "Error with type");
3017 QCC_type_t *QCC_PR_NextSubType(QCC_type_t *type, QCC_type_t *prev)
3023 for (p = prev->num_parms; p; p--)
3024 prev = QCC_PR_NextSubType(prev, NULL);
3025 if (prev->num_parms)
3037 QCC_type_t *QCC_TypeForName(char *name)
3041 for (i = 0; i < numtypeinfos; i++)
3043 if (!STRCMP(qcc_typeinfo[i].name, name))
3045 return &qcc_typeinfo[i];
3056 For error recovery, also pops out of nested braces
3059 void QCC_PR_SkipToSemicolon (void)
3063 if (!pr_bracelevel && QCC_PR_CheckToken (";"))
3066 } while (pr_token_type != tt_eof);
3074 Parses a variable type, including field and functions types
3077 #ifdef MAX_EXTRA_PARMS
3078 char pr_parm_names[MAX_PARMS+MAX_EXTRA_PARMS][MAX_NAME];
3080 char pr_parm_names[MAX_PARMS][MAX_NAME];
3083 pbool recursivefunctiontype;
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)
3089 QCC_type_t *ftype, *ptype, *nptype;
3091 int definenames = !recursivefunctiontype;
3093 recursivefunctiontype++;
3095 ftype = QCC_PR_NewType(type_function->name, ev_function);
3097 ftype->aux_type = returntype; // return type
3098 ftype->num_parms = 0;
3102 if (!QCC_PR_CheckToken (")"))
3104 if (QCC_PR_CheckToken ("..."))
3105 ftype->num_parms = -1; // variable args
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);
3112 if (QCC_PR_CheckToken ("..."))
3114 ftype->num_parms = (ftype->num_parms * -1) - 1;
3118 nptype = QCC_PR_ParseType(true);
3120 if (nptype->type == ev_void)
3125 ftype->param = ptype;
3129 ptype->next = nptype;
3130 ptype = ptype->next;
3132 // type->name = "FUNC PARAMETER";
3135 if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")"))
3137 name = QCC_PR_ParseName ();
3139 strcpy (pr_parm_names[ftype->num_parms], name);
3141 else if (definenames)
3142 strcpy (pr_parm_names[ftype->num_parms], "");
3144 } while (QCC_PR_CheckToken (","));
3146 QCC_PR_Expect (")");
3148 recursivefunctiontype--;
3151 return QCC_PR_FindType (ftype);
3153 QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
3155 QCC_type_t *ftype, *ptype, *nptype;
3158 int definenames = !recursivefunctiontype;
3160 recursivefunctiontype++;
3162 ftype = QCC_PR_NewType(type_function->name, ev_function);
3164 ftype->aux_type = returntype; // return type
3165 ftype->num_parms = 0;
3169 if (!QCC_PR_CheckToken (")"))
3171 if (QCC_PR_CheckToken ("..."))
3172 ftype->num_parms = -1; // variable args
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);
3179 if (QCC_PR_CheckToken ("..."))
3181 ftype->num_parms = (ftype->num_parms * -1) - 1;
3185 if (QCC_PR_CheckName("arg"))
3187 sprintf(argname, "arg%i", ftype->num_parms);
3189 nptype = QCC_PR_NewType("Variant", ev_variant);
3191 else if (QCC_PR_CheckName("vect")) //this can only be of vector sizes, so...
3193 sprintf(argname, "arg%i", ftype->num_parms);
3195 nptype = QCC_PR_NewType("Vector", ev_vector);
3199 name = QCC_PR_ParseName();
3201 nptype = QCC_PR_ParseType(true);
3204 if (nptype->type == ev_void)
3209 ftype->param = ptype;
3213 ptype->next = nptype;
3214 ptype = ptype->next;
3216 // type->name = "FUNC PARAMETER";
3219 strcpy (pr_parm_names[ftype->num_parms], name);
3221 } while (QCC_PR_CheckToken (";"));
3223 QCC_PR_Expect (")");
3225 recursivefunctiontype--;
3228 return QCC_PR_FindType (ftype);
3230 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
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);
3239 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
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);
3250 pbool type_inlinefunction;
3251 QCC_type_t *QCC_PR_ParseType (int newtype)
3253 QCC_type_t *newparm;
3259 type_inlinefunction = false; //doesn't really matter so long as its not from an inline function type
3263 if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges)
3265 newt = QCC_PR_NewType("FIELD TYPE", ev_field);
3266 newt->aux_type = QCC_PR_ParseType (false);
3268 newt->size = newt->aux_type->size;
3270 newt = QCC_PR_FindType (newt);
3272 type = QCC_PR_NewType("FIELD TYPE", ev_field);
3273 type->aux_type = newt;
3275 type->size = type->aux_type->size;
3279 return QCC_PR_FindType (type);
3281 if (QCC_PR_CheckToken ("."))
3283 newt = QCC_PR_NewType("FIELD TYPE", ev_field);
3284 newt->aux_type = QCC_PR_ParseType (false);
3286 newt->size = newt->aux_type->size;
3290 return QCC_PR_FindType (newt);
3293 name = QCC_PR_CheakCompConstString(pr_token);
3295 if (QCC_PR_CheckKeyword (keyword_class, "class"))
3298 QCC_type_t *fieldtype;
3299 char membername[2048];
3300 char *classname = QCC_PR_ParseName();
3301 int forwarddeclaration;
3305 /* Don't advance the line number yet */
3306 forwarddeclaration = pr_token[0] == ';';
3308 /* Look to see if this type is already defined */
3309 for(i=0;i<numtypeinfos;i++)
3311 if (STRCMP(qcc_typeinfo[i].name, classname) == 0)
3313 newt = &qcc_typeinfo[i];
3318 if (newt && forwarddeclaration)
3319 QCC_PR_ParseError(ERR_REDECLARATION, "Forward declaration of already defined class %s", classname);
3321 if (newt && newt->num_parms != 0)
3322 QCC_PR_ParseError(ERR_REDECLARATION, "Redeclaration of class %s", classname);
3325 newt = QCC_PR_NewType(classname, ev_entity);
3327 newt->size=type_entity->size;
3331 if (forwarddeclaration)
3333 QCC_PR_CheckToken(";");
3339 if (QCC_PR_CheckToken(":"))
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);
3347 newt->parentclass = type_entity;
3351 if (QCC_PR_CheckToken(","))
3352 QCC_PR_ParseError(ERR_NOTANAME, "member missing name");
3353 while (!QCC_PR_CheckToken("}"))
3355 // if (QCC_PR_CheckToken(","))
3356 // type->next = QCC_PR_NewType(type->name, type->type);
3358 newparm = QCC_PR_ParseType(true);
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);
3363 if (!QCC_PR_CheckToken(";"))
3365 newparm->name = QCC_CopyString(pr_token)+strings;
3367 if (QCC_PR_CheckToken("["))
3369 type->next->size*=atoi(pr_token);
3373 QCC_PR_CheckToken(";");
3376 newparm->name = QCC_CopyString("")+strings;
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);
3385 newparm->ofs = 0;//newt->size;
3389 type->next = newparm;
3391 newt->param = newparm;
3400 if (QCC_PR_CheckKeyword (keyword_struct, "struct"))
3402 newt = QCC_PR_NewType("struct", ev_struct);
3407 if (QCC_PR_CheckToken(","))
3408 QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3411 while (!QCC_PR_CheckToken("}"))
3413 if (QCC_PR_CheckToken(","))
3416 QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3417 newparm = QCC_PR_NewType(newparm->name, newparm->type);
3420 newparm = QCC_PR_ParseType(true);
3422 if (!QCC_PR_CheckToken(";"))
3424 newparm->name = QCC_CopyString(pr_token)+strings;
3426 if (QCC_PR_CheckToken("["))
3428 newparm->size*=atoi(pr_token);
3432 QCC_PR_CheckToken(";");
3435 newparm->name = QCC_CopyString("")+strings;
3436 newparm->ofs = newt->size;
3437 newt->size += newparm->size;
3441 type->next = newparm;
3443 newt->param = newparm;
3448 if (QCC_PR_CheckKeyword (keyword_union, "union"))
3450 newt = QCC_PR_NewType("union", ev_union);
3455 if (QCC_PR_CheckToken(","))
3456 QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3458 while (!QCC_PR_CheckToken("}"))
3460 if (QCC_PR_CheckToken(","))
3463 QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3464 newparm = QCC_PR_NewType(newparm->name, newparm->type);
3467 newparm = QCC_PR_ParseType(true);
3468 if (QCC_PR_CheckToken(";"))
3469 newparm->name = QCC_CopyString("")+strings;
3472 newparm->name = QCC_CopyString(pr_token)+strings;
3477 if (newparm->size > newt->size)
3478 newt->size = newparm->size;
3482 type->next = newparm;
3484 newt->param = newparm;
3490 for (i = 0; i < numtypeinfos; i++)
3492 if (!STRCMP(qcc_typeinfo[i].name, name))
3494 type = &qcc_typeinfo[i];
3499 if (i == numtypeinfos)
3503 if (!stricmp("Void", name))
3505 else if (!stricmp("Real", name))
3507 else if (!stricmp("Vector", name))
3509 else if (!stricmp("Object", name))
3511 else if (!stricmp("String", name))
3513 else if (!stricmp("PFunc", name))
3514 type = type_function;
3517 QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name);
3518 type = type_float; // shut up compiler warning
3523 if (QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function.
3525 type_inlinefunction = true;
3526 return QCC_PR_ParseFunctionType(newtype, type);
3532 type = QCC_PR_DuplicateType(type);