9 // I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
12 #if (_MSC_VER >= 1400)
13 //with MSVC 8, use MS extensions
14 #define snprintf linuxlike_snprintf_vc8
15 int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
16 #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
19 #define snprintf linuxlike_snprintf
20 int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
21 #define vsnprintf linuxlike_vsnprintf
22 int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
27 #define MEMBERFIELDNAME "__m%s"
29 #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc
31 void QCC_PR_ConditionCompilation(void);
32 pbool QCC_PR_UndefineName(char *name);
33 char *QCC_PR_CheakCompConstString(char *def);
34 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def);
35 pbool QCC_Include(char *filename);
42 char *pr_line_start; // start of current source line
47 token_type_t pr_token_type;
48 QCC_type_t *pr_immediate_type;
49 QCC_eval_t pr_immediate;
51 char pr_immediate_string[8192];
57 CompilerConstant_t *CompilerConstant;
58 int numCompilerConstants;
59 extern pbool expandedemptymacro;
63 char *pr_punctuation[] =
64 // longer symbols must be before a shorter partial match
65 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
67 char *pr_punctuationremap[] = //a nice bit of evilness.
71 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
73 // simple types. function types are dynamically allocated
74 QCC_type_t *type_void;// = {ev_void/*, &def_void*/};
75 QCC_type_t *type_string;// = {ev_string/*, &def_string*/};
76 QCC_type_t *type_float;// = {ev_float/*, &def_float*/};
77 QCC_type_t *type_vector;// = {ev_vector/*, &def_vector*/};
78 QCC_type_t *type_entity;// = {ev_entity/*, &def_entity*/};
79 QCC_type_t *type_field;// = {ev_field/*, &def_field*/};
80 QCC_type_t *type_function;// = {ev_function/*, &def_function*/,NULL,&type_void};
81 // type_function is a void() function used for state defs
82 QCC_type_t *type_pointer;// = {ev_pointer/*, &def_pointer*/};
83 QCC_type_t *type_integer;// = {ev_integer/*, &def_integer*/};
84 QCC_type_t *type_variant;// = {ev_integer/*, &def_integer*/};
86 QCC_type_t *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float};
88 /*QCC_def_t def_void = {type_void, "temp"};
89 QCC_def_t def_string = {type_string, "temp"};
90 QCC_def_t def_float = {type_float, "temp"};
91 QCC_def_t def_vector = {type_vector, "temp"};
92 QCC_def_t def_entity = {type_entity, "temp"};
93 QCC_def_t def_field = {type_field, "temp"};
94 QCC_def_t def_function = {type_function, "temp"};
95 QCC_def_t def_pointer = {type_pointer, "temp"};
96 QCC_def_t def_integer = {type_integer, "temp"};
98 QCC_def_t def_ret, def_parms[MAX_PARMS];
100 //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};
102 void QCC_PR_LexWhitespace (void);
107 //for compiler constants and file includes.
109 typedef struct qcc_includechunk_s {
110 struct qcc_includechunk_s *prev;
112 char *currentdatapoint;
113 int currentlinenumber;
114 CompilerConstant_t *cnst;
115 } qcc_includechunk_t;
116 qcc_includechunk_t *currentchunk;
117 void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst)
119 qcc_includechunk_t *chunk = qccHunkAlloc(sizeof(qcc_includechunk_t));
120 chunk->prev = currentchunk;
121 currentchunk = chunk;
123 chunk->currentdatapoint = pr_file_p;
124 chunk->currentlinenumber = pr_source_line;
133 pr_file_p = qccHunkAlloc(strlen(data)+1);
134 strcpy(pr_file_p, data);
139 void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename)
141 QCC_PR_IncludeChunkEx(data, duplicate, filename, NULL);
144 pbool QCC_PR_UnInclude(void)
149 if( currentchunk->cnst )
150 currentchunk->cnst->inside--;
152 pr_file_p = currentchunk->currentdatapoint;
153 pr_source_line = currentchunk->currentlinenumber;
155 currentchunk = currentchunk->prev;
166 void QCC_PR_PrintNextLine (void)
170 printf ("%3i:",pr_source_line);
171 for (t=pr_line_start ; *t && *t != '\n' ; t++)
176 extern char qccmsourcedir[];
177 //also meant to include it.
178 void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
183 char *end = fullname;
189 /*count how far up we need to go*/
190 while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
196 currentfile += strlen(rootpath); //could this be bad?
198 strcpy(fullname, rootpath);
199 end = fullname+strlen(end);
200 if (*fullname && end[-1] != '/')
203 end = end+strlen(end);
205 strcpy(end, currentfile);
206 end = end+strlen(end);
208 while (end > fullname)
211 /*stop at the slash, unless we're meant to go further*/
212 if (*end == '/' || *end == '\\')
223 strcpy(end, newfile);
225 QCC_Include(fullname);
231 int QCC_PR_LexInteger (void);
232 void QCC_AddFile (char *filename);
233 void QCC_PR_LexString (void);
234 pbool QCC_PR_SimpleGetToken (void);
236 int ParsePrecompilerIf(void)
238 CompilerConstant_t *c;
240 //char *start = pr_file_p; //warning: unused variable âstartâ
241 if (!QCC_PR_SimpleGetToken())
243 if (*pr_file_p == '(')
245 eval = ParsePrecompilerIf();
246 while (*pr_file_p == ' ' || *pr_file_p == '\t')
248 if (*pr_file_p != ')')
249 QCC_PR_ParseError(ERR_EXPECTED, "unclosed bracket condition\n");
252 QCC_PR_ParseError(ERR_EXPECTED, "expected bracket or constant\n");
254 else if (!strcmp(pr_token, "defined"))
256 while (*pr_file_p == ' ' || *pr_file_p == '\t')
258 if (*pr_file_p != '(')
259 QCC_PR_ParseError(ERR_EXPECTED, "no opening bracket after defined\n");
264 QCC_PR_SimpleGetToken();
265 eval = !!QCC_PR_CheckCompConstDefined(pr_token);
267 while (*pr_file_p == ' ' || *pr_file_p == '\t')
269 if (*pr_file_p != ')')
270 QCC_PR_ParseError(ERR_EXPECTED, "unclosed defined condition\n");
276 c = QCC_PR_CheckCompConstDefined(pr_token);
278 eval = atoi(pr_token);
280 eval = atoi(c->value);
283 QCC_PR_SimpleGetToken();
284 if (!strcmp(pr_token, "||"))
285 eval = ParsePrecompilerIf()||eval;
286 else if (!strcmp(pr_token, "&&"))
287 eval = ParsePrecompilerIf()&&eval;
288 else if (!strcmp(pr_token, "<="))
289 eval = eval <= ParsePrecompilerIf();
290 else if (!strcmp(pr_token, ">="))
291 eval = eval >= ParsePrecompilerIf();
292 else if (!strcmp(pr_token, "<"))
293 eval = eval < ParsePrecompilerIf();
294 else if (!strcmp(pr_token, ">"))
295 eval = eval > ParsePrecompilerIf();
296 else if (!strcmp(pr_token, "!="))
297 eval = eval != ParsePrecompilerIf();
306 Runs precompiler stage
308 pbool QCC_PR_Precompiler(void)
314 int level; //#if level
317 if (*pr_file_p == '#')
320 for (directive = pr_file_p+1; *directive; directive++) //so # define works
322 if (*directive == '\r' || *directive == '\n')
323 QCC_PR_ParseError(ERR_UNKNOWNPUCTUATION, "Hanging # with no directive\n");
324 if (*directive > ' ')
327 if (!strncmp(directive, "define", 6))
329 pr_file_p = directive;
330 QCC_PR_ConditionCompilation();
331 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
336 else if (!strncmp(directive, "undef", 5))
338 pr_file_p = directive+5;
339 while(*pr_file_p <= ' ')
342 QCC_PR_SimpleGetToken ();
343 QCC_PR_UndefineName(pr_token);
345 // QCC_PR_ConditionCompilation();
346 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
351 else if (!strncmp(directive, "if", 2))
353 int originalline = pr_source_line;
354 pr_file_p = directive+2;
355 if (!strncmp(pr_file_p, "def ", 4))
360 else if (!strncmp(pr_file_p, "ndef ", 5))
369 //QCC_PR_ParseError("bad \"#if\" type");
374 eval = ParsePrecompilerIf();
376 if(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
378 QCC_PR_ParseError (ERR_NOENDIF, "junk on the end of #if line");
383 QCC_PR_SimpleGetToken ();
385 // if (!STRCMP(pr_token, "COOP_MODE"))
387 if (QCC_PR_CheckCompConstDefined(pr_token))
391 eval = eval?false:true;
394 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
406 while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
411 pr_source_line = originalline;
412 QCC_PR_ParseError (ERR_NOENDIF, "#if with no endif");
415 if (*pr_file_p == '#')
418 while(*pr_file_p==' ' || *pr_file_p == '\t')
420 if (!strncmp(pr_file_p, "endif", 5))
422 if (!strncmp(pr_file_p, "if", 2))
424 if (!strncmp(pr_file_p, "else", 4) && level == 1)
427 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
435 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
441 pr_file_p++; //next line
446 else if (!strncmp(directive, "else", 4))
448 int originalline = pr_source_line;
453 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
459 while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
464 pr_source_line = originalline;
465 QCC_PR_ParseError(ERR_NOENDIF, "#if with no endif");
468 if (*pr_file_p == '#')
471 while(*pr_file_p==' ' || *pr_file_p == '\t')
474 if (!strncmp(pr_file_p, "endif", 5))
476 if (!strncmp(pr_file_p, "if", 2))
478 if (!strncmp(pr_file_p, "else", 4) && level == 1)
485 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
491 pr_file_p++; //go off the end
495 else if (!strncmp(directive, "endif", 5))
497 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
502 QCC_PR_ParseError(ERR_NOPRECOMPILERIF, "unmatched #endif");
506 else if (!strncmp(directive, "eof", 3))
511 else if (!strncmp(directive, "error", 5))
513 pr_file_p = directive+5;
514 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
515 msg[a] = pr_file_p[a];
519 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...
524 QCC_PR_ParseError(ERR_HASHERROR, "#Error: %s", msg);
526 else if (!strncmp(directive, "warning", 7))
528 pr_file_p = directive+7;
529 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
530 msg[a] = pr_file_p[a];
534 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
539 QCC_PR_ParseWarning(WARN_PRECOMPILERMESSAGE, "#warning: %s", msg);
541 else if (!strncmp(directive, "message", 7))
543 pr_file_p = directive+7;
544 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
545 msg[a] = pr_file_p[a];
549 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
554 printf("#message: %s\n", msg);
556 else if (!strncmp(directive, "copyright", 9))
558 pr_file_p = directive+9;
559 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
560 msg[a] = pr_file_p[a];
564 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
569 if (strlen(msg) >= sizeof(QCC_copyright))
570 QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n");
571 strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1);
573 else if (!strncmp(directive, "pack", 4))
576 pr_file_p=directive+4;
577 if (!strncmp(pr_file_p, "id", 2))
581 ifmode = QCC_PR_LexInteger();
586 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
587 msg[a] = pr_file_p[a];
591 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
597 QCC_packid = atoi(msg);
598 else if (ifmode <= 5)
599 strcpy(QCC_Packname[ifmode-1], msg);
601 QCC_PR_ParseError(ERR_TOOMANYPACKFILES, "No more than 5 packs are allowed");
603 else if (!strncmp(directive, "forcecrc", 8))
605 pr_file_p=directive+8;
607 ForcedCRC = QCC_PR_LexInteger();
611 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
612 msg[a] = pr_file_p[a];
616 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
621 else if (!strncmp(directive, "includelist", 11))
623 pr_file_p=directive+11;
625 while(*pr_file_p <= ' ')
630 QCC_PR_LexWhitespace();
631 if (!QCC_PR_SimpleGetToken())
634 QCC_Error(ERR_EOF, "eof in includelist");
642 if (!strcmp(pr_token, "#endlist"))
645 QCC_FindBestInclude(pr_token, compilingfile, qccmsourcedir);
647 if (*pr_file_p == '\r')
650 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
651 msg[a] = pr_file_p[a];
655 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
661 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
666 else if (!strncmp(directive, "include", 7))
670 pr_file_p=directive+7;
672 while(*pr_file_p <= ' ')
676 if (*pr_file_p == '\"')
678 else if (*pr_file_p == '<')
682 QCC_PR_ParseError(0, "Not a string literal (on a #include)");
687 while(*pr_file_p != sm)
689 if (*pr_file_p == '\n')
691 QCC_PR_ParseError(0, "#include continued over line boundry\n");
694 msg[a++] = *pr_file_p;
699 QCC_FindBestInclude(msg, compilingfile, qccmsourcedir);
703 while(*pr_file_p != '\n' && *pr_file_p != '\0' && *pr_file_p <= ' ')
707 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
712 else if (!strncmp(directive, "datafile", 8))
714 pr_file_p=directive+8;
716 while(*pr_file_p <= ' ')
720 printf("Including datafile: %s\n", pr_token);
721 QCC_AddFile(pr_token);
725 for (a = 0; a < sizeof(msg)-1 && 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, "output", 6))
737 extern char destfile[1024];
738 pr_file_p=directive+6;
740 while(*pr_file_p <= ' ')
744 strcpy(destfile, pr_token);
745 printf("Outputfile: %s\n", destfile);
749 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
750 msg[a] = pr_file_p[a];
754 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
759 else if (!strncmp(directive, "pragma", 6))
761 pr_file_p=directive+6;
762 while(*pr_file_p <= ' ')
766 for(a = 0; *pr_file_p != '\n' && *pr_file_p != '\0'; pr_file_p++) //read on until the end of the line
768 if ((*pr_file_p == ' ' || *pr_file_p == '\t'|| *pr_file_p == '(') && !*qcc_token)
771 strcpy(qcc_token, msg);
775 msg[a++] = *pr_file_p;
781 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
787 strcpy(qcc_token, msg);
793 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
797 if (!QC_strcasecmp(qcc_token, "DONT_COMPILE_THIS_FILE"))
801 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
804 if (*pr_file_p == '\n')
807 QCC_PR_NewLine(false);
811 else if (!QC_strcasecmp(qcc_token, "COPYRIGHT"))
813 if (strlen(msg) >= sizeof(QCC_copyright))
814 QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n");
815 strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1);
817 else if (!strncmp(qcc_token, "compress", 8))
819 extern pbool compressoutput;
820 compressoutput = atoi(msg);
822 else if (!strncmp(qcc_token, "forcecrc", 8))
824 ForcedCRC = atoi(msg);
826 else if (!strncmp(qcc_token, "noref", 8))
828 defaultnoref = atoi(msg);
830 else if (!strncmp(qcc_token, "defaultstatic", 13))
832 defaultstatic = atoi(msg);
834 else if (!strncmp(qcc_token, "sourcefile", 10))
836 #define MAXSOURCEFILESLIST 8
837 extern char sourcefileslist[MAXSOURCEFILESLIST][1024];
838 //extern int currentsourcefile; // warning: unused variable âcurrentsourcefileâ
839 extern int numsourcefiles;
845 for (i = 0; i < numsourcefiles; i++)
847 if (!strcmp(sourcefileslist[i], qcc_token))
850 if (i == numsourcefiles)
851 strcpy(sourcefileslist[numsourcefiles++], qcc_token);
853 else if (!QC_strcasecmp(qcc_token, "TARGET"))
855 if (qcc_targetformat == QCF_HEXEN2 && numstatements)
856 QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch from hexen2 target \'%s\'. Ignored.", msg);
857 else if (!QC_strcasecmp(msg, "H2") || !QC_strcasecmp(msg, "HEXEN2"))
860 QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch from hexen2 target \'%s\'. Ignored.", msg);
862 qcc_targetformat = QCF_HEXEN2;
864 else if (!QC_strcasecmp(msg, "KK7"))
865 qcc_targetformat = QCF_KK7;
866 else if (!QC_strcasecmp(msg, "DP") || !QC_strcasecmp(msg, "DARKPLACES"))
867 qcc_targetformat = QCF_DARKPLACES;
868 else if (!QC_strcasecmp(msg, "FTEDEBUG"))
869 qcc_targetformat = QCF_FTEDEBUG;
870 else if (!QC_strcasecmp(msg, "FTE"))
871 qcc_targetformat = QCF_FTE;
872 else if (!QC_strcasecmp(msg, "STANDARD") || !QC_strcasecmp(msg, "ID"))
873 qcc_targetformat = QCF_STANDARD;
874 else if (!QC_strcasecmp(msg, "DEBUG"))
875 qcc_targetformat = QCF_FTEDEBUG;
876 else if (!QC_strcasecmp(msg, "QTEST"))
877 qcc_targetformat = QCF_QTEST;
879 QCC_PR_ParseWarning(WARN_BADTARGET, "Unknown target \'%s\'. Ignored.", msg);
881 else if (!QC_strcasecmp(qcc_token, "PROGS_SRC"))
882 { //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
884 else if (!QC_strcasecmp(qcc_token, "PROGS_DAT"))
885 { //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
886 extern char destfile[1024];
888 extern char qccmfilename[1024];
897 if (!strncmp(s2, "./", 2))
901 while(!strncmp(s2, "../", 3))
907 strcpy(qccmfilename, qccmsourcedir);
908 for (s=qccmfilename+strlen(qccmfilename);p && s>=qccmfilename; s--)
910 if (*s == '/' || *s == '\\')
916 sprintf(destfile, "%s", s2);
920 memmove(destfile+3, destfile, strlen(destfile)+1);
928 strcpy(destfile, qcc_token);
930 printf("Outputfile: %s\n", destfile);
932 else if (!QC_strcasecmp(qcc_token, "keyword") || !QC_strcasecmp(qcc_token, "flag"))
936 s = QCC_COM_Parse(msg);
937 if (!QC_strcasecmp(qcc_token, "enable") || !QC_strcasecmp(qcc_token, "on"))
939 else if (!QC_strcasecmp(qcc_token, "disable") || !QC_strcasecmp(qcc_token, "off"))
943 QCC_PR_ParseWarning(WARN_BADPRAGMA, "compiler flag state not recognised");
947 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
951 s = QCC_COM_Parse(s);
953 for (f = 0; compiler_flag[f].enabled; f++)
955 if (!QC_strcasecmp(compiler_flag[f].abbrev, qcc_token))
957 if (compiler_flag[f].flags & FLAG_MIDCOMPILE)
958 *compiler_flag[f].enabled = st;
960 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Cannot enable/disable keyword/flag via a pragma");
964 if (!compiler_flag[f].enabled)
965 QCC_PR_ParseWarning(WARN_BADPRAGMA, "keyword/flag not recognised");
969 else if (!QC_strcasecmp(qcc_token, "warning"))
973 s = QCC_COM_Parse(msg);
974 if (!stricmp(qcc_token, "enable") || !stricmp(qcc_token, "on"))
976 else if (!stricmp(qcc_token, "disable") || !stricmp(qcc_token, "off"))
978 else if (!stricmp(qcc_token, "toggle"))
982 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning state not recognised");
988 s = QCC_COM_Parse(s);
989 wn = QCC_WarningForName(qcc_token);
991 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
994 if (st == 2) //toggle
995 qccwarningdisabled[wn] = true - qccwarningdisabled[wn];
997 qccwarningdisabled[wn] = st;
1002 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Unknown pragma \'%s\'", qcc_token);
1014 Call at start of file and when *pr_file_p == '\n'
1017 void QCC_PR_NewLine (pbool incomment)
1020 pr_line_start = pr_file_p;
1021 while(*pr_file_p==' ' || *pr_file_p == '\t')
1023 if (incomment) //no constants if in a comment.
1026 else if (QCC_PR_Precompiler())
1031 // PR_PrintNextLine ();
1038 Parses a quoted string
1042 void QCC_PR_LexString (void)
1052 bool fromfile = true;
1059 QCC_COM_Parse(text);
1060 // print("Next token is \"%s\"\n", com_token);
1064 if (fromfile) pr_file_p++;
1069 if (fromfile) pr_file_p++;
1071 QCC_PR_ParseError ("EOF inside quote");
1073 QCC_PR_ParseError ("newline inside quote");
1077 if (fromfile) pr_file_p++;
1079 QCC_PR_ParseError ("EOF inside quote");
1087 QCC_PR_ParseError ("Unknown escape char");
1091 if (fromfile) pr_file_p++;
1098 // if (fromfile) pr_file_p++;
1100 pr_immediate_type=NULL;
1101 oldline=pr_source_line;
1104 if (pr_immediate_type == &type_string)
1106 // print("Appending \"%s\" to \"%s\"\n", pr_immediate_string, tmpbuf);
1107 strcat(tmpbuf, pr_immediate_string);
1108 len+=strlen(pr_immediate_string);
1112 pr_source_line = oldline;
1114 QCC_PR_LexWhitespace();
1115 if (*pr_file_p != '\"') //annother string
1119 QCC_PR_LexWhitespace();
1124 strcpy(pr_token, tmpbuf);
1125 pr_token_type = tt_immediate;
1126 pr_immediate_type = &type_string;
1127 strcpy (pr_immediate_string, pr_token);
1129 // print("Found \"%s\"\n", pr_immediate_string);
1132 void QCC_PR_LexString (void)
1146 QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1148 QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "newline inside quote");
1153 QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1168 else if (c == 's' || c == 'b')
1181 while ((d = *pr_file_p++) != '}')
1183 c = c * 10 + d - '0';
1184 if (d < '0' || d > '9' || c > 255)
1185 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1194 else if (c == 'x' || c == 'X')
1199 d = (unsigned char)*pr_file_p++;
1200 if (d >= '0' && d <= '9')
1202 else if (d >= 'A' && d <= 'F')
1204 else if (d >= 'a' && d <= 'f')
1207 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1211 d = (unsigned char)*pr_file_p++;
1212 if (d >= '0' && d <= '9')
1214 else if (d >= 'A' && d <= 'F')
1216 else if (d >= 'a' && d <= 'f')
1219 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1225 else if (c >= '0' && c <= '9')
1231 QCC_PR_ParseWarning(WARN_HANGINGSLASHR, "Hanging \\\\\r");
1239 QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "Unknown escape char %c", c);
1243 if (len >= sizeof(pr_immediate_string)-1)
1244 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
1246 while(*pr_file_p && *pr_file_p <= ' ')
1248 if (*pr_file_p == '\n')
1251 QCC_PR_NewLine(false);
1256 if (*pr_file_p == '\"') //have annother go
1262 pr_token_type = tt_immediate;
1263 pr_immediate_type = type_string;
1264 strcpy (pr_immediate_string, pr_token);
1269 for (end = pr_file_p; ; end++)
1301 cnst = QCC_PR_CheakCompConstString(pr_file_p);
1302 if (cnst==pr_file_p)
1308 QCC_PR_ParseWarning(WARN_MACROINSTRING, "Macro expansion in string");
1310 if (len+strlen(cnst) >= sizeof(pr_token)-1)
1311 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1313 strcpy(pr_token+len, cnst);
1319 else if (c == 0x7C && flag_acc) //reacc support... reacc is strange.
1326 if (len >= sizeof(pr_token)-1)
1327 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1337 int QCC_PR_LexInteger (void)
1344 if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1349 c = *(pr_file_p+=2);
1357 } while ((c >= '0' && c<= '9') || c == '.' || (c>='a' && c <= 'f'));
1359 return atoi (pr_token);
1362 void QCC_PR_LexNumber (void)
1369 if (*pr_file_p == '-')
1374 pr_token[tokenlen++] = '-';
1376 if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1381 pr_token[tokenlen++] = '0';
1382 pr_token[tokenlen++] = 'x';
1385 pr_immediate_type = NULL;
1386 //assume base 10 if not stated
1390 while((c = *pr_file_p))
1392 if (c >= '0' && c <= '9')
1394 pr_token[tokenlen++] = c;
1398 else if (c >= 'a' && c <= 'f' && base > 10)
1400 pr_token[tokenlen++] = c;
1404 else if (c >= 'A' && c <= 'F' && base > 10)
1406 pr_token[tokenlen++] = c;
1412 pr_token[tokenlen++] = c;
1414 pr_immediate_type = type_float;
1418 if (c >= '0' && c <= '9')
1420 pr_token[tokenlen++] = c;
1433 pr_token[tokenlen++] = 0;
1434 pr_immediate._float = (float)atof(pr_token);
1439 pr_token[tokenlen++] = c;
1440 pr_token[tokenlen++] = 0;
1442 pr_immediate_type = type_integer;
1443 pr_immediate._int = num*sign;
1450 pr_token[tokenlen++] = 0;
1452 if (!pr_immediate_type)
1454 if (flag_assume_integer)
1455 pr_immediate_type = type_integer;
1457 pr_immediate_type = type_float;
1460 if (pr_immediate_type == type_integer)
1462 pr_immediate_type = type_integer;
1463 pr_immediate._int = num*sign;
1467 pr_immediate_type = type_float;
1468 // at this point, we know there's no . in it, so the NaN bug shouldn't happen
1469 // and we cannot use atof on tokens like 0xabc, so use num*sign, it SHOULD be safe
1470 //pr_immediate._float = atof(pr_token);
1471 pr_immediate._float = (float)(num*sign);
1476 float QCC_PR_LexFloat (void)
1489 } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.')); //only allow a . if the next isn't too...
1491 return (float)atof (pr_token);
1498 Parses a single quoted vector
1501 void QCC_PR_LexVector (void)
1507 if (*pr_file_p == '\\')
1508 {//extended character constant
1509 pr_token_type = tt_immediate;
1510 pr_immediate_type = type_float;
1515 pr_immediate._float = '\n';
1518 pr_immediate._float = '\r';
1521 pr_immediate._float = '\t';
1524 pr_immediate._float = '\'';
1527 pr_immediate._float = '\"';
1530 pr_immediate._float = '\\';
1533 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
1535 if (*pr_file_p != '\'')
1536 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
1540 if (pr_file_p[1] == '\'')
1541 {//character constant
1542 pr_token_type = tt_immediate;
1543 pr_immediate_type = type_float;
1544 pr_immediate._float = pr_file_p[0];
1548 pr_token_type = tt_immediate;
1549 pr_immediate_type = type_vector;
1550 QCC_PR_LexWhitespace ();
1551 for (i=0 ; i<3 ; i++)
1553 pr_immediate.vector[i] = QCC_PR_LexFloat ();
1554 QCC_PR_LexWhitespace ();
1556 if (*pr_file_p == '\'' && i == 1)
1559 QCC_PR_ParseWarning (WARN_FTE_SPECIFIC, "Bad vector");
1561 for (i++ ; i<3 ; i++)
1562 pr_immediate.vector[i] = 0;
1566 if (*pr_file_p != '\'')
1567 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad vector");
1575 Parses an identifier
1578 void QCC_PR_LexName (void)
1591 } while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
1592 || (c >= '0' && c <= '9'));
1595 pr_token_type = tt_name;
1603 void QCC_PR_LexPunctuation (void)
1609 pr_token_type = tt_punct;
1611 for (i=0 ; (p = pr_punctuation[i]) != NULL ; i++)
1614 if (!strncmp(p, pr_file_p, len) )
1616 strcpy (pr_token, pr_punctuationremap[i]);
1619 else if (p[0] == '}')
1626 QCC_PR_ParseError (ERR_UNKNOWNPUCTUATION, "Unknown punctuation");
1635 void QCC_PR_LexWhitespace (void)
1642 while ( (c = *pr_file_p) <= ' ')
1647 QCC_PR_NewLine (false);
1654 return; // end of file
1660 if (c=='/' && pr_file_p[1] == '/')
1662 while (*pr_file_p && *pr_file_p != '\n')
1665 if (*pr_file_p == '\n')
1666 pr_file_p++; //don't break on eof.
1667 QCC_PR_NewLine(false);
1671 // skip /* */ comments
1672 if (c=='/' && pr_file_p[1] == '*')
1677 if (pr_file_p[0]=='\n')
1679 QCC_PR_NewLine(true);
1681 if (pr_file_p[1] == 0)
1687 } while (pr_file_p[0] != '*' || pr_file_p[1] != '/');
1692 break; // a real character has been found
1696 //============================================================================
1698 #define MAX_FRAMES 8192
1699 char pr_framemodelname[64];
1700 char pr_framemacros[MAX_FRAMES][64];
1701 int pr_framemacrovalue[MAX_FRAMES];
1702 int pr_nummacros, pr_oldmacros;
1706 void QCC_PR_ClearGrabMacros (void)
1708 pr_oldmacros = pr_nummacros;
1709 // pr_nummacros = 0;
1714 int QCC_PR_FindMacro (char *name)
1718 for (i=pr_nummacros-1 ; i>=0 ; i--)
1720 if (!STRCMP (name, pr_framemacros[i]))
1722 return pr_framemacrovalue[i];
1725 for (i=pr_nummacros-1 ; i>=0 ; i--)
1727 if (!stricmp (name, pr_framemacros[i]))
1729 QCC_PR_ParseWarning(WARN_CASEINSENSATIVEFRAMEMACRO, "Case insensative frame macro");
1730 return pr_framemacrovalue[i];
1736 void QCC_PR_ExpandMacro(void)
1738 int i = QCC_PR_FindMacro(pr_token);
1741 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "Unknown frame macro $%s", pr_token);
1743 sprintf (pr_token,"%d", i);
1744 pr_token_type = tt_immediate;
1745 pr_immediate_type = type_float;
1746 pr_immediate._float = (float)i;
1749 // just parses text, returning false if an eol is reached
1750 pbool QCC_PR_SimpleGetToken (void)
1758 while ( (c = *pr_file_p) <= ' ')
1760 if (c=='\n' || c == 0)
1764 if (pr_file_p[0] == '/')
1766 if (pr_file_p[1] == '/')
1768 while(*pr_file_p && *pr_file_p != '\n')
1772 if (pr_file_p[1] == '*')
1777 while ( (c = *pr_file_p) > ' ' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']')
1787 pbool QCC_PR_LexMacroName(void)
1795 while ( (c = *pr_file_p) <= ' ')
1797 if (c=='\n' || c == 0)
1801 if (pr_file_p[0] == '/')
1803 if (pr_file_p[1] == '/')
1805 while(*pr_file_p && *pr_file_p != '\n')
1809 if (pr_file_p[1] == '*')
1814 while ( (c = *pr_file_p) > ' ' && c != '\n' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']' && !(pr_file_p[0] == '.' && pr_file_p[1] == '.'))
1824 void QCC_PR_MacroFrame(char *name, int value)
1827 for (i=pr_nummacros-1 ; i>=0 ; i--)
1829 if (!STRCMP (name, pr_framemacros[i]))
1831 pr_framemacrovalue[i] = value;
1832 if (i>=pr_oldmacros)
1833 QCC_PR_ParseWarning(WARN_DUPLICATEMACRO, "Duplicate macro defined (%s)", pr_token);
1834 //else it's from an old file, and shouldn't be mentioned.
1839 if (strlen(name)+1 > sizeof(pr_framemacros[0]))
1840 QCC_PR_ParseWarning(ERR_TOOMANYFRAMEMACROS, "Name for frame macro %s is too long", name);
1843 strcpy (pr_framemacros[pr_nummacros], name);
1844 pr_framemacrovalue[pr_nummacros] = value;
1846 if (pr_nummacros >= MAX_FRAMES)
1847 QCC_PR_ParseError(ERR_TOOMANYFRAMEMACROS, "Too many frame macros defined");
1851 void QCC_PR_ParseFrame (void)
1853 while (QCC_PR_LexMacroName ())
1855 QCC_PR_MacroFrame(pr_token, pr_macrovalue++);
1863 Deals with counting sequence numbers and replacing frame macros
1866 void QCC_PR_LexGrab (void)
1868 pr_file_p++; // skip the $
1869 // if (!QCC_PR_SimpleGetToken ())
1870 // QCC_PR_ParseError ("hanging $");
1871 if (*pr_file_p <= ' ')
1872 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
1873 QCC_PR_LexMacroName();
1875 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
1878 if (!STRCMP (pr_token, "frame") || !STRCMP (pr_token, "framesave"))
1880 QCC_PR_ParseFrame ();
1883 // ignore other known $commands - just for model/spritegen
1884 else if (!STRCMP (pr_token, "cd")
1885 || !STRCMP (pr_token, "origin")
1886 || !STRCMP (pr_token, "base")
1887 || !STRCMP (pr_token, "flags")
1888 || !STRCMP (pr_token, "scale")
1889 || !STRCMP (pr_token, "skin") )
1890 { // skip to end of line
1891 while (QCC_PR_LexMacroName ())
1895 else if (!STRCMP (pr_token, "flush"))
1897 QCC_PR_ClearGrabMacros();
1898 while (QCC_PR_LexMacroName ())
1902 else if (!STRCMP (pr_token, "framevalue"))
1904 QCC_PR_LexMacroName ();
1905 pr_macrovalue = atoi(pr_token);
1909 else if (!STRCMP (pr_token, "framerestore"))
1911 QCC_PR_LexMacroName ();
1912 QCC_PR_ExpandMacro();
1913 pr_macrovalue = (int)pr_immediate._float;
1917 else if (!STRCMP (pr_token, "modelname"))
1920 QCC_PR_LexMacroName ();
1922 if (*pr_framemodelname)
1923 QCC_PR_MacroFrame(pr_framemodelname, pr_macrovalue);
1925 strncpy(pr_framemodelname, pr_token, sizeof(pr_framemodelname)-1);
1926 pr_framemodelname[sizeof(pr_framemodelname)-1] = '\0';
1928 i = QCC_PR_FindMacro(pr_framemodelname);
1936 // look for a frame name macro
1938 QCC_PR_ExpandMacro ();
1941 //===========================
1942 //compiler constants - dmw
1944 pbool QCC_PR_UndefineName(char *name)
1947 CompilerConstant_t *c;
1948 c = pHash_Get(&compconstantstable, name);
1951 QCC_PR_ParseWarning(WARN_UNDEFNOTDEFINED, "Precompiler constant %s was not defined", name);
1955 Hash_Remove(&compconstantstable, name);
1959 CompilerConstant_t *QCC_PR_DefineName(char *name)
1962 CompilerConstant_t *cnst;
1964 // if (numCompilerConstants >= MAX_CONSTANTS)
1965 // QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS);
1967 if (strlen(name) >= MAXCONSTANTLENGTH || !*name)
1968 QCC_PR_ParseError(ERR_NAMETOOLONG, "Compiler constant name length is too long or short");
1970 cnst = pHash_Get(&compconstantstable, name);
1973 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "Duplicate definition for Precompiler constant %s", name);
1974 Hash_Remove(&compconstantstable, name);
1977 cnst = qccHunkAlloc(sizeof(CompilerConstant_t));
1980 cnst->numparams = 0;
1981 strcpy(cnst->name, name);
1982 cnst->namelen = strlen(name);
1983 cnst->value = cnst->name + strlen(cnst->name);
1984 for (i = 0; i < MAXCONSTANTPARAMS; i++)
1985 cnst->params[i][0] = '\0';
1987 pHash_Add(&compconstantstable, cnst->name, cnst, qccHunkAlloc(sizeof(bucket_t)));
1992 void QCC_PR_Undefine(void)
1994 QCC_PR_SimpleGetToken ();
1996 QCC_PR_UndefineName(pr_token);
1997 // QCC_PR_ParseError("%s was not defined.", pr_token);
2000 void QCC_PR_ConditionCompilation(void)
2008 CompilerConstant_t *cnst;
2010 QCC_PR_SimpleGetToken ();
2012 if (!QCC_PR_SimpleGetToken ())
2013 QCC_PR_ParseError(ERR_NONAME, "No name defined for compiler constant");
2015 cnst = pHash_Get(&compconstantstable, pr_token);
2018 oldval = cnst->value;
2019 Hash_Remove(&compconstantstable, pr_token);
2024 cnst = QCC_PR_DefineName(pr_token);
2026 if (*pr_file_p == '(')
2031 if (*pr_file_p == ',')
2033 if (cnst->numparams >= MAXCONSTANTPARAMS)
2034 QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
2035 strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
2036 cnst->params[cnst->numparams][pr_file_p-s] = '\0';
2041 if (*pr_file_p == ')')
2043 if (cnst->numparams >= MAXCONSTANTPARAMS)
2044 QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
2045 strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
2046 cnst->params[cnst->numparams][pr_file_p-s] = '\0';
2053 else cnst->numparams = -1;
2058 while(*s == ' ' || *s == '\t')
2062 if ((d - dbuf) + 2 >= dbuflen)
2065 dbuflen = (len+128) * 2;
2066 dbuf = qccHunkAlloc(dbuflen);
2067 memcpy(dbuf, d - len, len);
2073 // read over a newline if necessary
2074 if( s[1] == '\n' || s[1] == '\r' )
2077 QCC_PR_NewLine(false);
2079 if( s[-1] == '\r' && s[0] == '\n' )
2085 else if(*s == '\r' || *s == '\n' || *s == '\0')
2090 if (!quote && s[0]=='/'&&(s[1]=='/'||s[1]=='*'))
2104 { //we always warn if it was already defined
2105 //we use different warning codes so that -Wno-mundane can be used to ignore identical redefinitions.
2106 if (strcmp(oldval, cnst->value))
2107 QCC_PR_ParseWarning(WARN_DUPLICATEPRECOMPILER, "Alternate precompiler definition of %s", pr_token);
2109 QCC_PR_ParseWarning(WARN_IDENTICALPRECOMPILER, "Identical precompiler definition of %s", pr_token);
2115 int QCC_PR_CheakCompConst(void)
2117 char *oldpr_file_p = pr_file_p;
2120 CompilerConstant_t *c;
2123 for (end = pr_file_p; ; end++)
2151 strncpy(pr_token, pr_file_p, end-pr_file_p);
2152 pr_token[end-pr_file_p]='\0';
2154 // printf("%s\n", pr_token);
2155 c = pHash_Get(&compconstantstable, pr_token);
2157 if (c && !c->inside)
2159 pr_file_p = oldpr_file_p+strlen(c->name);
2160 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2162 if (c->numparams>=0)
2164 if (*pr_file_p == '(')
2169 char *paramoffset[MAXCONSTANTPARAMS+1];
2174 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2179 // handle strings correctly by ignoring them
2180 if (*pr_file_p == '\"')
2184 } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
2186 if (*pr_file_p == '(')
2188 else if (!plevel && (*pr_file_p == ',' || *pr_file_p == ')'))
2190 paramoffset[param++] = start;
2191 start = pr_file_p+1;
2192 if (*pr_file_p == ')')
2200 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2205 // move back by one char because we move forward by one at the end of the loop
2207 if (param == MAXCONSTANTPARAMS)
2208 QCC_PR_ParseError(ERR_TOOMANYPARAMS, "Too many parameters in macro call");
2209 } else if (*pr_file_p == ')' )
2211 else if(*pr_file_p == '\n')
2212 QCC_PR_NewLine(false);
2214 // see that *pr_file_p = '\0' up there? Must ++ BEFORE checking for !*pr_file_p
2217 QCC_PR_ParseError(ERR_EOF, "EOF on macro call");
2219 if (param < c->numparams)
2220 QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Not enough macro parameters");
2221 paramoffset[param] = start;
2225 oldpr_file_p = pr_file_p;
2226 pr_file_p = c->value;
2229 whitestart = p = strlen(buffer);
2230 while(*pr_file_p <= ' ') //copy across whitespace
2234 buffer[p++] = *pr_file_p++;
2238 if(*pr_file_p == '\"')
2242 buffer[p++] = *pr_file_p;
2244 } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
2245 buffer[p++] = *pr_file_p; // copy the end-quote too
2247 ++pr_file_p; // and skip it
2250 else if (*pr_file_p == '#') //if you ask for #a##b you will be shot. use #a #b instead, or chain macros.
2252 if (pr_file_p[1] == '#')
2253 { //concatinate (srip out whitespace)
2254 buffer[whitestart] = '\0';
2260 pr_file_p = QCC_COM_Parse2(pr_file_p);
2264 for (p = 0; p < param; p++)
2266 if (!STRCMP(qcc_token, c->params[p]))
2268 strcat(buffer, "\"");
2269 strcat(buffer, paramoffset[p]);
2270 strcat(buffer, "\"");
2276 strcat(buffer, "#");
2277 strcat(buffer, qcc_token);
2278 //QCC_PR_ParseWarning(0, "Stringification ignored");
2280 continue; //already did this one
2284 pr_file_p = QCC_COM_Parse2(pr_file_p);
2288 for (p = 0; p < param; p++)
2290 if (!STRCMP(qcc_token, c->params[p]))
2292 strcat(buffer, paramoffset[p]);
2297 strcat(buffer, qcc_token);
2300 for (p = 0; p < param-1; p++)
2301 paramoffset[p][strlen(paramoffset[p])] = ',';
2302 paramoffset[p][strlen(paramoffset[p])] = ')';
2304 pr_file_p = oldpr_file_p;
2306 expandedemptymacro = true;
2307 QCC_PR_IncludeChunkEx(buffer, true, NULL, c);
2310 QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without opening brace");
2315 expandedemptymacro = true;
2316 QCC_PR_IncludeChunkEx(c->value, false, NULL, c);
2323 if (!strncmp(pr_file_p, "__TIME__", 8))
2325 static char retbuf[128];
2329 strftime( retbuf, sizeof(retbuf),
2330 "\"%H:%M\"", localtime( &long_time ));
2333 QCC_PR_Lex(); //translate the macro's value
2334 pr_file_p = oldpr_file_p+8;
2338 if (!strncmp(pr_file_p, "__DATE__", 8))
2340 static char retbuf[128];
2344 strftime( retbuf, sizeof(retbuf),
2345 "\"%a %d %b %Y\"", localtime( &long_time ));
2348 QCC_PR_Lex(); //translate the macro's value
2349 pr_file_p = oldpr_file_p+8;
2353 if (!strncmp(pr_file_p, "__FILE__", 8))
2355 static char retbuf[256];
2356 sprintf(retbuf, "\"%s\"", strings + s_file);
2358 QCC_PR_Lex(); //translate the macro's value
2359 pr_file_p = oldpr_file_p+8;
2363 if (!strncmp(pr_file_p, "__LINE__", 8))
2365 static char retbuf[256];
2366 sprintf(retbuf, "\"%i\"", pr_source_line);
2368 QCC_PR_Lex(); //translate the macro's value
2369 pr_file_p = oldpr_file_p+8;
2372 if (!strncmp(pr_file_p, "__FUNC__", 8))
2374 static char retbuf[256];
2375 sprintf(retbuf, "\"%s\"",pr_scope->name);
2377 QCC_PR_Lex(); //translate the macro's value
2378 pr_file_p = oldpr_file_p+8;
2381 if (!strncmp(pr_file_p, "__NULL__", 8))
2383 static char retbuf[256];
2384 sprintf(retbuf, "0i");
2386 QCC_PR_Lex(); //translate the macro's value
2387 pr_file_p = oldpr_file_p+8;
2393 char *QCC_PR_CheakCompConstString(char *def)
2397 CompilerConstant_t *c;
2399 c = pHash_Get(&compconstantstable, def);
2403 s = QCC_PR_CheakCompConstString(c->value);
2409 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def)
2411 CompilerConstant_t *c = pHash_Get(&compconstantstable, def);
2415 //============================================================================
2421 Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
2424 void QCC_PR_Lex (void)
2432 if (QCC_PR_UnInclude())
2437 pr_token_type = tt_eof;
2441 QCC_PR_LexWhitespace ();
2445 if (QCC_PR_UnInclude())
2450 pr_token_type = tt_eof;
2458 if (QCC_PR_UnInclude())
2463 pr_token_type = tt_eof;
2467 // handle quoted strings as a unit
2470 QCC_PR_LexString ();
2474 // handle quoted vectors as a unit
2477 QCC_PR_LexVector ();
2481 // if the first character is a valid identifier, parse until a non-id
2482 // character is reached
2483 if ( c == '~' || c == '%') //let's see which one we make into an operator first... possibly both...
2485 QCC_PR_ParseWarning(0, "~ or %% prefixes to denote integers are deprecated. Please use a postfix of 'i'");
2487 pr_token_type = tt_immediate;
2488 pr_immediate_type = type_integer;
2489 pr_immediate._int = QCC_PR_LexInteger ();
2492 if ( c == '0' && pr_file_p[1] == 'x')
2494 pr_token_type = tt_immediate;
2498 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') )
2500 pr_token_type = tt_immediate;
2501 QCC_PR_LexNumber ();
2505 if (c == '#' && !(pr_file_p[1]=='-' || (pr_file_p[1]>='0' && pr_file_p[1] <='9'))) //hash and not number
2508 if (!QCC_PR_CheakCompConst())
2510 if (!QCC_PR_SimpleGetToken())
2511 strcpy(pr_token, "unknown");
2512 QCC_PR_ParseError(ERR_CONSTANTNOTDEFINED, "Explicit precompiler usage when not defined %s", pr_token);
2515 if (pr_token_type == tt_eof)
2521 if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
2523 if (flag_hashonly || !QCC_PR_CheakCompConst()) //look for a macro.
2526 if (pr_token_type == tt_eof)
2528 if (QCC_PR_UnInclude())
2533 pr_token_type = tt_eof;
2544 // parse symbol strings until a non-symbol is found
2545 QCC_PR_LexPunctuation ();
2548 //=============================================================================
2551 void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
2553 if (qccwarningdisabled[type])
2558 printf ("%s(%i) : %s is defined here\n", strings + def->s_file, def->s_line, def->name);
2560 printf ("%s:%i: %s is defined here\n", strings + def->s_file, def->s_line, def->name);
2564 void QCC_PR_PrintScope (void)
2568 if (errorscope != pr_scope)
2569 printf ("in function %s (line %i),\n", pr_scope->name, pr_scope->s_line);
2570 errorscope = pr_scope;
2575 printf ("at global scope,\n");
2579 void QCC_PR_ResetErrorScope(void)
2587 Aborts the current file load
2591 void editbadfile(char *file, int line);
2593 void VARGS QCC_PR_ParseError (int errortype, char *error, ...)
2598 va_start (argptr,error);
2599 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2603 editbadfile(strings+s_file, pr_source_line);
2606 QCC_PR_PrintScope();
2608 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2610 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2612 longjmp (pr_parse_abort, 1);
2614 void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...)
2619 va_start (argptr,error);
2620 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2624 editbadfile(strings+s_file, pr_source_line);
2626 QCC_PR_PrintScope();
2628 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2630 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2632 QCC_PR_ParsePrintDef(WARN_ERROR, def);
2634 longjmp (pr_parse_abort, 1);
2636 void VARGS QCC_PR_ParseWarning (int type, char *error, ...)
2641 if (type < ERR_PARSEERRORS && qccwarningdisabled[type])
2644 va_start (argptr,error);
2645 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2648 QCC_PR_PrintScope();
2649 if (type >= ERR_PARSEERRORS)
2652 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2654 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2660 printf ("%s(%i) : warning: %s\n", strings + s_file, pr_source_line, string);
2662 printf ("%s:%i: warning: %s\n", strings + s_file, pr_source_line, string);
2667 void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...)
2672 if (qccwarningdisabled[type])
2675 va_start (argptr,error);
2676 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2679 QCC_PR_PrintScope();
2683 printf ("%s(%i) : note: %s\n", file, line, string);
2685 printf ("%s:%i: note: %s\n", file, line, string);
2688 printf ("note: %s\n", string);
2691 void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
2696 if (qccwarningdisabled[type])
2699 va_start (argptr,error);
2700 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2703 QCC_PR_PrintScope();
2707 printf ("%s(%i) : warning: %s\n", file, line, string);
2709 printf ("%s:%i: warning: %s\n", file, line, string);
2712 printf ("warning: %s\n", string);
2721 Issues an error if the current token isn't equal to string
2725 #ifndef COMMONINLINES
2726 void QCC_PR_Expect (char *string)
2728 if (STRCMP (string, pr_token))
2729 QCC_PR_ParseError (ERR_EXPECTED, "expected %s, found %s",string, pr_token);
2739 Returns true and gets the next token if the current token equals string
2740 Returns false and does nothing otherwise
2743 #ifndef COMMONINLINES
2744 pbool QCC_PR_CheckToken (char *string)
2746 if (pr_token_type != tt_punct)
2749 if (STRCMP (string, pr_token))
2756 pbool QCC_PR_CheckImmediate (char *string)
2758 if (pr_token_type != tt_immediate)
2761 if (STRCMP (string, pr_token))
2768 pbool QCC_PR_CheckName(char *string)
2770 if (pr_token_type != tt_name)
2772 if (flag_caseinsensative)
2774 if (stricmp (string, pr_token))
2779 if (STRCMP(string, pr_token))
2786 pbool QCC_PR_CheckKeyword(int keywordenabled, char *string)
2788 if (!keywordenabled)
2790 if (flag_caseinsensative)
2792 if (stricmp (string, pr_token))
2797 if (STRCMP(string, pr_token))
2810 Checks to see if the current token is a valid name
2813 char *QCC_PR_ParseName (void)
2815 static char ident[MAX_NAME];
2818 if (pr_token_type != tt_name)
2819 QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
2820 if (strlen(pr_token) >= MAX_NAME-1)
2821 QCC_PR_ParseError (ERR_NAMETOOLONG, "name too long");
2822 strcpy (ident, pr_token);
2825 ret = qccHunkAlloc(strlen(ident)+1);
2835 Returns a preexisting complex type that matches the parm, or allocates
2836 a new one and copies it out.
2841 QCC_type_t *QCC_PR_NewType (char *name, int basictype);
2842 int typecmp(QCC_type_t *a, QCC_type_t *b)
2847 return 1; //different (^ and not both null)
2849 if (a->type != b->type)
2851 if (a->num_parms != b->num_parms)
2854 if (a->size != b->size)
2856 // if (STRCMP(a->name, b->name)) //This isn't 100% clean.
2859 if (typecmp(a->aux_type, b->aux_type))
2862 if (a->param || b->param)
2880 QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in)
2882 QCC_type_t *out, *op, *ip;
2886 out = QCC_PR_NewType(in->name, in->type);
2887 out->aux_type = QCC_PR_DuplicateType(in->aux_type);
2888 out->param = QCC_PR_DuplicateType(in->param);
2894 out->param = op = QCC_PR_DuplicateType(ip);
2896 op = (op->next = QCC_PR_DuplicateType(ip));
2899 out->size = in->size;
2900 out->num_parms = in->num_parms;
2902 out->name = in->name;
2903 out->parentclass = in->parentclass;
2908 char *TypeName(QCC_type_t *type)
2910 static char buffer[2][512];
2917 if (type->type == ev_field)
2919 type = type->aux_type;
2924 if (type->type == ev_function)
2926 strcat(ret, type->aux_type->name);
2931 strcat(ret, type->name);
2939 else if (type->type == ev_entity && type->parentclass)
2943 strcat(ret, "class ");
2944 strcat(ret, type->name);
2945 /* strcat(ret, " {");
2949 strcat(ret, type->name);
2959 strcpy(ret, type->name);
2961 return buffer[op&1];
2963 //#define typecmp(a, b) (a && ((a)->type==(b)->type) && !STRCMP((a)->name, (b)->name))
2965 QCC_type_t *QCC_PR_FindType (QCC_type_t *type)
2968 for (t = 0; t < numtypeinfos; t++)
2970 // check = &qcc_typeinfo[t];
2971 if (typecmp(&qcc_typeinfo[t], type))
2975 // c2 = check->next;
2977 // for (i=0 ; n2&&c2 ; i++)
2979 // if (!typecmp((c2), (n2)))
2985 // if (n2==NULL&&c2==NULL)
2987 return &qcc_typeinfo[t];
2990 QCC_Error(ERR_INTERNAL, "Error with type");
2995 QCC_type_t *QCC_PR_NextSubType(QCC_type_t *type, QCC_type_t *prev)
3001 for (p = prev->num_parms; p; p--)
3002 prev = QCC_PR_NextSubType(prev, NULL);
3003 if (prev->num_parms)
3015 QCC_type_t *QCC_TypeForName(char *name)
3019 for (i = 0; i < numtypeinfos; i++)
3021 if (!STRCMP(qcc_typeinfo[i].name, name))
3023 return &qcc_typeinfo[i];
3034 For error recovery, also pops out of nested braces
3037 void QCC_PR_SkipToSemicolon (void)
3041 if (!pr_bracelevel && QCC_PR_CheckToken (";"))
3044 } while (pr_token_type != tt_eof);
3052 Parses a variable type, including field and functions types
3055 #ifdef MAX_EXTRA_PARMS
3056 char pr_parm_names[MAX_PARMS+MAX_EXTRA_PARMS][MAX_NAME];
3058 char pr_parm_names[MAX_PARMS][MAX_NAME];
3061 pbool recursivefunctiontype;
3063 QCC_type_t *QCC_PR_NewType (char *name, int basictype);
3064 //expects a ( to have already been parsed.
3065 QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
3067 QCC_type_t *ftype, *ptype, *nptype;
3069 int definenames = !recursivefunctiontype;
3071 recursivefunctiontype++;
3073 ftype = QCC_PR_NewType(type_function->name, ev_function);
3075 ftype->aux_type = returntype; // return type
3076 ftype->num_parms = 0;
3080 if (!QCC_PR_CheckToken (")"))
3082 if (QCC_PR_CheckToken ("..."))
3083 ftype->num_parms = -1; // variable args
3087 if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
3088 QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS);
3090 if (QCC_PR_CheckToken ("..."))
3092 ftype->num_parms = (ftype->num_parms * -1) - 1;
3096 nptype = QCC_PR_ParseType(true);
3098 if (nptype->type == ev_void)
3103 ftype->param = ptype;
3107 ptype->next = nptype;
3108 ptype = ptype->next;
3110 // type->name = "FUNC PARAMETER";
3113 if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")"))
3115 name = QCC_PR_ParseName ();
3117 strcpy (pr_parm_names[ftype->num_parms], name);
3119 else if (definenames)
3120 strcpy (pr_parm_names[ftype->num_parms], "");
3122 } while (QCC_PR_CheckToken (","));
3124 QCC_PR_Expect (")");
3126 recursivefunctiontype--;
3129 return QCC_PR_FindType (ftype);
3131 QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
3133 QCC_type_t *ftype, *ptype, *nptype;
3136 int definenames = !recursivefunctiontype;
3138 recursivefunctiontype++;
3140 ftype = QCC_PR_NewType(type_function->name, ev_function);
3142 ftype->aux_type = returntype; // return type
3143 ftype->num_parms = 0;
3147 if (!QCC_PR_CheckToken (")"))
3149 if (QCC_PR_CheckToken ("..."))
3150 ftype->num_parms = -1; // variable args
3154 if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
3155 QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS);
3157 if (QCC_PR_CheckToken ("..."))
3159 ftype->num_parms = (ftype->num_parms * -1) - 1;
3163 if (QCC_PR_CheckName("arg"))
3165 sprintf(argname, "arg%i", ftype->num_parms);
3167 nptype = QCC_PR_NewType("Variant", ev_variant);
3169 else if (QCC_PR_CheckName("vect")) //this can only be of vector sizes, so...
3171 sprintf(argname, "arg%i", ftype->num_parms);
3173 nptype = QCC_PR_NewType("Vector", ev_vector);
3177 name = QCC_PR_ParseName();
3179 nptype = QCC_PR_ParseType(true);
3182 if (nptype->type == ev_void)
3187 ftype->param = ptype;
3191 ptype->next = nptype;
3192 ptype = ptype->next;
3194 // type->name = "FUNC PARAMETER";
3197 strcpy (pr_parm_names[ftype->num_parms], name);
3199 } while (QCC_PR_CheckToken (";"));
3201 QCC_PR_Expect (")");
3203 recursivefunctiontype--;
3206 return QCC_PR_FindType (ftype);
3208 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
3212 sprintf(name, "*%s", pointsto->name);
3213 ptype = QCC_PR_NewType(name, ev_pointer);
3214 ptype->aux_type = pointsto;
3215 return QCC_PR_FindType (ptype);
3217 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
3221 sprintf(name, "FIELD TYPE(%s)", pointsto->name);
3222 ptype = QCC_PR_NewType(name, ev_field);
3223 ptype->aux_type = pointsto;
3224 ptype->size = ptype->aux_type->size;
3225 return QCC_PR_FindType (ptype);
3228 pbool type_inlinefunction;
3229 QCC_type_t *QCC_PR_ParseType (int newtype)
3231 QCC_type_t *newparm;
3237 type_inlinefunction = false; //doesn't really matter so long as its not from an inline function type
3241 if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges)
3243 newt = QCC_PR_NewType("FIELD TYPE", ev_field);
3244 newt->aux_type = QCC_PR_ParseType (false);
3246 newt->size = newt->aux_type->size;
3248 newt = QCC_PR_FindType (newt);
3250 type = QCC_PR_NewType("FIELD TYPE", ev_field);
3251 type->aux_type = newt;
3253 type->size = type->aux_type->size;
3257 return QCC_PR_FindType (type);
3259 if (QCC_PR_CheckToken ("."))
3261 newt = QCC_PR_NewType("FIELD TYPE", ev_field);
3262 newt->aux_type = QCC_PR_ParseType (false);
3264 newt->size = newt->aux_type->size;
3268 return QCC_PR_FindType (newt);
3271 name = QCC_PR_CheakCompConstString(pr_token);
3273 if (QCC_PR_CheckKeyword (keyword_class, "class"))
3276 QCC_type_t *fieldtype;
3277 char membername[2048];
3278 char *classname = QCC_PR_ParseName();
3279 int forwarddeclaration;
3283 /* Don't advance the line number yet */
3284 forwarddeclaration = pr_token[0] == ';';
3286 /* Look to see if this type is already defined */
3287 for(i=0;i<numtypeinfos;i++)
3289 if (STRCMP(qcc_typeinfo[i].name, classname) == 0)
3291 newt = &qcc_typeinfo[i];
3296 if (newt && forwarddeclaration)
3297 QCC_PR_ParseError(ERR_REDECLARATION, "Forward declaration of already defined class %s", classname);
3299 if (newt && newt->num_parms != 0)
3300 QCC_PR_ParseError(ERR_REDECLARATION, "Redeclaration of class %s", classname);
3303 newt = QCC_PR_NewType(classname, ev_entity);
3305 newt->size=type_entity->size;
3309 if (forwarddeclaration)
3311 QCC_PR_CheckToken(";");
3317 if (QCC_PR_CheckToken(":"))
3319 char *parentname = QCC_PR_ParseName();
3320 newt->parentclass = QCC_TypeForName(parentname);
3321 if (!newt->parentclass)
3322 QCC_PR_ParseError(ERR_NOTANAME, "Parent class %s was not defined", parentname);
3325 newt->parentclass = type_entity;
3329 if (QCC_PR_CheckToken(","))
3330 QCC_PR_ParseError(ERR_NOTANAME, "member missing name");
3331 while (!QCC_PR_CheckToken("}"))
3333 // if (QCC_PR_CheckToken(","))
3334 // type->next = QCC_PR_NewType(type->name, type->type);
3336 newparm = QCC_PR_ParseType(true);
3338 if (newparm->type == ev_struct || newparm->type == ev_union) //we wouldn't be able to handle it.
3339 QCC_PR_ParseError(ERR_INTERNAL, "Struct or union in class %s", classname);
3341 if (!QCC_PR_CheckToken(";"))
3343 newparm->name = QCC_CopyString(pr_token)+strings;
3345 if (QCC_PR_CheckToken("["))
3347 type->next->size*=atoi(pr_token);
3351 QCC_PR_CheckToken(";");
3354 newparm->name = QCC_CopyString("")+strings;
3356 sprintf(membername, "%s::"MEMBERFIELDNAME, classname, newparm->name);
3357 fieldtype = QCC_PR_NewType(newparm->name, ev_field);
3358 fieldtype->aux_type = newparm;
3359 fieldtype->size = newparm->size;
3360 QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 1, false);
3363 newparm->ofs = 0;//newt->size;
3367 type->next = newparm;
3369 newt->param = newparm;
3378 if (QCC_PR_CheckKeyword (keyword_struct, "struct"))
3380 newt = QCC_PR_NewType("struct", ev_struct);
3385 if (QCC_PR_CheckToken(","))
3386 QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3389 while (!QCC_PR_CheckToken("}"))
3391 if (QCC_PR_CheckToken(","))
3394 QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3395 newparm = QCC_PR_NewType(newparm->name, newparm->type);
3398 newparm = QCC_PR_ParseType(true);
3400 if (!QCC_PR_CheckToken(";"))
3402 newparm->name = QCC_CopyString(pr_token)+strings;
3404 if (QCC_PR_CheckToken("["))
3406 newparm->size*=atoi(pr_token);
3410 QCC_PR_CheckToken(";");
3413 newparm->name = QCC_CopyString("")+strings;
3414 newparm->ofs = newt->size;
3415 newt->size += newparm->size;
3419 type->next = newparm;
3421 newt->param = newparm;
3426 if (QCC_PR_CheckKeyword (keyword_union, "union"))
3428 newt = QCC_PR_NewType("union", ev_union);
3433 if (QCC_PR_CheckToken(","))
3434 QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3436 while (!QCC_PR_CheckToken("}"))
3438 if (QCC_PR_CheckToken(","))
3441 QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3442 newparm = QCC_PR_NewType(newparm->name, newparm->type);
3445 newparm = QCC_PR_ParseType(true);
3446 if (QCC_PR_CheckToken(";"))
3447 newparm->name = QCC_CopyString("")+strings;
3450 newparm->name = QCC_CopyString(pr_token)+strings;
3455 if (newparm->size > newt->size)
3456 newt->size = newparm->size;
3460 type->next = newparm;
3462 newt->param = newparm;
3468 for (i = 0; i < numtypeinfos; i++)
3470 if (!STRCMP(qcc_typeinfo[i].name, name))
3472 type = &qcc_typeinfo[i];
3477 if (i == numtypeinfos)
3481 if (!stricmp("Void", name))
3483 else if (!stricmp("Real", name))
3485 else if (!stricmp("Vector", name))
3487 else if (!stricmp("Object", name))
3489 else if (!stricmp("String", name))
3491 else if (!stricmp("PFunc", name))
3492 type = type_function;
3495 QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name);
3496 type = type_float; // shut up compiler warning
3501 if (QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function.
3503 type_inlinefunction = true;
3504 return QCC_PR_ParseFunctionType(newtype, type);
3510 type = QCC_PR_DuplicateType(type);