11 #define snprintf linuxlike_snprintf
12 int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
13 #define vsnprintf linuxlike_vsnprintf
14 int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
15 //void *__imp__vsnprintf = vsnprintf;
19 #define MEMBERFIELDNAME "__m%s"
21 #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc
23 void QCC_PR_ConditionCompilation(void);
24 pbool QCC_PR_UndefineName(char *name);
25 char *QCC_PR_CheakCompConstString(char *def);
26 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def);
27 pbool QCC_Include(char *filename);
34 char *pr_line_start; // start of current source line
39 token_type_t pr_token_type;
40 QCC_type_t *pr_immediate_type;
41 QCC_eval_t pr_immediate;
43 char pr_immediate_string[8192];
49 CompilerConstant_t *CompilerConstant;
50 int numCompilerConstants;
51 extern pbool expandedemptymacro;
55 char *pr_punctuation[] =
56 // longer symbols must be before a shorter partial match
57 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
59 char *pr_punctuationremap[] = //a nice bit of evilness.
63 {"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL};
65 // simple types. function types are dynamically allocated
66 QCC_type_t *type_void;// = {ev_void/*, &def_void*/};
67 QCC_type_t *type_string;// = {ev_string/*, &def_string*/};
68 QCC_type_t *type_float;// = {ev_float/*, &def_float*/};
69 QCC_type_t *type_vector;// = {ev_vector/*, &def_vector*/};
70 QCC_type_t *type_entity;// = {ev_entity/*, &def_entity*/};
71 QCC_type_t *type_field;// = {ev_field/*, &def_field*/};
72 QCC_type_t *type_function;// = {ev_function/*, &def_function*/,NULL,&type_void};
73 // type_function is a void() function used for state defs
74 QCC_type_t *type_pointer;// = {ev_pointer/*, &def_pointer*/};
75 QCC_type_t *type_integer;// = {ev_integer/*, &def_integer*/};
76 QCC_type_t *type_variant;// = {ev_integer/*, &def_integer*/};
77 QCC_type_t *type_floatpointer;
78 QCC_type_t *type_intpointer;
80 QCC_type_t *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float};
82 /*QCC_def_t def_void = {type_void, "temp"};
83 QCC_def_t def_string = {type_string, "temp"};
84 QCC_def_t def_float = {type_float, "temp"};
85 QCC_def_t def_vector = {type_vector, "temp"};
86 QCC_def_t def_entity = {type_entity, "temp"};
87 QCC_def_t def_field = {type_field, "temp"};
88 QCC_def_t def_function = {type_function, "temp"};
89 QCC_def_t def_pointer = {type_pointer, "temp"};
90 QCC_def_t def_integer = {type_integer, "temp"};
92 QCC_def_t def_ret, def_parms[MAX_PARMS];
94 //QCC_def_t *def_for_type[9] = {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer, &def_integer};
96 void QCC_PR_LexWhitespace (void);
101 //for compiler constants and file includes.
103 qcc_includechunk_t *currentchunk;
104 void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst)
106 qcc_includechunk_t *chunk = qccHunkAlloc(sizeof(qcc_includechunk_t));
107 chunk->prev = currentchunk;
108 currentchunk = chunk;
110 chunk->currentdatapoint = pr_file_p;
111 chunk->currentlinenumber = pr_source_line;
120 pr_file_p = qccHunkAlloc(strlen(data)+1);
121 strcpy(pr_file_p, data);
126 void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename)
128 QCC_PR_IncludeChunkEx(data, duplicate, filename, NULL);
131 pbool QCC_PR_UnInclude(void)
136 if( currentchunk->cnst )
137 currentchunk->cnst->inside--;
139 pr_file_p = currentchunk->currentdatapoint;
140 pr_source_line = currentchunk->currentlinenumber;
142 currentchunk = currentchunk->prev;
153 void QCC_PR_PrintNextLine (void)
157 printf ("%3i:",pr_source_line);
158 for (t=pr_line_start ; *t && *t != '\n' ; t++)
163 extern char qccmsourcedir[];
164 //also meant to include it.
165 void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
170 char *end = fullname;
176 /*count how far up we need to go*/
177 while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
183 currentfile += strlen(rootpath); //could this be bad?
185 strcpy(fullname, rootpath);
186 end = fullname+strlen(end);
187 if (*fullname && end[-1] != '/')
190 end = end+strlen(end);
192 strcpy(end, currentfile);
193 end = end+strlen(end);
195 while (end > fullname)
198 /*stop at the slash, unless we're meant to go further*/
199 if (*end == '/' || *end == '\\')
210 strcpy(end, newfile);
212 QCC_Include(fullname);
218 int QCC_PR_LexInteger (void);
219 void QCC_AddFile (char *filename);
220 void QCC_PR_LexString (void);
221 pbool QCC_PR_SimpleGetToken (void);
223 int ParsePrecompilerIf(void)
225 CompilerConstant_t *c;
227 pbool notted = false;
230 while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n')
234 if (*pr_file_p == '!')
238 while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n')
244 if (!QCC_PR_SimpleGetToken())
246 if (*pr_file_p == '(')
249 eval = ParsePrecompilerIf();
250 while (*pr_file_p == ' ' || *pr_file_p == '\t')
252 if (*pr_file_p != ')')
253 QCC_PR_ParseError(ERR_EXPECTED, "unclosed bracket condition\n");
257 QCC_PR_ParseError(ERR_EXPECTED, "expected bracket or constant\n");
259 else if (!strcmp(pr_token, "defined"))
261 while (*pr_file_p == ' ' || *pr_file_p == '\t')
263 if (*pr_file_p != '(')
264 QCC_PR_ParseError(ERR_EXPECTED, "no opening bracket after defined\n");
269 QCC_PR_SimpleGetToken();
270 eval = !!QCC_PR_CheckCompConstDefined(pr_token);
272 while (*pr_file_p == ' ' || *pr_file_p == '\t')
274 if (*pr_file_p != ')')
275 QCC_PR_ParseError(ERR_EXPECTED, "unclosed defined condition\n");
281 c = QCC_PR_CheckCompConstDefined(pr_token);
283 eval = atoi(pr_token);
285 eval = atoi(c->value);
291 QCC_PR_SimpleGetToken();
292 if (!strcmp(pr_token, "||"))
293 eval = ParsePrecompilerIf()||eval;
294 else if (!strcmp(pr_token, "&&"))
295 eval = ParsePrecompilerIf()&&eval;
296 else if (!strcmp(pr_token, "<="))
297 eval = eval <= ParsePrecompilerIf();
298 else if (!strcmp(pr_token, ">="))
299 eval = eval >= ParsePrecompilerIf();
300 else if (!strcmp(pr_token, "<"))
301 eval = eval < ParsePrecompilerIf();
302 else if (!strcmp(pr_token, ">"))
303 eval = eval > ParsePrecompilerIf();
304 else if (!strcmp(pr_token, "!="))
305 eval = eval != ParsePrecompilerIf();
314 Runs precompiler stage
316 pbool QCC_PR_Precompiler(void)
322 int level; //#if level
325 if (*pr_file_p == '#')
328 for (directive = pr_file_p+1; *directive; directive++) //so # define works
330 if (*directive == '\r' || *directive == '\n')
331 QCC_PR_ParseError(ERR_UNKNOWNPUCTUATION, "Hanging # with no directive\n");
332 if (*directive > ' ')
335 if (!strncmp(directive, "define", 6))
337 pr_file_p = directive;
338 QCC_PR_ConditionCompilation();
339 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
344 else if (!strncmp(directive, "undef", 5))
346 pr_file_p = directive+5;
347 while(*pr_file_p <= ' ')
350 QCC_PR_SimpleGetToken ();
351 QCC_PR_UndefineName(pr_token);
353 // QCC_PR_ConditionCompilation();
354 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
359 else if (!strncmp(directive, "if", 2))
361 int originalline = pr_source_line;
362 pr_file_p = directive+2;
363 if (!strncmp(pr_file_p, "def ", 4))
368 else if (!strncmp(pr_file_p, "ndef ", 5))
377 //QCC_PR_ParseError("bad \"#if\" type");
382 eval = ParsePrecompilerIf();
384 if(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
386 QCC_PR_ParseError (ERR_NOENDIF, "junk on the end of #if line");
391 QCC_PR_SimpleGetToken ();
393 // if (!STRCMP(pr_token, "COOP_MODE"))
395 if (QCC_PR_CheckCompConstDefined(pr_token))
399 eval = eval?false:true;
402 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
414 while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
419 pr_source_line = originalline;
420 QCC_PR_ParseError (ERR_NOENDIF, "#if with no endif");
423 if (*pr_file_p == '#')
426 while(*pr_file_p==' ' || *pr_file_p == '\t')
428 if (!strncmp(pr_file_p, "endif", 5))
430 if (!strncmp(pr_file_p, "if", 2))
432 if (!strncmp(pr_file_p, "else", 4) && level == 1)
435 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
443 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
449 pr_file_p++; //next line
454 else if (!strncmp(directive, "else", 4))
456 int originalline = pr_source_line;
461 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
467 while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t'))
472 pr_source_line = originalline;
473 QCC_PR_ParseError(ERR_NOENDIF, "#if with no endif");
476 if (*pr_file_p == '#')
479 while(*pr_file_p==' ' || *pr_file_p == '\t')
482 if (!strncmp(pr_file_p, "endif", 5))
484 if (!strncmp(pr_file_p, "if", 2))
486 if (!strncmp(pr_file_p, "else", 4) && level == 1)
493 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
499 pr_file_p++; //go off the end
503 else if (!strncmp(directive, "endif", 5))
505 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
510 QCC_PR_ParseError(ERR_NOPRECOMPILERIF, "unmatched #endif");
514 else if (!strncmp(directive, "eof", 3))
519 else if (!strncmp(directive, "error", 5))
521 pr_file_p = directive+5;
522 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
523 msg[a] = pr_file_p[a];
527 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line, yes, I KNOW we are going to register an error, and not properly leave this function tree, but...
532 QCC_PR_ParseError(ERR_HASHERROR, "#Error: %s", msg);
534 else if (!strncmp(directive, "warning", 7))
536 pr_file_p = directive+7;
537 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
538 msg[a] = pr_file_p[a];
542 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
547 QCC_PR_ParseWarning(WARN_PRECOMPILERMESSAGE, "#warning: %s", msg);
549 else if (!strncmp(directive, "message", 7))
551 pr_file_p = directive+7;
552 for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
553 msg[a] = pr_file_p[a];
557 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
562 printf("#message: %s\n", msg);
564 else if (!strncmp(directive, "copyright", 9))
566 pr_file_p = directive+9;
567 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
568 msg[a] = pr_file_p[a];
572 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
577 if (strlen(msg) >= sizeof(QCC_copyright))
578 QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n");
579 strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1);
581 else if (!strncmp(directive, "pack", 4))
584 pr_file_p=directive+4;
585 if (!strncmp(pr_file_p, "id", 2))
589 ifmode = QCC_PR_LexInteger();
594 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
595 msg[a] = pr_file_p[a];
599 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
605 QCC_packid = atoi(msg);
606 else if (ifmode <= 5)
607 strcpy(QCC_Packname[ifmode-1], msg);
609 QCC_PR_ParseError(ERR_TOOMANYPACKFILES, "No more than 5 packs are allowed");
611 else if (!strncmp(directive, "forcecrc", 8))
613 pr_file_p=directive+8;
615 ForcedCRC = QCC_PR_LexInteger();
619 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
620 msg[a] = pr_file_p[a];
624 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
629 else if (!strncmp(directive, "includelist", 11))
631 pr_file_p=directive+11;
633 while(*pr_file_p <= ' ')
638 QCC_PR_LexWhitespace();
639 if (!QCC_PR_SimpleGetToken())
642 QCC_Error(ERR_EOF, "eof in includelist");
650 if (!strcmp(pr_token, "#endlist"))
653 QCC_FindBestInclude(pr_token, compilingfile, qccmsourcedir);
655 if (*pr_file_p == '\r')
658 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
664 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
669 else if (!strncmp(directive, "include", 7))
673 pr_file_p=directive+7;
675 while(*pr_file_p <= ' ')
679 if (*pr_file_p == '\"')
681 else if (*pr_file_p == '<')
685 QCC_PR_ParseError(0, "Not a string literal (on a #include)");
690 while(*pr_file_p != sm)
692 if (*pr_file_p == '\n')
694 QCC_PR_ParseError(0, "#include continued over line boundry\n");
697 msg[a++] = *pr_file_p;
702 QCC_FindBestInclude(msg, compilingfile, qccmsourcedir);
706 while(*pr_file_p != '\n' && *pr_file_p != '\0' && *pr_file_p <= ' ')
710 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
715 else if (!strncmp(directive, "datafile", 8))
717 pr_file_p=directive+8;
719 while(*pr_file_p <= ' ')
723 printf("Including datafile: %s\n", pr_token);
724 QCC_AddFile(pr_token);
728 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
729 msg[a] = pr_file_p[a];
733 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
738 else if (!strncmp(directive, "output", 6))
740 extern char destfile[1024];
741 pr_file_p=directive+6;
743 while(*pr_file_p <= ' ')
747 strcpy(destfile, pr_token);
748 printf("Outputfile: %s\n", destfile);
752 for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
753 msg[a] = pr_file_p[a];
757 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
762 else if (!strncmp(directive, "pragma", 6))
764 pr_file_p=directive+6;
765 while(*pr_file_p <= ' ')
769 for(a = 0; *pr_file_p != '\n' && *pr_file_p != '\0'; pr_file_p++) //read on until the end of the line
771 if ((*pr_file_p == ' ' || *pr_file_p == '\t'|| *pr_file_p == '(') && !*qcc_token)
774 strcpy(qcc_token, msg);
778 msg[a++] = *pr_file_p;
784 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
790 strcpy(qcc_token, msg);
796 for (end = msg + a-1; end>=msg && *end <= ' '; end--)
800 if (!QC_strcasecmp(qcc_token, "DONT_COMPILE_THIS_FILE"))
804 while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
807 if (*pr_file_p == '\n')
810 QCC_PR_NewLine(false);
814 else if (!QC_strcasecmp(qcc_token, "COPYRIGHT"))
816 if (strlen(msg) >= sizeof(QCC_copyright))
817 QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n");
818 strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1);
820 else if (!strncmp(qcc_token, "compress", 8))
822 extern pbool compressoutput;
823 compressoutput = atoi(msg);
825 else if (!strncmp(qcc_token, "forcecrc", 8))
827 ForcedCRC = atoi(msg);
829 else if (!strncmp(qcc_token, "noref", 8))
831 defaultnoref = atoi(msg);
833 else if (!strncmp(qcc_token, "defaultstatic", 13))
835 defaultstatic = atoi(msg);
837 else if (!strncmp(qcc_token, "wrasm", 5))
839 pbool on = atoi(msg);
847 asmfile = fopen("qc.asm", "wb");
849 else if (!strncmp(qcc_token, "sourcefile", 10))
851 #define MAXSOURCEFILESLIST 8
852 extern char sourcefileslist[MAXSOURCEFILESLIST][1024];
853 //extern int currentsourcefile; // warning: unused variable âcurrentsourcefileâ
854 extern int numsourcefiles;
860 for (i = 0; i < numsourcefiles; i++)
862 if (!strcmp(sourcefileslist[i], qcc_token))
865 if (i == numsourcefiles && numsourcefiles < MAXSOURCEFILESLIST)
866 strcpy(sourcefileslist[numsourcefiles++], qcc_token);
868 else if (!QC_strcasecmp(qcc_token, "TARGET"))
870 if (qcc_targetformat == QCF_HEXEN2 && numstatements)
871 QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch from hexen2 target \'%s\'. Ignored.", msg);
872 else if (!QC_strcasecmp(msg, "H2") || !QC_strcasecmp(msg, "HEXEN2"))
875 QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch to hexen2 target \'%s\'. Ignored.", msg);
877 qcc_targetformat = QCF_HEXEN2;
879 else if (!QC_strcasecmp(msg, "KK7"))
880 qcc_targetformat = QCF_KK7;
881 else if (!QC_strcasecmp(msg, "DP") || !QC_strcasecmp(msg, "DARKPLACES"))
882 qcc_targetformat = QCF_DARKPLACES;
883 else if (!QC_strcasecmp(msg, "FTEDEBUG"))
884 qcc_targetformat = QCF_FTEDEBUG;
885 else if (!QC_strcasecmp(msg, "FTE"))
886 qcc_targetformat = QCF_FTE;
887 else if (!QC_strcasecmp(msg, "STANDARD") || !QC_strcasecmp(msg, "ID"))
888 qcc_targetformat = QCF_STANDARD;
889 else if (!QC_strcasecmp(msg, "DEBUG"))
890 qcc_targetformat = QCF_FTEDEBUG;
891 else if (!QC_strcasecmp(msg, "QTEST"))
892 qcc_targetformat = QCF_QTEST;
894 QCC_PR_ParseWarning(WARN_BADTARGET, "Unknown target \'%s\'. Ignored.", msg);
896 else if (!QC_strcasecmp(qcc_token, "PROGS_SRC"))
897 { //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
899 else if (!QC_strcasecmp(qcc_token, "PROGS_DAT"))
900 { //doesn't make sence, but silenced if you are switching between using a certain precompiler app used with CuTF.
901 extern char destfile[1024];
903 extern char qccmfilename[1024];
912 if (!strncmp(s2, "./", 2))
916 while(!strncmp(s2, "../", 3))
922 strcpy(qccmfilename, qccmsourcedir);
923 for (s=qccmfilename+strlen(qccmfilename);p && s>=qccmfilename; s--)
925 if (*s == '/' || *s == '\\')
931 sprintf(destfile, "%s", s2);
935 memmove(destfile+3, destfile, strlen(destfile)+1);
943 strcpy(destfile, qcc_token);
945 printf("Outputfile: %s\n", destfile);
947 else if (!QC_strcasecmp(qcc_token, "keyword") || !QC_strcasecmp(qcc_token, "flag"))
951 s = QCC_COM_Parse(msg);
952 if (!QC_strcasecmp(qcc_token, "enable") || !QC_strcasecmp(qcc_token, "on"))
954 else if (!QC_strcasecmp(qcc_token, "disable") || !QC_strcasecmp(qcc_token, "off"))
958 QCC_PR_ParseWarning(WARN_BADPRAGMA, "compiler flag state not recognised");
962 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
966 s = QCC_COM_Parse(s);
968 for (f = 0; compiler_flag[f].enabled; f++)
970 if (!QC_strcasecmp(compiler_flag[f].abbrev, qcc_token))
972 if (compiler_flag[f].flags & FLAG_MIDCOMPILE)
973 *compiler_flag[f].enabled = st;
975 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Cannot enable/disable keyword/flag via a pragma");
979 if (!compiler_flag[f].enabled)
980 QCC_PR_ParseWarning(WARN_BADPRAGMA, "keyword/flag not recognised");
984 else if (!QC_strcasecmp(qcc_token, "warning"))
988 s = QCC_COM_Parse(msg);
989 if (!stricmp(qcc_token, "enable") || !stricmp(qcc_token, "on"))
991 else if (!stricmp(qcc_token, "disable") || !stricmp(qcc_token, "off"))
993 else if (!stricmp(qcc_token, "toggle"))
997 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning state not recognised");
1003 s = QCC_COM_Parse(s);
1004 wn = QCC_WarningForName(qcc_token);
1006 QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
1009 if (st == 2) //toggle
1010 qccwarningdisabled[wn] = true - qccwarningdisabled[wn];
1012 qccwarningdisabled[wn] = st;
1017 QCC_PR_ParseWarning(WARN_BADPRAGMA, "Unknown pragma \'%s\'", qcc_token);
1029 Call at start of file and when *pr_file_p == '\n'
1032 void QCC_PR_NewLine (pbool incomment)
1035 pr_line_start = pr_file_p;
1036 while(*pr_file_p==' ' || *pr_file_p == '\t')
1038 if (incomment) //no constants if in a comment.
1041 else if (QCC_PR_Precompiler())
1046 // PR_PrintNextLine ();
1053 Parses a quoted string
1057 void QCC_PR_LexString (void)
1067 bool fromfile = true;
1074 QCC_COM_Parse(text);
1075 // print("Next token is \"%s\"\n", com_token);
1079 if (fromfile) pr_file_p++;
1084 if (fromfile) pr_file_p++;
1086 QCC_PR_ParseError ("EOF inside quote");
1088 QCC_PR_ParseError ("newline inside quote");
1092 if (fromfile) pr_file_p++;
1094 QCC_PR_ParseError ("EOF inside quote");
1102 QCC_PR_ParseError ("Unknown escape char");
1106 if (fromfile) pr_file_p++;
1113 // if (fromfile) pr_file_p++;
1115 pr_immediate_type=NULL;
1116 oldline=pr_source_line;
1119 if (pr_immediate_type == &type_string)
1121 // print("Appending \"%s\" to \"%s\"\n", pr_immediate_string, tmpbuf);
1122 strcat(tmpbuf, pr_immediate_string);
1123 len+=strlen(pr_immediate_string);
1127 pr_source_line = oldline;
1129 QCC_PR_LexWhitespace();
1130 if (*pr_file_p != '\"') //annother string
1134 QCC_PR_LexWhitespace();
1139 strcpy(pr_token, tmpbuf);
1140 pr_token_type = tt_immediate;
1141 pr_immediate_type = &type_string;
1142 strcpy (pr_immediate_string, pr_token);
1144 // print("Found \"%s\"\n", pr_immediate_string);
1147 void QCC_PR_LexString (void)
1161 QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1163 QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "newline inside quote");
1168 QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
1183 else if (c == 's' || c == 'b')
1196 while ((d = *pr_file_p++) != '}')
1198 c = c * 10 + d - '0';
1199 if (d < '0' || d > '9' || c > 255)
1200 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1209 else if (c == 'x' || c == 'X')
1214 d = (unsigned char)*pr_file_p++;
1215 if (d >= '0' && d <= '9')
1217 else if (d >= 'A' && d <= 'F')
1219 else if (d >= 'a' && d <= 'f')
1222 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1226 d = (unsigned char)*pr_file_p++;
1227 if (d >= '0' && d <= '9')
1229 else if (d >= 'A' && d <= 'F')
1231 else if (d >= 'a' && d <= 'f')
1234 QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code");
1240 else if (c >= '0' && c <= '9')
1246 QCC_PR_ParseWarning(WARN_HANGINGSLASHR, "Hanging \\\\\r");
1254 QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "Unknown escape char %c", c);
1258 if (len >= sizeof(pr_immediate_string)-1)
1259 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
1261 while(*pr_file_p && *pr_file_p <= ' ')
1263 if (*pr_file_p == '\n')
1266 QCC_PR_NewLine(false);
1271 if (*pr_file_p == '\"') //have annother go
1277 pr_token_type = tt_immediate;
1278 pr_immediate_type = type_string;
1279 strcpy (pr_immediate_string, pr_token);
1284 for (end = pr_file_p; ; end++)
1316 cnst = QCC_PR_CheakCompConstString(pr_file_p);
1317 if (cnst==pr_file_p)
1323 QCC_PR_ParseWarning(WARN_MACROINSTRING, "Macro expansion in string");
1325 if (len+strlen(cnst) >= sizeof(pr_token)-1)
1326 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1328 strcpy(pr_token+len, cnst);
1334 else if (c == 0x7C && flag_acc) //reacc support... reacc is strange.
1341 if (len >= sizeof(pr_token)-1)
1342 QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
1352 int QCC_PR_LexInteger (void)
1359 if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1364 c = *(pr_file_p+=2);
1372 } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.') || (c>='a' && c <= 'f'));
1374 return atoi (pr_token);
1377 void QCC_PR_LexNumber (void)
1384 if (*pr_file_p == '-')
1389 pr_token[tokenlen++] = '-';
1391 if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
1396 pr_token[tokenlen++] = '0';
1397 pr_token[tokenlen++] = 'x';
1400 pr_immediate_type = NULL;
1401 //assume base 10 if not stated
1405 while((c = *pr_file_p))
1407 if (c >= '0' && c <= '9')
1409 pr_token[tokenlen++] = c;
1413 else if (c >= 'a' && c <= 'f' && base > 10)
1415 pr_token[tokenlen++] = c;
1419 else if (c >= 'A' && c <= 'F' && base > 10)
1421 pr_token[tokenlen++] = c;
1425 else if (c == '.' && pr_file_p[1]!='.')
1427 pr_token[tokenlen++] = c;
1429 pr_immediate_type = type_float;
1433 if (c >= '0' && c <= '9')
1435 pr_token[tokenlen++] = c;
1448 pr_token[tokenlen++] = 0;
1449 pr_immediate._float = (float)atof(pr_token);
1454 pr_token[tokenlen++] = c;
1455 pr_token[tokenlen++] = 0;
1457 pr_immediate_type = type_float;
1458 pr_immediate._float = num*sign;
1463 pr_token[tokenlen++] = c;
1464 pr_token[tokenlen++] = 0;
1466 pr_immediate_type = type_integer;
1467 pr_immediate._int = num*sign;
1474 pr_token[tokenlen++] = 0;
1476 if (!pr_immediate_type)
1478 if (flag_assume_integer)
1479 pr_immediate_type = type_integer;
1481 pr_immediate_type = type_float;
1484 if (pr_immediate_type == type_integer)
1486 pr_immediate_type = type_integer;
1487 pr_immediate._int = num*sign;
1491 pr_immediate_type = type_float;
1492 // at this point, we know there's no . in it, so the NaN bug shouldn't happen
1493 // and we cannot use atof on tokens like 0xabc, so use num*sign, it SHOULD be safe
1494 //pr_immediate._float = atof(pr_token);
1495 pr_immediate._float = (float)(num*sign);
1500 float QCC_PR_LexFloat (void)
1513 } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.')); //only allow a . if the next isn't too...
1514 if (*pr_file_p == 'f')
1517 return (float)atof (pr_token);
1524 Parses a single quoted vector
1527 void QCC_PR_LexVector (void)
1533 if (*pr_file_p == '\\')
1534 {//extended character constant
1535 pr_token_type = tt_immediate;
1536 pr_immediate_type = type_float;
1541 pr_immediate._float = '\n';
1544 pr_immediate._float = '\r';
1547 pr_immediate._float = '\t';
1550 pr_immediate._float = '\'';
1553 pr_immediate._float = '\"';
1556 pr_immediate._float = '\\';
1559 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
1562 if (*pr_file_p != '\'')
1563 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant");
1567 if (pr_file_p[1] == '\'')
1568 {//character constant
1569 pr_token_type = tt_immediate;
1570 pr_immediate_type = type_float;
1571 pr_immediate._float = pr_file_p[0];
1575 pr_token_type = tt_immediate;
1576 pr_immediate_type = type_vector;
1577 QCC_PR_LexWhitespace ();
1578 for (i=0 ; i<3 ; i++)
1580 pr_immediate.vector[i] = QCC_PR_LexFloat ();
1581 QCC_PR_LexWhitespace ();
1583 if (*pr_file_p == '\'' && i == 1)
1586 QCC_PR_ParseWarning (WARN_FTE_SPECIFIC, "Bad vector");
1588 for (i++ ; i<3 ; i++)
1589 pr_immediate.vector[i] = 0;
1593 if (*pr_file_p != '\'')
1594 QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad vector");
1602 Parses an identifier
1605 void QCC_PR_LexName (void)
1618 } while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
1619 || (c >= '0' && c <= '9'));
1622 pr_token_type = tt_name;
1630 void QCC_PR_LexPunctuation (void)
1636 pr_token_type = tt_punct;
1638 for (i=0 ; (p = pr_punctuation[i]) != NULL ; i++)
1641 if (!strncmp(p, pr_file_p, len) )
1643 strcpy (pr_token, pr_punctuationremap[i]);
1646 else if (p[0] == '}')
1653 QCC_PR_ParseError (ERR_UNKNOWNPUCTUATION, "Unknown punctuation");
1662 void QCC_PR_LexWhitespace (void)
1669 while ( (c = *pr_file_p) <= ' ')
1674 QCC_PR_NewLine (false);
1681 return; // end of file
1687 if (c=='/' && pr_file_p[1] == '/')
1689 while (*pr_file_p && *pr_file_p != '\n')
1692 if (*pr_file_p == '\n')
1693 pr_file_p++; //don't break on eof.
1694 QCC_PR_NewLine(false);
1698 // skip /* */ comments
1699 if (c=='/' && pr_file_p[1] == '*')
1704 if (pr_file_p[0]=='\n')
1706 QCC_PR_NewLine(true);
1708 if (pr_file_p[1] == 0)
1710 QCC_PR_ParseError(0, "EOF inside comment\n");
1715 } while (pr_file_p[0] != '*' || pr_file_p[1] != '/');
1720 break; // a real character has been found
1724 //============================================================================
1726 #define MAX_FRAMES 8192
1727 char pr_framemodelname[64];
1728 char pr_framemacros[MAX_FRAMES][64];
1729 int pr_framemacrovalue[MAX_FRAMES];
1730 int pr_nummacros, pr_oldmacros;
1734 void QCC_PR_ClearGrabMacros (void)
1736 pr_oldmacros = pr_nummacros;
1737 // pr_nummacros = 0;
1742 int QCC_PR_FindMacro (char *name)
1746 for (i=pr_nummacros-1 ; i>=0 ; i--)
1748 if (!STRCMP (name, pr_framemacros[i]))
1750 return pr_framemacrovalue[i];
1753 for (i=pr_nummacros-1 ; i>=0 ; i--)
1755 if (!stricmp (name, pr_framemacros[i]))
1757 QCC_PR_ParseWarning(WARN_CASEINSENSATIVEFRAMEMACRO, "Case insensative frame macro");
1758 return pr_framemacrovalue[i];
1764 void QCC_PR_ExpandMacro(void)
1766 int i = QCC_PR_FindMacro(pr_token);
1769 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "Unknown frame macro $%s", pr_token);
1771 sprintf (pr_token,"%d", i);
1772 pr_token_type = tt_immediate;
1773 pr_immediate_type = type_float;
1774 pr_immediate._float = (float)i;
1777 // just parses text, returning false if an eol is reached
1778 pbool QCC_PR_SimpleGetToken (void)
1786 while ( (c = *pr_file_p) <= ' ')
1788 if (c=='\n' || c == 0)
1792 if (pr_file_p[0] == '/')
1794 if (pr_file_p[1] == '/')
1796 while(*pr_file_p && *pr_file_p != '\n')
1800 if (pr_file_p[1] == '*')
1805 while ( (c = *pr_file_p) > ' ' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']')
1815 pbool QCC_PR_LexMacroName(void)
1823 while ( (c = *pr_file_p) <= ' ')
1825 if (c=='\n' || c == 0)
1829 if (pr_file_p[0] == '/')
1831 if (pr_file_p[1] == '/')
1833 while(*pr_file_p && *pr_file_p != '\n')
1837 if (pr_file_p[1] == '*')
1842 while ( (c = *pr_file_p) > ' ' && c != '\n' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']' && !(pr_file_p[0] == '.' && pr_file_p[1] == '.'))
1852 void QCC_PR_MacroFrame(char *name, int value)
1855 for (i=pr_nummacros-1 ; i>=0 ; i--)
1857 if (!STRCMP (name, pr_framemacros[i]))
1859 pr_framemacrovalue[i] = value;
1860 if (i>=pr_oldmacros)
1861 QCC_PR_ParseWarning(WARN_DUPLICATEMACRO, "Duplicate macro defined (%s)", pr_token);
1862 //else it's from an old file, and shouldn't be mentioned.
1867 if (strlen(name)+1 > sizeof(pr_framemacros[0]))
1868 QCC_PR_ParseWarning(ERR_TOOMANYFRAMEMACROS, "Name for frame macro %s is too long", name);
1871 strcpy (pr_framemacros[pr_nummacros], name);
1872 pr_framemacrovalue[pr_nummacros] = value;
1874 if (pr_nummacros >= MAX_FRAMES)
1875 QCC_PR_ParseError(ERR_TOOMANYFRAMEMACROS, "Too many frame macros defined");
1879 void QCC_PR_ParseFrame (void)
1881 while (QCC_PR_LexMacroName ())
1883 QCC_PR_MacroFrame(pr_token, pr_macrovalue++);
1891 Deals with counting sequence numbers and replacing frame macros
1894 void QCC_PR_LexGrab (void)
1896 pr_file_p++; // skip the $
1897 // if (!QCC_PR_SimpleGetToken ())
1898 // QCC_PR_ParseError ("hanging $");
1899 if (*pr_file_p <= ' ')
1900 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
1901 QCC_PR_LexMacroName();
1903 QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
1906 if (!STRCMP (pr_token, "frame") || !STRCMP (pr_token, "framesave"))
1908 QCC_PR_ParseFrame ();
1911 // ignore other known $commands - just for model/spritegen
1912 else if (!STRCMP (pr_token, "cd")
1913 || !STRCMP (pr_token, "origin")
1914 || !STRCMP (pr_token, "base")
1915 || !STRCMP (pr_token, "flags")
1916 || !STRCMP (pr_token, "scale")
1917 || !STRCMP (pr_token, "skin") )
1918 { // skip to end of line
1919 while (QCC_PR_LexMacroName ())
1923 else if (!STRCMP (pr_token, "flush"))
1925 QCC_PR_ClearGrabMacros();
1926 while (QCC_PR_LexMacroName ())
1930 else if (!STRCMP (pr_token, "framevalue"))
1932 QCC_PR_LexMacroName ();
1933 pr_macrovalue = atoi(pr_token);
1937 else if (!STRCMP (pr_token, "framerestore"))
1939 QCC_PR_LexMacroName ();
1940 QCC_PR_ExpandMacro();
1941 pr_macrovalue = (int)pr_immediate._float;
1945 else if (!STRCMP (pr_token, "modelname"))
1948 QCC_PR_LexMacroName ();
1950 if (*pr_framemodelname)
1951 QCC_PR_MacroFrame(pr_framemodelname, pr_macrovalue);
1953 strncpy(pr_framemodelname, pr_token, sizeof(pr_framemodelname)-1);
1954 pr_framemodelname[sizeof(pr_framemodelname)-1] = '\0';
1956 i = QCC_PR_FindMacro(pr_framemodelname);
1964 // look for a frame name macro
1966 QCC_PR_ExpandMacro ();
1969 //===========================
1970 //compiler constants - dmw
1972 pbool QCC_PR_UndefineName(char *name)
1975 CompilerConstant_t *c;
1976 c = pHash_Get(&compconstantstable, name);
1979 QCC_PR_ParseWarning(WARN_UNDEFNOTDEFINED, "Precompiler constant %s was not defined", name);
1983 Hash_Remove(&compconstantstable, name);
1987 CompilerConstant_t *QCC_PR_DefineName(char *name)
1990 CompilerConstant_t *cnst;
1992 // if (numCompilerConstants >= MAX_CONSTANTS)
1993 // QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS);
1995 if (strlen(name) >= MAXCONSTANTNAMELENGTH || !*name)
1996 QCC_PR_ParseError(ERR_NAMETOOLONG, "Compiler constant name length is too long or short");
1998 cnst = pHash_Get(&compconstantstable, name);
2001 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "Duplicate definition for Precompiler constant %s", name);
2002 Hash_Remove(&compconstantstable, name);
2005 cnst = qccHunkAlloc(sizeof(CompilerConstant_t));
2008 cnst->numparams = 0;
2009 strcpy(cnst->name, name);
2010 cnst->namelen = strlen(name);
2011 cnst->value = cnst->name + strlen(cnst->name);
2012 for (i = 0; i < MAXCONSTANTPARAMS; i++)
2013 cnst->params[i][0] = '\0';
2015 pHash_Add(&compconstantstable, cnst->name, cnst, qccHunkAlloc(sizeof(bucket_t)));
2020 void QCC_PR_Undefine(void)
2022 QCC_PR_SimpleGetToken ();
2024 QCC_PR_UndefineName(pr_token);
2025 // QCC_PR_ParseError("%s was not defined.", pr_token);
2028 void QCC_PR_ConditionCompilation(void)
2036 CompilerConstant_t *cnst;
2038 QCC_PR_SimpleGetToken ();
2040 if (!QCC_PR_SimpleGetToken ())
2041 QCC_PR_ParseError(ERR_NONAME, "No name defined for compiler constant");
2043 cnst = pHash_Get(&compconstantstable, pr_token);
2046 oldval = cnst->value;
2047 Hash_Remove(&compconstantstable, pr_token);
2052 cnst = QCC_PR_DefineName(pr_token);
2054 if (*pr_file_p == '(')
2059 if (*pr_file_p == ',')
2061 if (cnst->numparams >= MAXCONSTANTPARAMS)
2062 QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
2063 strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
2064 cnst->params[cnst->numparams][pr_file_p-s] = '\0';
2069 if (*pr_file_p == ')')
2071 if (cnst->numparams >= MAXCONSTANTPARAMS)
2072 QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
2073 strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
2074 cnst->params[cnst->numparams][pr_file_p-s] = '\0';
2081 else cnst->numparams = -1;
2086 while(*s == ' ' || *s == '\t')
2090 if ((d - dbuf) + 2 >= dbuflen)
2093 dbuflen = (len+128) * 2;
2094 dbuf = qccHunkAlloc(dbuflen);
2095 memcpy(dbuf, d - len, len);
2101 // read over a newline if necessary
2102 if( s[1] == '\n' || s[1] == '\r' )
2105 QCC_PR_NewLine(false);
2107 if( s[-1] == '\r' && s[0] == '\n' )
2113 else if(*s == '\r' || *s == '\n' || *s == '\0')
2118 if (!quote && s[0]=='/'&&(s[1]=='/'||s[1]=='*'))
2132 { //we always warn if it was already defined
2133 //we use different warning codes so that -Wno-mundane can be used to ignore identical redefinitions.
2134 if (strcmp(oldval, cnst->value))
2135 QCC_PR_ParseWarning(WARN_DUPLICATEPRECOMPILER, "Alternate precompiler definition of %s", pr_token);
2137 QCC_PR_ParseWarning(WARN_IDENTICALPRECOMPILER, "Identical precompiler definition of %s", pr_token);
2143 /* *buffer, *bufferlen and *buffermax should be NULL/0 at the start */
2144 static void QCC_PR_ExpandStrCat(char **buffer, int *bufferlen, int *buffermax, char *newdata, int newlen)
2146 int newmax = *bufferlen + newlen;
2147 if (newmax < *bufferlen)
2149 QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
2152 if (newmax > *buffermax)
2157 if (newmax < *bufferlen * 2)
2159 newmax = *bufferlen * 2;
2160 if (newmax < *bufferlen) /*overflowed?*/
2162 QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
2166 newbuf = realloc(*buffer, newmax);
2169 QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
2173 *buffermax = newmax;
2175 memcpy(*buffer + *bufferlen, newdata, newlen);
2176 *bufferlen += newlen;
2177 /*no null terminator, remember to cat one if required*/
2180 int QCC_PR_CheakCompConst(void)
2182 char *oldpr_file_p = pr_file_p;
2185 CompilerConstant_t *c;
2188 for (end = pr_file_p; ; end++)
2216 strncpy(pr_token, pr_file_p, end-pr_file_p);
2217 pr_token[end-pr_file_p]='\0';
2219 // printf("%s\n", pr_token);
2220 c = pHash_Get(&compconstantstable, pr_token);
2222 if (c && !c->inside)
2224 pr_file_p = oldpr_file_p+strlen(c->name);
2225 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2227 if (c->numparams>=0)
2229 if (*pr_file_p == '(')
2237 char *paramoffset[MAXCONSTANTPARAMS+1];
2242 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2247 // handle strings correctly by ignoring them
2248 if (*pr_file_p == '\"')
2252 } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
2254 if (*pr_file_p == '(')
2256 else if (!plevel && (*pr_file_p == ',' || *pr_file_p == ')'))
2258 paramoffset[param++] = start;
2259 start = pr_file_p+1;
2260 if (*pr_file_p == ')')
2268 while(*pr_file_p == ' ' || *pr_file_p == '\t')
2273 // move back by one char because we move forward by one at the end of the loop
2275 if (param == MAXCONSTANTPARAMS)
2276 QCC_PR_ParseError(ERR_TOOMANYPARAMS, "Too many parameters in macro call");
2277 } else if (*pr_file_p == ')' )
2279 else if(*pr_file_p == '\n')
2280 QCC_PR_NewLine(false);
2282 // see that *pr_file_p = '\0' up there? Must ++ BEFORE checking for !*pr_file_p
2285 QCC_PR_ParseError(ERR_EOF, "EOF on macro call");
2287 if (param < c->numparams)
2288 QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Not enough macro parameters");
2289 paramoffset[param] = start;
2295 oldpr_file_p = pr_file_p;
2296 pr_file_p = c->value;
2299 whitestart = bufferlen;
2300 starttok = pr_file_p;
2301 while(*pr_file_p <= ' ') //copy across whitespace
2307 if (starttok != pr_file_p)
2309 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, starttok, pr_file_p - starttok);
2312 if(*pr_file_p == '\"')
2314 starttok = pr_file_p;
2318 } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' );
2319 if(*pr_file_p == '\"')
2322 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, starttok, pr_file_p - starttok);
2325 else if (*pr_file_p == '#') //if you ask for #a##b you will be shot. use #a #b instead, or chain macros.
2327 if (pr_file_p[1] == '#')
2328 { //concatinate (strip out whitespace before the token)
2329 bufferlen = whitestart;
2335 pr_file_p = QCC_COM_Parse2(pr_file_p);
2339 for (p = 0; p < param; p++)
2341 if (!STRCMP(qcc_token, c->params[p]))
2343 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\"", 1);
2344 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[p], strlen(paramoffset[p]));
2345 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\"", 1);
2351 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "#", 1);
2352 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, qcc_token, strlen(qcc_token));
2353 //QCC_PR_ParseWarning(0, "Stringification ignored");
2355 continue; //already did this one
2359 pr_file_p = QCC_COM_Parse2(pr_file_p);
2363 for (p = 0; p < param; p++)
2365 if (!STRCMP(qcc_token, c->params[p]))
2367 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[p], strlen(paramoffset[p]));
2372 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, qcc_token, strlen(qcc_token));
2375 for (p = 0; p < param-1; p++)
2376 paramoffset[p][strlen(paramoffset[p])] = ',';
2377 paramoffset[p][strlen(paramoffset[p])] = ')';
2379 pr_file_p = oldpr_file_p;
2381 expandedemptymacro = true;
2384 QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\0", 1);
2385 QCC_PR_IncludeChunkEx(buffer, true, NULL, c);
2390 QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without argument list");
2395 expandedemptymacro = true;
2396 QCC_PR_IncludeChunkEx(c->value, false, NULL, c);
2403 if (!strncmp(pr_file_p, "__TIME__", 8))
2405 static char retbuf[128];
2409 strftime( retbuf, sizeof(retbuf),
2410 "\"%H:%M\"", localtime( &long_time ));
2413 QCC_PR_Lex(); //translate the macro's value
2414 pr_file_p = oldpr_file_p+8;
2418 if (!strncmp(pr_file_p, "__DATE__", 8))
2420 static char retbuf[128];
2424 strftime( retbuf, sizeof(retbuf),
2425 "\"%a %d %b %Y\"", localtime( &long_time ));
2428 QCC_PR_Lex(); //translate the macro's value
2429 pr_file_p = oldpr_file_p+8;
2433 if (!strncmp(pr_file_p, "__FILE__", 8))
2435 static char retbuf[256];
2436 sprintf(retbuf, "\"%s\"", strings + s_file);
2438 QCC_PR_Lex(); //translate the macro's value
2439 pr_file_p = oldpr_file_p+8;
2443 if (!strncmp(pr_file_p, "__LINE__", 8))
2445 static char retbuf[256];
2446 sprintf(retbuf, "\"%i\"", pr_source_line);
2448 QCC_PR_Lex(); //translate the macro's value
2449 pr_file_p = oldpr_file_p+8;
2452 if (!strncmp(pr_file_p, "__FUNC__", 8))
2454 static char retbuf[256];
2455 sprintf(retbuf, "\"%s\"",pr_scope->name);
2457 QCC_PR_Lex(); //translate the macro's value
2458 pr_file_p = oldpr_file_p+8;
2461 if (!strncmp(pr_file_p, "__NULL__", 8))
2463 static char retbuf[256];
2464 sprintf(retbuf, "0i");
2466 QCC_PR_Lex(); //translate the macro's value
2467 pr_file_p = oldpr_file_p+8;
2473 char *QCC_PR_CheakCompConstString(char *def)
2477 CompilerConstant_t *c;
2479 c = pHash_Get(&compconstantstable, def);
2483 s = QCC_PR_CheakCompConstString(c->value);
2489 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def)
2491 CompilerConstant_t *c = pHash_Get(&compconstantstable, def);
2495 //============================================================================
2501 Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
2504 void QCC_PR_Lex (void)
2512 if (QCC_PR_UnInclude())
2517 pr_token_type = tt_eof;
2521 QCC_PR_LexWhitespace ();
2525 if (QCC_PR_UnInclude())
2530 pr_token_type = tt_eof;
2538 if (QCC_PR_UnInclude())
2543 pr_token_type = tt_eof;
2547 // handle quoted strings as a unit
2550 QCC_PR_LexString ();
2554 // handle quoted vectors as a unit
2557 QCC_PR_LexVector ();
2561 // if the first character is a valid identifier, parse until a non-id
2562 // character is reached
2563 if ( c == '~' || c == '%') //let's see which one we make into an operator first... possibly both...
2565 QCC_PR_ParseWarning(0, "~ or %% prefixes to denote integers are deprecated. Please use a postfix of 'i'");
2567 pr_token_type = tt_immediate;
2568 pr_immediate_type = type_integer;
2569 pr_immediate._int = QCC_PR_LexInteger ();
2572 if ( c == '0' && pr_file_p[1] == 'x')
2574 pr_token_type = tt_immediate;
2578 if ( (c == '.'&&pr_file_p[1]!='.'&&pr_file_p[1] >='0' && pr_file_p[1] <= '9') || (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') )
2580 pr_token_type = tt_immediate;
2581 QCC_PR_LexNumber ();
2585 if (c == '#' && !(pr_file_p[1]=='-' || (pr_file_p[1]>='0' && pr_file_p[1] <='9'))) //hash and not number
2588 if (!QCC_PR_CheakCompConst())
2590 if (!QCC_PR_SimpleGetToken())
2591 strcpy(pr_token, "unknown");
2592 QCC_PR_ParseError(ERR_CONSTANTNOTDEFINED, "Explicit precompiler usage when not defined %s", pr_token);
2595 if (pr_token_type == tt_eof)
2601 if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
2603 if (flag_hashonly || !QCC_PR_CheakCompConst()) //look for a macro.
2606 if (pr_token_type == tt_eof)
2608 if (QCC_PR_UnInclude())
2613 pr_token_type = tt_eof;
2624 // parse symbol strings until a non-symbol is found
2625 QCC_PR_LexPunctuation ();
2628 //=============================================================================
2631 void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
2633 if (qccwarningdisabled[type])
2638 printf ("%s(%i) : %s is defined here\n", strings + def->s_file, def->s_line, def->name);
2640 printf ("%s:%i: %s is defined here\n", strings + def->s_file, def->s_line, def->name);
2644 void QCC_PR_PrintScope (void)
2648 if (errorscope != pr_scope)
2649 printf ("in function %s (line %i),\n", pr_scope->name, pr_scope->s_line);
2650 errorscope = pr_scope;
2655 printf ("at global scope,\n");
2659 void QCC_PR_ResetErrorScope(void)
2667 Aborts the current file load
2671 void editbadfile(char *file, int line);
2673 void VARGS QCC_PR_ParseError (int errortype, char *error, ...)
2678 va_start (argptr,error);
2679 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2683 editbadfile(strings+s_file, pr_source_line);
2686 QCC_PR_PrintScope();
2688 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2690 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2692 longjmp (pr_parse_abort, 1);
2694 void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...)
2699 va_start (argptr,error);
2700 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2704 editbadfile(strings+s_file, pr_source_line);
2706 QCC_PR_PrintScope();
2708 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2710 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2712 QCC_PR_ParsePrintDef(WARN_ERROR, def);
2714 longjmp (pr_parse_abort, 1);
2716 void VARGS QCC_PR_ParseWarning (int type, char *error, ...)
2721 if (type < ERR_PARSEERRORS && qccwarningdisabled[type])
2724 va_start (argptr,error);
2725 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2728 QCC_PR_PrintScope();
2729 if (type >= ERR_PARSEERRORS)
2732 printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
2734 printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
2740 printf ("%s(%i) : warning: %s\n", strings + s_file, pr_source_line, string);
2742 printf ("%s:%i: warning: %s\n", strings + s_file, pr_source_line, string);
2747 void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...)
2752 if (qccwarningdisabled[type])
2755 va_start (argptr,error);
2756 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2759 QCC_PR_PrintScope();
2763 printf ("%s(%i) : note: %s\n", file, line, string);
2765 printf ("%s:%i: note: %s\n", file, line, string);
2768 printf ("note: %s\n", string);
2771 pbool VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
2776 if (qccwarningdisabled[type])
2779 va_start (argptr,error);
2780 QC_vsnprintf (string,sizeof(string)-1, error,argptr);
2783 QCC_PR_PrintScope();
2787 printf ("%s(%i) : warning: %s\n", file, line, string);
2789 printf ("%s:%i: warning: %s\n", file, line, string);
2792 printf ("warning: %s\n", string);
2803 Issues an error if the current token isn't equal to string
2807 #ifndef COMMONINLINES
2808 void QCC_PR_Expect (char *string)
2810 if (STRCMP (string, pr_token))
2811 QCC_PR_ParseError (ERR_EXPECTED, "expected %s, found %s",string, pr_token);
2821 Returns true and gets the next token if the current token equals string
2822 Returns false and does nothing otherwise
2825 #ifndef COMMONINLINES
2826 pbool QCC_PR_CheckToken (char *string)
2828 if (pr_token_type != tt_punct)
2831 if (STRCMP (string, pr_token))
2838 pbool QCC_PR_CheckImmediate (char *string)
2840 if (pr_token_type != tt_immediate)
2843 if (STRCMP (string, pr_token))
2850 pbool QCC_PR_CheckName(char *string)
2852 if (pr_token_type != tt_name)
2854 if (flag_caseinsensative)
2856 if (stricmp (string, pr_token))
2861 if (STRCMP(string, pr_token))
2868 pbool QCC_PR_CheckKeyword(int keywordenabled, char *string)
2870 if (!keywordenabled)
2872 if (flag_caseinsensative)
2874 if (stricmp (string, pr_token))
2879 if (STRCMP(string, pr_token))
2892 Checks to see if the current token is a valid name
2895 char *QCC_PR_ParseName (void)
2897 static char ident[MAX_NAME];
2900 if (pr_token_type != tt_name)
2902 if (pr_token_type == tt_eof)
2903 QCC_PR_ParseError (ERR_EOF, "unexpected EOF", pr_token);
2905 QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
2907 if (strlen(pr_token) >= MAX_NAME-1)
2908 QCC_PR_ParseError (ERR_NAMETOOLONG, "name too long");
2909 strcpy (ident, pr_token);
2912 ret = qccHunkAlloc(strlen(ident)+1);
2922 Returns a preexisting complex type that matches the parm, or allocates
2923 a new one and copies it out.
2928 int typecmp(QCC_type_t *a, QCC_type_t *b)
2933 return 1; //different (^ and not both null)
2935 if (a->type != b->type)
2937 if (a->num_parms != b->num_parms)
2942 if (a->size != b->size)
2944 // if (STRCMP(a->name, b->name)) //This isn't 100% clean.
2947 if (typecmp(a->aux_type, b->aux_type))
2950 if (a->param || b->param)
2968 QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in)
2970 QCC_type_t *out, *op, *ip;
2974 out = QCC_PR_NewType(in->name, in->type, false);
2975 out->aux_type = QCC_PR_DuplicateType(in->aux_type);
2976 out->param = QCC_PR_DuplicateType(in->param);
2982 out->param = op = QCC_PR_DuplicateType(ip);
2984 op = (op->next = QCC_PR_DuplicateType(ip));
2987 out->arraysize = in->arraysize;
2988 out->size = in->size;
2989 out->num_parms = in->num_parms;
2991 out->name = in->name;
2992 out->parentclass = in->parentclass;
2997 char *TypeName(QCC_type_t *type)
2999 static char buffer[2][512];
3006 if (type->type == ev_field)
3008 type = type->aux_type;
3013 if (type->type == ev_function)
3015 pbool varg = type->num_parms < 0;
3016 int args = type->num_parms;
3019 strcat(ret, type->aux_type->name);
3025 strcat(ret, "optional ");
3028 strcat(ret, type->name);
3040 else if (type->type == ev_entity && type->parentclass)
3044 strcat(ret, "class ");
3045 strcat(ret, type->name);
3046 /* strcat(ret, " {");
3050 strcat(ret, type->name);
3060 strcpy(ret, type->name);
3062 return buffer[op&1];
3064 //#define typecmp(a, b) (a && ((a)->type==(b)->type) && !STRCMP((a)->name, (b)->name))
3066 QCC_type_t *QCC_PR_FindType (QCC_type_t *type)
3069 for (t = 0; t < numtypeinfos; t++)
3071 // check = &qcc_typeinfo[t];
3072 if (typecmp(&qcc_typeinfo[t], type))
3076 // c2 = check->next;
3078 // for (i=0 ; n2&&c2 ; i++)
3080 // if (!typecmp((c2), (n2)))
3086 // if (n2==NULL&&c2==NULL)
3088 return &qcc_typeinfo[t];
3091 QCC_Error(ERR_INTERNAL, "Error with type");
3096 QCC_type_t *QCC_PR_NextSubType(QCC_type_t *type, QCC_type_t *prev)
3102 for (p = prev->num_parms; p; p--)
3103 prev = QCC_PR_NextSubType(prev, NULL);
3104 if (prev->num_parms)
3116 QCC_type_t *QCC_TypeForName(char *name)
3120 for (i = 0; i < numtypeinfos; i++)
3122 if (!STRCMP(qcc_typeinfo[i].name, name))
3124 return &qcc_typeinfo[i];
3135 For error recovery, also pops out of nested braces
3138 void QCC_PR_SkipToSemicolon (void)
3142 if (!pr_bracelevel && QCC_PR_CheckToken (";"))
3145 } while (pr_token_type != tt_eof);
3153 Parses a variable type, including field and functions types
3156 #ifdef MAX_EXTRA_PARMS
3157 char pr_parm_names[MAX_PARMS+MAX_EXTRA_PARMS][MAX_NAME];
3159 char pr_parm_names[MAX_PARMS][MAX_NAME];
3162 pbool recursivefunctiontype;
3164 //expects a ( to have already been parsed.
3165 QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
3167 QCC_type_t *ftype, *ptype, *nptype;
3169 int definenames = !recursivefunctiontype;
3173 recursivefunctiontype++;
3175 ftype = QCC_PR_NewType(type_function->name, ev_function, false);
3177 ftype->aux_type = returntype; // return type
3178 ftype->num_parms = 0;
3182 if (!QCC_PR_CheckToken (")"))
3184 if (QCC_PR_CheckToken ("..."))
3185 ftype->num_parms = -1; // variable args
3189 if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
3190 QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS);
3192 if (QCC_PR_CheckToken ("..."))
3195 numparms = optional-1;
3196 ftype->num_parms = (numparms * -1) - 1;
3200 if (QCC_PR_CheckKeyword(keyword_optional, "optional"))
3203 optional = numparms+1;
3206 QCC_PR_ParseWarning(WARN_MISSINGOPTIONAL, "optional not specified on all optional args\n");
3208 nptype = QCC_PR_ParseType(true, false);
3210 if (nptype->type == ev_void)
3215 ftype->param = ptype;
3219 ptype->next = nptype;
3220 ptype = ptype->next;
3222 // type->name = "FUNC PARAMETER";
3225 if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")"))
3227 name = QCC_PR_ParseName ();
3229 strcpy (pr_parm_names[numparms], name);
3231 else if (definenames)
3232 strcpy (pr_parm_names[numparms], "");
3235 ftype->num_parms = optional-1;
3237 ftype->num_parms = numparms;
3238 } while (QCC_PR_CheckToken (","));
3240 QCC_PR_Expect (")");
3242 recursivefunctiontype--;
3245 return QCC_PR_FindType (ftype);
3247 QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
3249 QCC_type_t *ftype, *ptype, *nptype;
3252 int definenames = !recursivefunctiontype;
3254 recursivefunctiontype++;
3256 ftype = QCC_PR_NewType(type_function->name, ev_function, false);
3258 ftype->aux_type = returntype; // return type
3259 ftype->num_parms = 0;
3263 if (!QCC_PR_CheckToken (")"))
3265 if (QCC_PR_CheckToken ("..."))
3266 ftype->num_parms = -1; // variable args
3270 if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
3271 QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS);
3273 if (QCC_PR_CheckToken ("..."))
3275 ftype->num_parms = (ftype->num_parms * -1) - 1;
3279 if (QCC_PR_CheckName("arg"))
3281 sprintf(argname, "arg%i", ftype->num_parms);
3283 nptype = QCC_PR_NewType("Variant", ev_variant, false);
3285 else if (QCC_PR_CheckName("vect")) //this can only be of vector sizes, so...
3287 sprintf(argname, "arg%i", ftype->num_parms);
3289 nptype = QCC_PR_NewType("Vector", ev_vector, false);
3293 name = QCC_PR_ParseName();
3295 nptype = QCC_PR_ParseType(true, false);
3298 if (nptype->type == ev_void)
3303 ftype->param = ptype;
3307 ptype->next = nptype;
3308 ptype = ptype->next;
3310 // type->name = "FUNC PARAMETER";
3313 strcpy (pr_parm_names[ftype->num_parms], name);
3315 } while (QCC_PR_CheckToken (";"));
3317 QCC_PR_Expect (")");
3319 recursivefunctiontype--;
3322 return QCC_PR_FindType (ftype);
3324 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
3326 QCC_type_t *ptype, *e;
3327 ptype = QCC_PR_NewType("ptr", ev_pointer, false);
3328 ptype->aux_type = pointsto;
3329 e = QCC_PR_FindType (ptype);
3333 sprintf(name, "ptr to %s", pointsto->name);
3334 e->name = strdup(name);
3338 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
3342 sprintf(name, "FIELD TYPE(%s)", pointsto->name);
3343 ptype = QCC_PR_NewType(name, ev_field, false);
3344 ptype->aux_type = pointsto;
3345 ptype->size = ptype->aux_type->size;
3346 return QCC_PR_FindType (ptype);
3349 pbool type_inlinefunction;
3350 /*newtype=true: creates a new type always
3351 silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL
3353 QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
3355 QCC_type_t *newparm;
3361 type_inlinefunction = false; //doesn't really matter so long as its not from an inline function type
3365 if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges)
3367 newt = QCC_PR_NewType("FIELD TYPE", ev_field, false);
3368 newt->aux_type = QCC_PR_ParseType (false, false);
3370 newt->size = newt->aux_type->size;
3372 newt = QCC_PR_FindType (newt);
3374 type = QCC_PR_NewType("FIELD TYPE", ev_field, false);
3375 type->aux_type = newt;
3377 type->size = type->aux_type->size;
3381 return QCC_PR_FindType (type);
3383 if (QCC_PR_CheckToken ("."))
3385 newt = QCC_PR_NewType("FIELD TYPE", ev_field, false);
3386 newt->aux_type = QCC_PR_ParseType (false, false);
3388 newt->size = newt->aux_type->size;
3392 return QCC_PR_FindType (newt);
3395 name = QCC_PR_CheakCompConstString(pr_token);
3397 if (QCC_PR_CheckKeyword (keyword_class, "class"))
3400 QCC_type_t *fieldtype;
3401 char membername[2048];
3402 char *classname = QCC_PR_ParseName();
3403 int forwarddeclaration;
3407 /* Don't advance the line number yet */
3408 forwarddeclaration = pr_token[0] == ';';
3410 /* Look to see if this type is already defined */
3411 for(i=0;i<numtypeinfos;i++)
3413 if (!qcc_typeinfo[i].typedefed)
3415 if (STRCMP(qcc_typeinfo[i].name, classname) == 0)
3417 newt = &qcc_typeinfo[i];
3422 if (newt && forwarddeclaration)
3423 QCC_PR_ParseError(ERR_REDECLARATION, "Forward declaration of already defined class %s", classname);
3425 if (newt && newt->num_parms != 0)
3426 QCC_PR_ParseError(ERR_REDECLARATION, "Redeclaration of class %s", classname);
3429 newt = QCC_PR_NewType(classname, ev_entity, true);
3431 newt->size=type_entity->size;
3435 if (forwarddeclaration)
3437 QCC_PR_CheckToken(";");
3443 if (QCC_PR_CheckToken(":"))
3445 char *parentname = QCC_PR_ParseName();
3446 newt->parentclass = QCC_TypeForName(parentname);
3447 if (!newt->parentclass)
3448 QCC_PR_ParseError(ERR_NOTANAME, "Parent class %s was not defined", parentname);
3451 newt->parentclass = type_entity;
3455 if (QCC_PR_CheckToken(","))
3456 QCC_PR_ParseError(ERR_NOTANAME, "member missing name");
3457 while (!QCC_PR_CheckToken("}"))
3459 // if (QCC_PR_CheckToken(","))
3460 // type->next = QCC_PR_NewType(type->name, type->type);
3462 newparm = QCC_PR_ParseType(true, false);
3464 if (newparm->type == ev_struct || newparm->type == ev_union) //we wouldn't be able to handle it.
3465 QCC_PR_ParseError(ERR_INTERNAL, "Struct or union in class %s", classname);
3467 if (!QCC_PR_CheckToken(";"))
3469 newparm->name = QCC_CopyString(pr_token)+strings;
3471 if (QCC_PR_CheckToken("["))
3473 type->next->size*=atoi(pr_token);
3477 QCC_PR_CheckToken(";");
3480 newparm->name = QCC_CopyString("")+strings;
3482 sprintf(membername, "%s::"MEMBERFIELDNAME, classname, newparm->name);
3483 fieldtype = QCC_PR_NewType(newparm->name, ev_field, false);
3484 fieldtype->aux_type = newparm;
3485 fieldtype->size = newparm->size;
3486 QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 0, false);
3489 newparm->ofs = 0;//newt->size;
3493 type->next = newparm;
3495 newt->param = newparm;
3504 if (QCC_PR_CheckKeyword (keyword_struct, "struct"))
3506 newt = QCC_PR_NewType("struct", ev_struct, false);
3511 if (QCC_PR_CheckToken(","))
3512 QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3515 while (!QCC_PR_CheckToken("}"))
3517 if (QCC_PR_CheckToken(","))
3520 QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3521 newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
3524 newparm = QCC_PR_ParseType(true, false);
3526 if (!QCC_PR_CheckToken(";"))
3528 newparm->name = QCC_CopyString(pr_token)+strings;
3530 if (QCC_PR_CheckToken("["))
3532 newparm->arraysize=QCC_PR_IntConstExpr();
3535 QCC_PR_CheckToken(";");
3538 newparm->name = QCC_CopyString("")+strings;
3539 newparm->ofs = newt->size;
3540 newt->size += newparm->size*(newparm->arraysize?newparm->arraysize:1);
3544 type->next = newparm;
3546 newt->param = newparm;
3551 if (QCC_PR_CheckKeyword (keyword_union, "union"))
3553 newt = QCC_PR_NewType("union", ev_union, false);
3558 if (QCC_PR_CheckToken(","))
3559 QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
3561 while (!QCC_PR_CheckToken("}"))
3564 if (QCC_PR_CheckToken(","))
3567 QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
3568 newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
3571 newparm = QCC_PR_ParseType(true, false);
3572 if (QCC_PR_CheckToken(";"))
3573 newparm->name = QCC_CopyString("")+strings;
3576 newparm->name = QCC_CopyString(pr_token)+strings;
3578 if (QCC_PR_CheckToken("["))
3580 newparm->arraysize=QCC_PR_IntConstExpr();
3586 arraysize = newparm->arraysize;
3589 if (newparm->size*arraysize > newt->size)
3590 newt->size = newparm->size*arraysize;
3594 type->next = newparm;
3596 newt->param = newparm;
3602 for (i = 0; i < numtypeinfos; i++)
3604 if (!qcc_typeinfo[i].typedefed)
3606 if (!STRCMP(qcc_typeinfo[i].name, name))
3608 type = &qcc_typeinfo[i];
3613 if (i == numtypeinfos)
3617 if (!stricmp("Void", name))
3619 else if (!stricmp("Real", name))
3621 else if (!stricmp("Vector", name))
3623 else if (!stricmp("Object", name))
3625 else if (!stricmp("String", name))
3627 else if (!stricmp("PFunc", name))
3628 type = type_function;
3634 QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name);
3635 type = type_float; // shut up compiler warning
3640 while (QCC_PR_CheckToken("*"))
3641 type = QCC_PointerTypeTo(type);
3643 if (QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function.
3645 type_inlinefunction = true;
3646 type = QCC_PR_ParseFunctionType(newtype, type);
3652 type = QCC_PR_DuplicateType(type);