5 int mkdir(const char *path);
7 char QCC_copyright[1024];
9 char QCC_Packname[5][128];
11 extern QCC_def_t *functemps; //floats/strings/funcs/ents...
13 extern int optres_test1;
14 extern int optres_test2;
17 static pbool pr_werror;
21 pbool QCC_PR_SimpleGetToken (void);
22 void QCC_PR_LexWhitespace (void);
24 void *FS_ReadToMem(char *fname, void *membuf, int *len);
25 void FS_CloseFromMem(void *mem);
27 struct qcc_includechunk_s *currentchunk;
29 unsigned int MAX_REGS;
43 #define MAXSOURCEFILESLIST 8
44 char sourcefileslist[MAXSOURCEFILESLIST][1024];
45 int currentsourcefile;
48 void QCC_PR_ResetErrorScope(void);
55 float *qcc_pr_globals;
56 unsigned int numpr_globals;
61 QCC_dstatement_t *statements;
63 int *statement_linenums;
65 QCC_dfunction_t *functions;
68 QCC_ddef_t *qcc_globals;
74 //typedef char PATHSTRING[MAX_DATA_PATH];
76 PATHSTRING *precache_sounds;
77 int *precache_sounds_block;
80 PATHSTRING *precache_textures;
81 int *precache_textures_block;
84 PATHSTRING *precache_models;
85 int *precache_models_block;
88 PATHSTRING *precache_files;
89 int *precache_files_block;
92 extern int numCompilerConstants;
93 hashtable_t compconstantstable;
94 hashtable_t globalstable;
95 hashtable_t localstable;
96 hashtable_t floatconstdefstable;
97 hashtable_t stringconstdefstable;
98 hashtable_t stringconstdefstable_dotranslate;
100 int dotranslate_count;
102 pbool qccwarningdisabled[WARN_MAX];
104 qcc_targetformat_t qcc_targetformat;
108 QCC_type_t *qcc_typeinfo;
118 {"Q302", WARN_NOTREFERENCED},
119 // {"", WARN_NOTREFERENCEDCONST},
120 // {"", WARN_CONFLICTINGRETURNS},
121 {"Q105", WARN_TOOFEWPARAMS},
122 {"Q101", WARN_TOOMANYPARAMS},
123 // {"", WARN_UNEXPECTEDPUNCT},
124 {"Q106", WARN_ASSIGNMENTTOCONSTANT},
125 {"Q203", WARN_MISSINGRETURNVALUE},
126 {"Q204", WARN_WRONGRETURNTYPE},
127 {"Q205", WARN_POINTLESSSTATEMENT},
128 {"Q206", WARN_MISSINGRETURN},
129 {"Q207", WARN_DUPLICATEDEFINITION},
130 {"Q100", WARN_PRECOMPILERMESSAGE},
131 // {"", WARN_STRINGTOOLONG},
132 // {"", WARN_BADTARGET},
133 {"Q120", WARN_BADPRAGMA},
134 // {"", WARN_HANGINGSLASHR},
135 // {"", WARN_NOTDEFINED},
136 // {"", WARN_SWITCHTYPEMISMATCH},
137 // {"", WARN_CONFLICTINGUNIONMEMBER},
138 // {"", WARN_KEYWORDDISABLED},
139 // {"", WARN_ENUMFLAGS_NOTINTEGER},
140 // {"", WARN_ENUMFLAGS_NOTBINARY},
141 // {"", WARN_CASEINSENSATIVEFRAMEMACRO},
142 {"Q111", WARN_DUPLICATELABEL},
143 {"Q201", WARN_ASSIGNMENTINCONDITIONAL},
144 {"F300", WARN_DEADCODE},
148 int QCC_WarningForName(char *name)
151 for (i = 0; warningnames[i].name; i++)
153 if (!stricmp(name, warningnames[i].name))
154 return warningnames[i].index;
159 optimisations_t optimisations[] =
161 //level 0 = no optimisations
162 //level 1 = size optimisations
163 //level 2 = speed optimisations
164 //level 3 = dodgy optimisations.
165 //level 4 = experimental...
167 {&opt_assignments, "t", 1, FLAG_ASDEFAULT, "assignments", "c = a*b is performed in one operation rather than two, and can cause older decompilers to fail."},
168 {&opt_shortenifnots, "i", 1, FLAG_ASDEFAULT, "shortenifs", "if (!a) was traditionally compiled in two statements. This optimisation does it in one, but can cause some decompilers to get confused."},
169 {&opt_nonvec_parms, "p", 1, FLAG_ASDEFAULT, "nonvec_parms", "In the original qcc, function parameters were specified as a vector store even for floats. This fixes that."},
170 {&opt_constant_names, "c", 2, FLAG_KILLSDEBUGGERS, "constant_names", "This optimisation strips out the names of constants (but not strings) from your progs, resulting in smaller files. It makes decompilers leave out names or fabricate numerical ones."},
171 {&opt_constant_names_strings, "cs", 3, FLAG_KILLSDEBUGGERS, "constant_names_strings", "This optimisation strips out the names of string constants from your progs. However, this can break addons, so don't use it in those cases."},
172 {&opt_dupconstdefs, "d", 1, FLAG_ASDEFAULT, "dupconstdefs", "This will merge definitions of constants which are the same value. Pay extra attention to assignment to constant warnings."},
173 {&opt_noduplicatestrings, "s", 1, 0, "noduplicatestrings", "This will compact the string table that is stored in the progs. It will be considerably smaller with this."},
174 {&opt_locals, "l", 1, FLAG_KILLSDEBUGGERS, "locals", "Strips out local names and definitions. This makes it REALLY hard to decompile"},
175 {&opt_function_names, "n", 1, FLAG_KILLSDEBUGGERS, "function_names", "This strips out the names of functions which are never called. Doesn't make much of an impact though."},
176 {&opt_filenames, "f", 1, FLAG_KILLSDEBUGGERS, "filenames", "This strips out the filenames of the progs. This can confuse the really old decompilers, but is nothing to the more recent ones."},
177 {&opt_unreferenced, "u", 1, FLAG_ASDEFAULT, "unreferenced", "Removes the entries of unreferenced variables. Doesn't make a difference in well maintained code."},
178 {&opt_overlaptemps, "r", 1, FLAG_ASDEFAULT, "overlaptemps", "Optimises the pr_globals count by overlapping temporaries. In QC, every multiplication, division or operation in general produces a temporary variable. This optimisation prevents excess, and in the case of Hexen2's gamecode, reduces the count by 50k. This is the most important optimisation, ever."},
179 {&opt_constantarithmatic, "a", 1, FLAG_ASDEFAULT, "constantarithmatic", "5*6 actually emits an operation into the progs. This prevents that happening, effectivly making the compiler see 30"},
180 {&opt_precache_file, "pf", 2, 0, "precache_file", "Strip out stuff wasted used in function calls and strings to the precache_file builtin (which is actually a stub in quake)."},
181 {&opt_return_only, "ro", 3, FLAG_KILLSDEBUGGERS, "return_only", "Functions ending in a return statement do not need a done statement at the end of the function. This can confuse some decompilers, making functions appear larger than they were."},
182 {&opt_compound_jumps, "cj", 3, FLAG_KILLSDEBUGGERS, "compound_jumps", "This optimisation plays an effect mostly with nested if/else statements, instead of jumping to an unconditional jump statement, it'll jump to the final destination instead. This will bewilder decompilers."},
183 // {&opt_comexprremoval, "cer", 4, 0, "expression_removal", "Eliminate common sub-expressions"}, //this would be too hard...
184 {&opt_stripfunctions, "sf", 3, 0, "strip_functions", "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games."},
185 {&opt_locals_marshalling, "lm", 4, FLAG_KILLSDEBUGGERS, "locals_marshalling", "Store all locals in one section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps. It's been noticed as buggy by a few, however, and the curcumstances where it causes problems are not yet known."},
186 {&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."},
190 #define defaultkeyword FLAG_HIDDENINGUI|FLAG_ASDEFAULT|FLAG_MIDCOMPILE
191 #define nondefaultkeyword FLAG_HIDDENINGUI|0|FLAG_MIDCOMPILE
192 //global to store useage to, flags, codename, human-readable name, help text
193 compiler_flag_t compiler_flag[] = {
195 {&keyword_asm, defaultkeyword, "asm", "Keyword: asm", "Disables the 'asm' keyword. Use the writeasm flag to see an example of the asm."},
196 {&keyword_break, defaultkeyword, "break", "Keyword: break", "Disables the 'break' keyword."},
197 {&keyword_case, defaultkeyword, "case", "Keyword: case", "Disables the 'case' keyword."},
198 {&keyword_class, defaultkeyword, "class", "Keyword: class", "Disables the 'class' keyword."},
199 {&keyword_const, defaultkeyword, "const", "Keyword: const", "Disables the 'const' keyword."},
200 {&keyword_continue, defaultkeyword, "continue", "Keyword: continue", "Disables the 'continue' keyword."},
201 {&keyword_default, defaultkeyword, "default", "Keyword: default", "Disables the 'default' keyword."},
202 {&keyword_entity, defaultkeyword, "entity", "Keyword: entity", "Disables the 'entity' keyword."},
203 {&keyword_enum, defaultkeyword, "enum", "Keyword: enum", "Disables the 'enum' keyword."}, //kinda like in c, but typedef not supported.
204 {&keyword_enumflags, defaultkeyword, "enumflags", "Keyword: enumflags", "Disables the 'enumflags' keyword."}, //like enum, but doubles instead of adds 1.
205 {&keyword_extern, defaultkeyword, "extern", "Keyword: extern", "Disables the 'extern' keyword. Use only on functions inside addons."}, //function is external, don't error or warn if the body was not found
206 {&keyword_float, defaultkeyword, "float", "Keyword: float", "Disables the 'float' keyword. (Disables the float keyword without 'local' preceeding it)"},
207 {&keyword_for, defaultkeyword, "for", "Keyword: for", "Disables the 'for' keyword. Syntax: for(assignment; while; increment) {codeblock;}"},
208 {&keyword_goto, defaultkeyword, "goto", "Keyword: goto", "Disables the 'goto' keyword."},
209 {&keyword_int, defaultkeyword, "int", "Keyword: int", "Disables the 'int' keyword."},
210 {&keyword_integer, defaultkeyword, "integer", "Keyword: integer", "Disables the 'integer' keyword."},
211 {&keyword_noref, defaultkeyword, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't strip it.
212 {&keyword_nosave, defaultkeyword, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output.
213 {&keyword_shared, defaultkeyword, "shared", "Keyword: shared", "Disables the 'shared' keyword."}, //mark global to be copied over when progs changes (part of FTE_MULTIPROGS)
214 {&keyword_state, nondefaultkeyword,"state", "Keyword: state", "Disables the 'state' keyword."},
215 {&keyword_string, defaultkeyword, "string", "Keyword: string", "Disables the 'string' keyword."},
216 {&keyword_struct, defaultkeyword, "struct", "Keyword: struct", "Disables the 'struct' keyword."},
217 {&keyword_switch, defaultkeyword, "switch", "Keyword: switch", "Disables the 'switch' keyword."},
218 {&keyword_thinktime, nondefaultkeyword,"thinktime", "Keyword: thinktime", "Disables the 'thinktime' keyword which is used in HexenC"},
219 {&keyword_typedef, defaultkeyword, "typedef", "Keyword: typedef", "Disables the 'typedef' keyword."}, //fixme
220 {&keyword_union, defaultkeyword, "union", "Keyword: union", "Disables the 'union' keyword."}, //you surly know what a union is!
221 {&keyword_var, defaultkeyword, "var", "Keyword: var", "Disables the 'var' keyword."},
222 {&keyword_vector, defaultkeyword, "vector", "Keyword: vector", "Disables the 'vector' keyword."},
226 {&keywords_coexist, FLAG_ASDEFAULT, "kce", "Keywords Coexist", "If you want keywords to NOT be disabled when they a variable by the same name is defined, check here."},
227 {&output_parms, 0, "parms", "Define offset parms", "if PARM0 PARM1 etc should be defined by the compiler. These are useful if you make use of the asm keyword for function calls, or you wish to create your own variable arguments. This is an easy way to break decompilers."}, //controls weather to define PARMx for the parms (note - this can screw over some decompilers)
228 {&autoprototype, 0, "autoproto", "Automatic Prototyping","Causes compilation to take two passes instead of one. The first pass, only the definitions are read. The second pass actually compiles your code. This means you never have to remember to prototype functions again."}, //so you no longer need to prototype functions and things in advance.
229 {&writeasm, 0, "wasm", "Dump Assembler", "Writes out a qc.asm which contains all your functions but in assembler. This is a great way to look for bugs in fteqcc, but can also be used to see exactly what your functions turn into, and thus how to optimise statements better."}, //spit out a qc.asm file, containing an assembler dump of the ENTIRE progs. (Doesn't include initialisation of constants)
230 {&flag_ifstring, FLAG_MIDCOMPILE,"ifstring", "if(string) fix", "Causes if(string) to behave identically to if(string!="") This is most useful with addons of course, but also has adverse effects with FRIK_FILE's fgets, where it becomes impossible to determin the end of the file. In such a case, you can still use asm {IF string 2;RETURN} to detect eof and leave the function."}, //correction for if(string) no-ifstring to get the standard behaviour.
231 {&flag_iffloat, FLAG_MIDCOMPILE,"iffloat","if(-0.0) fix","Fixes certain floating point logic."},
232 {&flag_acc, 0, "acc", "Reacc support", "Reacc is a pascall like compiler. It was released before the Quake source was released. This flag has a few effects. It sorts all qc files in the current directory into alphabetical order to compile them. It also allows Reacc global/field distinctions, as well as allows ¦ as EOF. Whilst case insensativity and lax type checking are supported by reacc, they are seperate compiler flags in fteqcc."}, //reacc like behaviour of src files.
233 {&flag_caseinsensative, 0, "caseinsens", "Case insensativity", "Causes fteqcc to become case insensative whilst compiling names. It's generally not advised to use this as it compiles a little more slowly and provides little benefit. However, it is required for full reacc support."}, //symbols will be matched to an insensative case if the specified case doesn't exist. This should b usable for any mod
234 {&flag_laxcasts, FLAG_MIDCOMPILE,"lax", "Lax type checks", "Disables many errors (generating warnings instead) when function calls or operations refer to two normally incompatible types. This is required for reacc support, and can also allow certain (evil) mods to compile that were originally written for frikqcc."}, //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code.
235 {&flag_hashonly, FLAG_MIDCOMPILE,"hashonly", "Hash-only constants", "Allows use of only #constant for precompiler constants, allows certain preqcc using mods to compile"},
236 {&opt_logicops, FLAG_MIDCOMPILE,"lo", "Logic ops", "This changes the behaviour of your code. It generates additional if operations to early-out in if statements. With this flag, the line if (0 && somefunction()) will never call the function. It can thus be considered an optimisation. However, due to the change of behaviour, it is not considered so by fteqcc. Note that due to inprecisions with floats, this flag can cause runaway loop errors within the player walk and run functions (without iffloat also enabled). This code is advised:\nplayer_stand1:\n if (self.velocity_x || self.velocity_y)\nplayer_run\n if (!(self.velocity_x || self.velocity_y))"},
237 {&flag_msvcstyle, FLAG_MIDCOMPILE,"msvcstyle", "MSVC-style errors", "Generates warning and error messages in a format that msvc understands, to facilitate ide integration."},
238 {&flag_fasttrackarrays, FLAG_MIDCOMPILE|FLAG_ASDEFAULT,"fastarrays","fast arrays where possible", "Generates extra instructions inside array handling functions to detect engine and use extension opcodes only in supporting engines.\nAdds a global which is set by the engine if the engine supports the extra opcodes. Note that this applies to all arrays or none."},
239 {&flag_assume_integer, FLAG_MIDCOMPILE,"assumeint", "Assume Integers", "Numerical constants are assumed to be integers, instead of floats."},
240 {&pr_subscopedlocals, FLAG_MIDCOMPILE,"subscope", "Subscoped locals", "Allow locals to only be valid in the block they are defined in (like in C)."},
245 qcc_targetformat_t target;
248 {QCF_STANDARD, "standard"},
249 {QCF_STANDARD, "q1"},
250 {QCF_STANDARD, "quakec"},
251 {QCF_HEXEN2, "hexen2"},
255 {QCF_KK7, "bigprogs"},
256 {QCF_KK7, "version7"},
259 {QCF_DARKPLACES,"darkplaces"},
260 {QCF_DARKPLACES,"dp"},
268 Runs qbsp and light on all of the models with a .bsp extension
271 int QCC_CheckParm (char *check);
273 void QCC_BspModels (void)
282 p = QCC_CheckParm ("-bspmodels");
286 QCC_Error (ERR_BADPARMS, "-bspmodels must preceed a game directory");
287 gamedir = myargv[p+1];
289 for (i=0 ; i<nummodels ; i++)
291 m = precache_models[i];
292 if (strcmp(m+strlen(m)-4, ".bsp"))
295 name[strlen(m)-4] = 0;
296 sprintf (cmd, "qbsp %s/%s ; light -extra %s/%s", gamedir, name, gamedir, name);
301 // CopyString returns an offset from the string heap
302 int QCC_CopyString (char *str)
307 if (opt_noduplicatestrings)
312 for (s = strings; s < strings+strofs; s++)
315 optres_noduplicatestrings += strlen(str);
321 strcpy (strings+strofs, str);
322 strofs += strlen(str)+1;
326 int QCC_CopyDupBackString (char *str)
331 for (s = strings+strofs-1; s>strings ; s--)
336 strcpy (strings+strofs, str);
337 strofs += strlen(str)+1;
341 void QCC_PrintStrings (void)
345 for (i=0 ; i<strofs ; i += l)
347 l = strlen(strings+i) + 1;
349 for (j=0 ; j<l ; j++)
351 if (strings[i+j] == '\n')
357 putchar (strings[i+j]);
364 /*void QCC_PrintFunctions (void)
369 for (i=0 ; i<numfunctions ; i++)
372 printf ("%s : %s : %i %i (", strings + d->s_file, strings + d->s_name, d->first_statement, d->parm_start);
373 for (j=0 ; j<d->numparms ; j++)
374 printf ("%i ",d->parm_size[j]);
379 void QCC_PrintFields (void)
384 for (i=0 ; i<numfielddefs ; i++)
387 printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
391 void QCC_PrintGlobals (void)
396 for (i=0 ; i<numglobaldefs ; i++)
399 printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
403 int encode(int len, int method, char *in, int handle);
404 int WriteSourceFiles(int h, dprograms_t *progs, pbool sourceaswell)
406 includeddatafile_t *idf;
407 qcc_cachedsourcefile_t *f;
412 for (f = qcc_sourcefile; f ; f=f->next)
414 if (f->type == FT_CODE && !sourceaswell)
417 SafeWrite(h, f->filename, strlen(f->filename)+1);
418 i = PRLittleLong(f->size);
419 SafeWrite(h, &i, sizeof(int));
421 i = PRLittleLong(encrpytmode);
422 SafeWrite(h, &i, sizeof(int));
425 for (i = 0; i < f->size; i++)
428 SafeWrite(h, f->file, f->size);
431 for (f = qcc_sourcefile,num=0; f ; f=f->next)
433 if (f->type == FT_CODE && !sourceaswell)
440 idf = qccHunkAlloc(sizeof(includeddatafile_t)*num);
441 for (f = qcc_sourcefile,num=0; f ; f=f->next)
443 if (f->type == FT_CODE && !sourceaswell)
446 strcpy(idf[num].filename, f->filename);
447 idf[num].size = f->size;
449 idf[num].compmethod = 2;
451 idf[num].compmethod = 1;
453 idf[num].ofs = SafeSeek(h, 0, SEEK_CUR);
454 idf[num].compsize = QC_encode(progfuncs, f->size, idf[num].compmethod, f->file, h);
458 ofs = SafeSeek(h, 0, SEEK_CUR);
459 SafeWrite(h, &num, sizeof(int));
460 SafeWrite(h, idf, sizeof(includeddatafile_t)*num);
462 qcc_sourcefile = NULL;
467 void QCC_InitData (void)
469 static char parmname[12][MAX_PARMS];
470 static temp_t ret_temp;
473 qcc_sourcefile = NULL;
481 memset(&ret_temp, 0, sizeof(ret_temp));
483 def_ret.ofs = OFS_RETURN;
484 def_ret.name = "return";
485 def_ret.temp = &ret_temp;
486 def_ret.constant = false;
488 ret_temp.ofs = def_ret.ofs;
489 ret_temp.scope = NULL;
491 ret_temp.next = NULL;
492 for (i=0 ; i<MAX_PARMS ; i++)
494 def_parms[i].temp = NULL;
495 def_parms[i].type = NULL;
496 def_parms[i].ofs = OFS_PARM0 + 3*i;
497 def_parms[i].name = parmname[i];
498 sprintf(parmname[i], "parm%i", i);
502 int WriteBodylessFuncs (int handle)
506 for (d=pr.def_head.next ; d ; d=d->next)
508 if (d->type->type == ev_function && !d->scope)// function parms are ok
510 if (d->initialized != 1 && d->references>0)
512 SafeWrite(handle, d->name, strlen(d->name)+1);
521 //marshalled locals remaps all the functions to use the range MAX_REGS onwards for the offset to their locals.
522 //this function remaps all the locals back into the function.
523 void QCC_UnmarshalLocals(void)
533 for (def = pr.def_head.next ; def ; def = def->next)
535 if (def->ofs >= MAX_REGS) //unmap defs.
537 def->ofs = def->ofs + ofs - MAX_REGS;
543 for (i = 0; i < numfunctions; i++)
545 if (functions[i].parm_start == MAX_REGS)
546 functions[i].parm_start = ofs;
549 QCC_RemapOffsets(0, numstatements, MAX_REGS, MAX_REGS + maxo-numpr_globals + 3, ofs);
551 numpr_globals = maxo+3;
552 if (numpr_globals > MAX_REGS)
553 QCC_Error(ERR_TOOMANYGLOBALS, "Too many globals are in use to unmarshal all locals");
556 printf("Total of %i marshalled globals\n", maxo-ofs);
559 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def);
560 pbool QCC_WriteData (int crc)
562 char element[MAX_NAME];
563 QCC_def_t *def, *comp_x, *comp_y, *comp_z;
568 pbool debugtarget = false;
572 if (numstatements==1 && numfunctions==1 && numglobaldefs==1 && numfielddefs==1)
574 printf("nothing to write\n");
578 progs.blockscompressed=0;
580 if (numstatements > MAX_STATEMENTS)
581 QCC_Error(ERR_TOOMANYSTATEMENTS, "Too many statements - %i\nAdd \"MAX_STATEMENTS\" \"%i\" to qcc.cfg", numstatements, (numstatements+32768)&~32767);
583 if (strofs > MAX_STRINGS)
584 QCC_Error(ERR_TOOMANYSTRINGS, "Too many strings - %i\nAdd \"MAX_STRINGS\" \"%i\" to qcc.cfg", strofs, (strofs+32768)&~32767);
586 QCC_UnmarshalLocals();
588 switch (qcc_targetformat)
593 printf("Warning: There are some functions without bodies.\n");
595 if (numpr_globals > 65530 )
597 printf("Forcing target to FTE32 due to numpr_globals\n");
600 else if (qcc_targetformat == QCF_HEXEN2)
602 printf("Progs execution requires a Hexen2 compatible engine\n");
607 if (numpr_globals >= 32768) //not much of a different format. Rewrite output to get it working on original executors?
608 printf("An enhanced executor will be required (FTE/QF/KK)\n");
610 printf("Progs should run on any Quake executor\n");
614 qcc_targetformat = QCF_FTE;
618 if (qcc_targetformat == QCF_FTEDEBUG)
621 if (numpr_globals > 65530)
623 printf("Using 32 bit target due to numpr_globals\n");
627 if (qcc_targetformat == QCF_DARKPLACES)
631 //compression of blocks?
632 if (compressoutput) progs.blockscompressed |=1; //statements
633 if (compressoutput) progs.blockscompressed |=2; //defs
634 if (compressoutput) progs.blockscompressed |=4; //fields
635 if (compressoutput) progs.blockscompressed |=8; //functions
636 if (compressoutput) progs.blockscompressed |=16; //strings
637 if (compressoutput) progs.blockscompressed |=32; //globals
638 if (compressoutput) progs.blockscompressed |=64; //line numbers
639 if (compressoutput) progs.blockscompressed |=128; //types
640 //include a type block?
641 types = debugtarget;//!!QCC_PR_CheckCompConstDefined("TYPES"); //useful for debugging and saving (maybe, anyway...).
645 if (qcc_targetformat == QCF_DARKPLACES)
646 printf("DarkPlaces or FTE will be required\n");
648 printf("An FTE executor will be required\n");
653 printf("Warning: There are some functions without bodies.\n");
654 if (numpr_globals > 65530)
655 printf("Warning: Saving is not supported. Ensure all engine read fields and globals are defined early on.\n");
657 printf("A KK compatible executor will be required (FTE/KK)\n");
661 //part of how compilation works. This def is always present, and never used.
662 def = QCC_PR_GetDef(NULL, "end_sys_globals", NULL, false, 0, false);
666 def = QCC_PR_GetDef(NULL, "end_sys_fields", NULL, false, 0, false);
670 for (def = pr.def_head.next ; def ; def = def->next)
672 if (def->type->type == ev_vector || (def->type->type == ev_field && def->type->aux_type->type == ev_vector))
673 { //do the references, so we don't get loadsa not referenced VEC_HULL_MINS_x
674 sprintf(element, "%s_x", def->name);
675 comp_x = QCC_PR_GetDef(NULL, element, def->scope, false, 0, false);
676 sprintf(element, "%s_y", def->name);
677 comp_y = QCC_PR_GetDef(NULL, element, def->scope, false, 0, false);
678 sprintf(element, "%s_z", def->name);
679 comp_z = QCC_PR_GetDef(NULL, element, def->scope, false, 0, false);
682 if (comp_x && comp_y && comp_z)
684 h += comp_x->references;
685 h += comp_y->references;
686 h += comp_z->references;
688 if (!def->references)
689 if (!comp_x->references || !comp_y->references || !comp_z->references) //one of these vars is useless...
698 comp_x->references = h;
700 comp_y->references = h;
702 comp_z->references = h;
705 if (def->references<=0)
708 QCC_PR_Warning(WARN_NOTREFERENCEDCONST, strings + def->s_file, def->s_line, "%s no references", def->name);
710 QCC_PR_Warning(WARN_NOTREFERENCED, strings + def->s_file, def->s_line, "%s no references", def->name);
712 if (opt_unreferenced && def->type->type != ev_field)
714 optres_unreferenced++;
719 if (def->type->type == ev_function)
721 if (opt_function_names && functions[G_FUNCTION(def->ofs)].first_statement<0)
723 optres_function_names++;
726 if (!def->timescalled)
728 if (def->references<=1)
729 QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called or referenced (spawn function or dead code)", def->name);
731 // QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called", def->name);
733 if (opt_stripfunctions && def->timescalled >= def->references-1) //make sure it's not copied into a different var.
734 { //if it ever does self.think then it could be needed for saves.
735 optres_stripfunctions++; //if it's only ever called explicitly, the engine doesn't need to know.
739 // df = &functions[numfunctions];
743 else if (def->type->type == ev_field)// && !def->constant)
745 dd = &fields[numfielddefs];
747 dd->type = def->type->aux_type->type;
748 dd->s_name = QCC_CopyString (def->name);
749 dd->ofs = G_INT(def->ofs);
751 else if ((def->scope||def->constant) && (def->type->type != ev_string || opt_constant_names_strings))
753 if (opt_constant_names)
755 if (def->type->type == ev_string)
756 optres_constant_names_strings += strlen(def->name);
758 optres_constant_names += strlen(def->name);
763 // if (!def->saved && def->type->type != ev_string)
765 dd = &qcc_globals[numglobaldefs];
769 dd->type = def->type-qcc_typeinfo;
771 dd->type = def->type->type;
772 #ifdef DEF_SAVEGLOBAL
773 if ( def->saved && ((!def->initialized || def->type->type == ev_function)
774 // && def->type->type != ev_function
775 && def->type->type != ev_field
776 && def->scope == NULL))
778 dd->type |= DEF_SAVEGLOBAL;
782 dd->type |= DEF_SHARED;
784 if (opt_locals && (def->scope || !strcmp(def->name, "IMMEDIATE")))
787 optres_locals += strlen(def->name);
790 dd->s_name = QCC_CopyString (def->name);
794 for (i = 0; i < numglobaldefs; i++)
796 dd = &qcc_globals[i];
797 if (!(dd->type & DEF_SAVEGLOBAL)) //only warn about saved ones.
800 for (h = 0; h < numglobaldefs; h++)
804 if (dd->ofs == qcc_globals[h].ofs)
806 if (dd->type != qcc_globals[h].type)
808 if (dd->type != ev_vector && qcc_globals[h].type != ev_float)
809 QCC_PR_Warning(0, NULL, 0, "Mismatched union global types (%s and %s)", strings+dd->s_name, strings+qcc_globals[h].s_name);
811 //remove the saveglobal flag on the duplicate globals.
812 qcc_globals[h].type &= ~DEF_SAVEGLOBAL;
816 for (i = 1; i < numfielddefs; i++)
820 if (dd->type == ev_vector) //just ignore vectors.
823 for (h = 1; h < numfielddefs; h++)
827 if (dd->ofs == fields[h].ofs)
829 if (dd->type != fields[h].type)
831 if (fields[h].type != ev_vector)
833 QCC_PR_Warning(0, NULL, 0, "Mismatched union field types (%s and %s)", strings+dd->s_name, strings+fields[h].s_name);
840 if (numglobaldefs > MAX_GLOBALS)
841 QCC_Error(ERR_TOOMANYGLOBALS, "Too many globals - %i\nAdd \"MAX_GLOBALS\" \"%i\" to qcc.cfg", numglobaldefs, (numglobaldefs+32768)&~32767);
844 for (i = 0; i < nummodels; i++)
846 if (!precache_models_used[i])
847 QCC_PR_Warning(WARN_EXTRAPRECACHE, NULL, 0, "Model %s was precached but not directly used", precache_models[i]);
848 else if (!precache_models_block[i])
849 QCC_PR_Warning(WARN_NOTPRECACHED, NULL, 0, "Model %s was used but not precached", precache_models[i]);
855 strofs = (strofs+3)&~3;
859 printf ("%6i strofs (of %i)\n", strofs, MAX_STRINGS);
860 printf ("%6i numstatements (of %i)\n", numstatements, MAX_STATEMENTS);
861 printf ("%6i numfunctions (of %i)\n", numfunctions, MAX_FUNCTIONS);
862 printf ("%6i numglobaldefs (of %i)\n", numglobaldefs, MAX_GLOBALS);
863 printf ("%6i numfielddefs (%i unique) (of %i)\n", numfielddefs, pr.size_fields, MAX_FIELDS);
864 printf ("%6i numpr_globals (of %i)\n", numpr_globals, MAX_REGS);
868 strcpy(destfile, "progs.dat");
870 printf("Writing %s\n", destfile);
871 h = SafeOpenWrite (destfile, 2*1024*1024);
872 SafeWrite (h, &progs, sizeof(progs));
873 SafeWrite (h, "\r\n\r\n", 4);
874 SafeWrite (h, QCC_copyright, strlen(QCC_copyright)+1);
875 SafeWrite (h, "\r\n\r\n", 4);
876 while(SafeSeek (h, 0, SEEK_CUR) & 3)//this is a lame way to do it
878 SafeWrite (h, "\0", 1);
881 progs.ofs_strings = SafeSeek (h, 0, SEEK_CUR);
882 progs.numstrings = strofs;
884 if (progs.blockscompressed&16)
886 SafeWrite (h, &len, sizeof(int)); //save for later
887 len = QC_encode(progfuncs, strofs*sizeof(char), 2, (char *)strings, h); //write
888 i = SafeSeek (h, 0, SEEK_CUR);
889 SafeSeek(h, progs.ofs_strings, SEEK_SET);//seek back
890 len = PRLittleLong(len);
891 SafeWrite (h, &len, sizeof(int)); //write size.
892 SafeSeek(h, i, SEEK_SET);
895 SafeWrite (h, strings, strofs);
897 progs.ofs_statements = SafeSeek (h, 0, SEEK_CUR);
898 progs.numstatements = numstatements;
900 if (qcc_targetformat == QCF_HEXEN2)
902 for (i=0 ; i<numstatements ; i++)
904 if (statements[i].op >= OP_CALL1 && statements[i].op <= OP_CALL8)
905 QCC_Error(ERR_BADTARGETSWITCH, "Target switching produced incompatible instructions");
906 else if (statements[i].op >= OP_CALL1H && statements[i].op <= OP_CALL8H)
907 statements[i].op = statements[i].op - OP_CALL1H + OP_CALL1;
911 for (i=0 ; i<numstatements ; i++)
913 switch(qcc_targetformat == QCF_KK7?32:outputsize) //KK7 sucks.
916 for (i=0 ; i<numstatements ; i++)
918 statements[i].op = PRLittleLong/*PRLittleShort*/(statements[i].op);
919 statements[i].a = PRLittleLong/*PRLittleShort*/(statements[i].a);
920 statements[i].b = PRLittleLong/*PRLittleShort*/(statements[i].b);
921 statements[i].c = PRLittleLong/*PRLittleShort*/(statements[i].c);
924 if (progs.blockscompressed&1)
926 SafeWrite (h, &len, sizeof(int)); //save for later
927 len = QC_encode(progfuncs, numstatements*sizeof(QCC_dstatement32_t), 2, (char *)statements, h); //write
928 i = SafeSeek (h, 0, SEEK_CUR);
929 SafeSeek(h, progs.ofs_statements, SEEK_SET);//seek back
930 len = PRLittleLong(len);
931 SafeWrite (h, &len, sizeof(int)); //write size.
932 SafeSeek(h, i, SEEK_SET);
935 SafeWrite (h, statements, numstatements*sizeof(QCC_dstatement32_t));
938 #define statements16 ((QCC_dstatement16_t*) statements)
939 for (i=0 ; i<numstatements ; i++) //resize as we go - scaling down
941 statements16[i].op = PRLittleShort((unsigned short)statements[i].op);
942 if (statements[i].a < 0)
943 statements16[i].a = PRLittleShort((short)statements[i].a);
945 statements16[i].a = (unsigned short)PRLittleShort((unsigned short)statements[i].a);
946 if (statements[i].b < 0)
947 statements16[i].b = PRLittleShort((short)statements[i].b);
949 statements16[i].b = (unsigned short)PRLittleShort((unsigned short)statements[i].b);
950 if (statements[i].c < 0)
951 statements16[i].c = PRLittleShort((short)statements[i].c);
953 statements16[i].c = (unsigned short)PRLittleShort((unsigned short)statements[i].c);
956 if (progs.blockscompressed&1)
958 SafeWrite (h, &len, sizeof(int)); //save for later
959 len = QC_encode(progfuncs, numstatements*sizeof(QCC_dstatement16_t), 2, (char *)statements16, h); //write
960 i = SafeSeek (h, 0, SEEK_CUR);
961 SafeSeek(h, progs.ofs_statements, SEEK_SET);//seek back
962 len = PRLittleLong(len);
963 SafeWrite (h, &len, sizeof(int)); //write size.
964 SafeSeek(h, i, SEEK_SET);
967 SafeWrite (h, statements16, numstatements*sizeof(QCC_dstatement16_t));
970 Sys_Error("intsize error");
973 progs.ofs_functions = SafeSeek (h, 0, SEEK_CUR);
974 progs.numfunctions = numfunctions;
975 for (i=0 ; i<numfunctions ; i++)
977 functions[i].first_statement = PRLittleLong (functions[i].first_statement);
978 functions[i].parm_start = PRLittleLong (functions[i].parm_start);
979 functions[i].s_name = PRLittleLong (functions[i].s_name);
980 functions[i].s_file = PRLittleLong (functions[i].s_file);
981 functions[i].numparms = PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
982 functions[i].locals = PRLittleLong (functions[i].locals);
985 if (progs.blockscompressed&8)
987 SafeWrite (h, &len, sizeof(int)); //save for later
988 len = QC_encode(progfuncs, numfunctions*sizeof(QCC_dfunction_t), 2, (char *)functions, h); //write
989 i = SafeSeek (h, 0, SEEK_CUR);
990 SafeSeek(h, progs.ofs_functions, SEEK_SET);//seek back
991 len = PRLittleLong(len);
992 SafeWrite (h, &len, sizeof(int)); //write size.
993 SafeSeek(h, i, SEEK_SET);
996 SafeWrite (h, functions, numfunctions*sizeof(QCC_dfunction_t));
1001 progs.ofs_globaldefs = SafeSeek (h, 0, SEEK_CUR);
1002 progs.numglobaldefs = numglobaldefs;
1003 for (i=0 ; i<numglobaldefs ; i++)
1005 qcc_globals[i].type = PRLittleLong/*PRLittleShort*/ (qcc_globals[i].type);
1006 qcc_globals[i].ofs = PRLittleLong/*PRLittleShort*/ (qcc_globals[i].ofs);
1007 qcc_globals[i].s_name = PRLittleLong (qcc_globals[i].s_name);
1010 if (progs.blockscompressed&2)
1012 SafeWrite (h, &len, sizeof(int)); //save for later
1013 len = QC_encode(progfuncs, numglobaldefs*sizeof(QCC_ddef_t), 2, (char *)qcc_globals, h); //write
1014 i = SafeSeek (h, 0, SEEK_CUR);
1015 SafeSeek(h, progs.ofs_globaldefs, SEEK_SET);//seek back
1016 len = PRLittleLong(len);
1017 SafeWrite (h, &len, sizeof(int)); //write size.
1018 SafeSeek(h, i, SEEK_SET);
1021 SafeWrite (h, qcc_globals, numglobaldefs*sizeof(QCC_ddef_t));
1023 progs.ofs_fielddefs = SafeSeek (h, 0, SEEK_CUR);
1024 progs.numfielddefs = numfielddefs;
1026 for (i=0 ; i<numfielddefs ; i++)
1028 fields[i].type = PRLittleLong/*PRLittleShort*/ (fields[i].type);
1029 fields[i].ofs = PRLittleLong/*PRLittleShort*/ (fields[i].ofs);
1030 fields[i].s_name = PRLittleLong (fields[i].s_name);
1033 if (progs.blockscompressed&4)
1035 SafeWrite (h, &len, sizeof(int)); //save for later
1036 len = QC_encode(progfuncs, numfielddefs*sizeof(QCC_ddef_t), 2, (char *)fields, h); //write
1037 i = SafeSeek (h, 0, SEEK_CUR);
1038 SafeSeek(h, progs.ofs_fielddefs, SEEK_SET);//seek back
1039 len = PRLittleLong(len);
1040 SafeWrite (h, &len, sizeof(int)); //write size.
1041 SafeSeek(h, i, SEEK_SET);
1044 SafeWrite (h, fields, numfielddefs*sizeof(QCC_ddef_t));
1047 #define qcc_globals16 ((QCC_ddef16_t*)qcc_globals)
1048 #define fields16 ((QCC_ddef16_t*)fields)
1049 progs.ofs_globaldefs = SafeSeek (h, 0, SEEK_CUR);
1050 progs.numglobaldefs = numglobaldefs;
1051 for (i=0 ; i<numglobaldefs ; i++)
1053 qcc_globals16[i].type = (unsigned short)PRLittleShort ((unsigned short)qcc_globals[i].type);
1054 qcc_globals16[i].ofs = (unsigned short)PRLittleShort ((unsigned short)qcc_globals[i].ofs);
1055 qcc_globals16[i].s_name = PRLittleLong (qcc_globals[i].s_name);
1058 if (progs.blockscompressed&2)
1060 SafeWrite (h, &len, sizeof(int)); //save for later
1061 len = QC_encode(progfuncs, numglobaldefs*sizeof(QCC_ddef16_t), 2, (char *)qcc_globals16, h); //write
1062 i = SafeSeek (h, 0, SEEK_CUR);
1063 SafeSeek(h, progs.ofs_globaldefs, SEEK_SET);//seek back
1064 len = PRLittleLong(len);
1065 SafeWrite (h, &len, sizeof(int)); //write size.
1066 SafeSeek(h, i, SEEK_SET);
1069 SafeWrite (h, qcc_globals16, numglobaldefs*sizeof(QCC_ddef16_t));
1071 progs.ofs_fielddefs = SafeSeek (h, 0, SEEK_CUR);
1072 progs.numfielddefs = numfielddefs;
1074 for (i=0 ; i<numfielddefs ; i++)
1076 fields16[i].type = (unsigned short)PRLittleShort ((unsigned short)fields[i].type);
1077 fields16[i].ofs = (unsigned short)PRLittleShort ((unsigned short)fields[i].ofs);
1078 fields16[i].s_name = PRLittleLong (fields[i].s_name);
1081 if (progs.blockscompressed&4)
1083 SafeWrite (h, &len, sizeof(int)); //save for later
1084 len = QC_encode(progfuncs, numfielddefs*sizeof(QCC_ddef16_t), 2, (char *)fields16, h); //write
1085 i = SafeSeek (h, 0, SEEK_CUR);
1086 SafeSeek(h, progs.ofs_fielddefs, SEEK_SET);//seek back
1087 len = PRLittleLong(len);
1088 SafeWrite (h, &len, sizeof(int)); //write size.
1089 SafeSeek(h, i, SEEK_SET);
1092 SafeWrite (h, fields16, numfielddefs*sizeof(QCC_ddef16_t));
1095 Sys_Error("intsize error");
1098 progs.ofs_globals = SafeSeek (h, 0, SEEK_CUR);
1099 progs.numglobals = numpr_globals;
1101 for (i=0 ; (unsigned)i<numpr_globals ; i++)
1102 ((int *)qcc_pr_globals)[i] = PRLittleLong (((int *)qcc_pr_globals)[i]);
1104 if (progs.blockscompressed&32)
1106 SafeWrite (h, &len, sizeof(int)); //save for later
1107 len = QC_encode(progfuncs, numpr_globals*4, 2, (char *)qcc_pr_globals, h); //write
1108 i = SafeSeek (h, 0, SEEK_CUR);
1109 SafeSeek(h, progs.ofs_globals, SEEK_SET);//seek back
1110 len = PRLittleLong(len);
1111 SafeWrite (h, &len, sizeof(int)); //write size.
1112 SafeSeek(h, i, SEEK_SET);
1115 SafeWrite (h, qcc_pr_globals, numpr_globals*4);
1118 for (i=0 ; i<numtypeinfos ; i++)
1120 if (qcc_typeinfo[i].aux_type)
1121 qcc_typeinfo[i].aux_type = (QCC_type_t*)(qcc_typeinfo[i].aux_type - qcc_typeinfo);
1122 if (qcc_typeinfo[i].next)
1123 qcc_typeinfo[i].next = (QCC_type_t*)(qcc_typeinfo[i].next - qcc_typeinfo);
1124 qcc_typeinfo[i].name = (char *)QCC_CopyDupBackString(qcc_typeinfo[i].name);
1128 progs.ofslinenums = 0;
1129 progs.secondaryversion = 0;
1130 progs.ofsbodylessfuncs = 0;
1131 progs.numbodylessfuncs = 0;
1132 progs.ofs_types = 0;
1135 switch(qcc_targetformat)
1138 progs.version = PROG_KKQWSVVERSION;
1141 case QCF_HEXEN2: //urgh
1142 progs.version = PROG_VERSION;
1144 case QCF_DARKPLACES:
1147 progs.version = PROG_EXTENDEDVERSION;
1149 if (outputsize == 32)
1150 progs.secondaryversion = PROG_SECONDARYVERSION32;
1152 progs.secondaryversion = PROG_SECONDARYVERSION16;
1154 progs.ofsbodylessfuncs = SafeSeek (h, 0, SEEK_CUR);
1155 progs.numbodylessfuncs = WriteBodylessFuncs(h);
1159 progs.ofslinenums = SafeSeek (h, 0, SEEK_CUR);
1160 if (progs.blockscompressed&64)
1162 SafeWrite (h, &len, sizeof(int)); //save for later
1163 len = QC_encode(progfuncs, numstatements*sizeof(int), 2, (char *)statement_linenums, h); //write
1164 i = SafeSeek (h, 0, SEEK_CUR);
1165 SafeSeek(h, progs.ofslinenums, SEEK_SET);//seek back
1166 len = PRLittleLong(len);
1167 SafeWrite (h, &len, sizeof(int)); //write size.
1168 SafeSeek(h, i, SEEK_SET);
1171 SafeWrite (h, statement_linenums, numstatements*sizeof(int));
1174 progs.ofslinenums = 0;
1178 progs.ofs_types = SafeSeek (h, 0, SEEK_CUR);
1179 if (progs.blockscompressed&128)
1181 SafeWrite (h, &len, sizeof(int)); //save for later
1182 len = QC_encode(progfuncs, sizeof(QCC_type_t)*numtypeinfos, 2, (char *)qcc_typeinfo, h); //write
1183 i = SafeSeek (h, 0, SEEK_CUR);
1184 SafeSeek(h, progs.ofs_types, SEEK_SET);//seek back#
1185 len = PRLittleLong(len);
1186 SafeWrite (h, &len, sizeof(int)); //write size.
1187 SafeSeek(h, i, SEEK_SET);
1190 SafeWrite (h, qcc_typeinfo, sizeof(QCC_type_t)*numtypeinfos);
1191 progs.numtypes = numtypeinfos;
1195 progs.ofs_types = 0;
1199 progs.ofsfiles = WriteSourceFiles(h, &progs, debugtarget);
1204 printf ("%6i TOTAL SIZE\n", (int)SafeSeek (h, 0, SEEK_CUR));
1206 progs.entityfields = pr.size_fields;
1210 // qbyte swap the header and write it out
1212 for (i=0 ; i<sizeof(progs)/4 ; i++)
1213 ((int *)&progs)[i] = PRLittleLong ( ((int *)&progs)[i] );
1216 SafeSeek (h, 0, SEEK_SET);
1217 SafeWrite (h, &progs, sizeof(progs));
1224 printf("Not writing linenumbers file due to conflicting optimisation\n");
1228 unsigned int lnotype = *(unsigned int*)"LNOF";
1229 unsigned int version = 1;
1230 StripExtension(destfile);
1231 strcat(destfile, ".lno");
1233 printf("Writing %s for debugging\n", destfile);
1234 h = SafeOpenWrite (destfile, 2*1024*1024);
1235 SafeWrite (h, &lnotype, sizeof(int));
1236 SafeWrite (h, &version, sizeof(int));
1237 SafeWrite (h, &numglobaldefs, sizeof(int));
1238 SafeWrite (h, &numpr_globals, sizeof(int));
1239 SafeWrite (h, &numfielddefs, sizeof(int));
1240 SafeWrite (h, &numstatements, sizeof(int));
1241 SafeWrite (h, statement_linenums, numstatements*sizeof(int));
1255 Returns a string suitable for printing (no newlines, max 60 chars length)
1258 char *QCC_PR_String (char *string)
1260 static char buf[80];
1265 while (string && *string)
1267 if (s == buf + sizeof(buf) - 2)
1269 if (*string == '\n')
1274 else if (*string == '"')
1297 QCC_def_t *QCC_PR_DefForFieldOfs (gofs_t ofs)
1301 for (d=pr.def_head.next ; d ; d=d->next)
1303 if (d->type->type != ev_field)
1305 if (*((unsigned int *)&qcc_pr_globals[d->ofs]) == ofs)
1308 QCC_Error (ERR_NOTDEFINED, "PR_DefForFieldOfs: couldn't find %i",ofs);
1316 Returns a string describing *data in a type specific manner
1319 char *QCC_PR_ValueString (etype_t type, void *val)
1321 static char line[256];
1328 sprintf (line, "%s", QCC_PR_String(strings + *(int *)val));
1331 sprintf (line, "entity %i", *(int *)val);
1334 f = functions + *(int *)val;
1336 sprintf (line, "undefined function");
1338 sprintf (line, "%s()", strings + f->s_name);
1341 def = QCC_PR_DefForFieldOfs ( *(int *)val );
1342 sprintf (line, ".%s", def->name);
1345 sprintf (line, "void");
1348 sprintf (line, "%5.1f", *(float *)val);
1351 sprintf (line, "%i", *(int *)val);
1354 sprintf (line, "'%5.1f %5.1f %5.1f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
1357 sprintf (line, "pointer");
1360 sprintf (line, "bad type %i", type);
1371 Returns a string with a description and the contents of a global,
1372 padded to 20 field width
1375 /*char *QCC_PR_GlobalStringNoContents (gofs_t ofs)
1380 static char line[128];
1382 val = (void *)&qcc_pr_globals[ofs];
1383 def = pr_global_defs[ofs];
1385 // Error ("PR_GlobalString: no def for %i", ofs);
1386 sprintf (line,"%i(?""?""?)", ofs);
1388 sprintf (line,"%i(%s)", ofs, def->name);
1398 char *QCC_PR_GlobalString (gofs_t ofs)
1404 static char line[128];
1406 val = (void *)&qcc_pr_globals[ofs];
1407 def = pr_global_defs[ofs];
1409 return QCC_PR_GlobalStringNoContents(ofs);
1410 if (def->initialized && def->type->type != ev_function)
1412 s = QCC_PR_ValueString (def->type->type, &qcc_pr_globals[ofs]);
1413 sprintf (line,"%i(%s)", ofs, s);
1416 sprintf (line,"%i(%s)", ofs, def->name);
1431 /*void QCC_PR_PrintOfs (gofs_t ofs)
1433 printf ("%s\n",QCC_PR_GlobalString(ofs));
1441 /*void QCC_PR_PrintStatement (QCC_dstatement_t *s)
1445 printf ("%4i : %4i : %s ", (int)(s - statements), statement_linenums[s-statements], pr_opcodes[s->op].opname);
1446 i = strlen(pr_opcodes[s->op].opname);
1450 if (s->op == OP_IF || s->op == OP_IFNOT)
1451 printf ("%sbranch %i",QCC_PR_GlobalString(s->a),s->b);
1452 else if (s->op == OP_GOTO)
1454 printf ("branch %i",s->a);
1456 else if ( (unsigned)(s->op - OP_STORE_F) < 6)
1458 printf ("%s",QCC_PR_GlobalString(s->a));
1459 printf ("%s", QCC_PR_GlobalStringNoContents(s->b));
1464 printf ("%s",QCC_PR_GlobalString(s->a));
1466 printf ("%s",QCC_PR_GlobalString(s->b));
1468 printf ("%s", QCC_PR_GlobalStringNoContents(s->c));
1479 /*void QCC_PR_PrintDefs (void)
1483 for (d=pr.def_head.next ; d ; d=d->next)
1484 QCC_PR_PrintOfs (d->ofs);
1487 QCC_type_t *QCC_PR_NewType (char *name, int basictype)
1489 if (numtypeinfos>= maxtypeinfos)
1490 QCC_Error(ERR_TOOMANYTYPES, "Too many types");
1491 memset(&qcc_typeinfo[numtypeinfos], 0, sizeof(QCC_type_t));
1492 qcc_typeinfo[numtypeinfos].type = basictype;
1493 qcc_typeinfo[numtypeinfos].name = name;
1494 qcc_typeinfo[numtypeinfos].num_parms = 0;
1495 qcc_typeinfo[numtypeinfos].param = NULL;
1496 qcc_typeinfo[numtypeinfos].size = type_size[basictype];
1501 return &qcc_typeinfo[numtypeinfos-1];
1508 called before compiling a batch of files, clears the pr struct
1511 void QCC_PR_BeginCompilation (void *memory, int memsize)
1513 extern int recursivefunctiontype;
1514 extern struct freeoffset_s *freeofs;
1519 pr.max_memory = memsize;
1521 pr.def_tail = &pr.def_head;
1523 QCC_PR_ResetErrorScope();
1526 /* numpr_globals = RESERVED_OFS;
1528 for (i=0 ; i<RESERVED_OFS ; i++)
1529 pr_global_defs[i] = &def_void;
1532 type_void = QCC_PR_NewType("void", ev_void);
1533 type_string = QCC_PR_NewType("string", ev_string);
1534 type_float = QCC_PR_NewType("float", ev_float);
1535 type_vector = QCC_PR_NewType("vector", ev_vector);
1536 type_entity = QCC_PR_NewType("entity", ev_entity);
1537 type_field = QCC_PR_NewType("field", ev_field);
1538 type_function = QCC_PR_NewType("function", ev_function);
1539 type_pointer = QCC_PR_NewType("pointer", ev_pointer);
1540 type_integer = QCC_PR_NewType("__integer", ev_integer);
1541 type_variant = QCC_PR_NewType("__variant", ev_variant);
1543 type_floatfield = QCC_PR_NewType("fieldfloat", ev_field);
1544 type_floatfield->aux_type = type_float;
1545 type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float);
1547 type_function->aux_type = type_void;
1549 //type_field->aux_type = type_float;
1551 if (keyword_integer)
1552 type_integer = QCC_PR_NewType("integer", ev_integer);
1554 type_integer = QCC_PR_NewType("int", ev_integer);
1559 { //this tends to confuse the brains out of decompilers. :)
1561 QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 1, false)->references++;
1562 for (i = 0; i < MAX_PARMS; i++)
1564 sprintf(name, "PARM%i", i);
1565 QCC_PR_GetDef(type_vector, name, NULL, true, 1, false)->references++;
1570 numpr_globals = RESERVED_OFS;
1571 // for (i=0 ; i<RESERVED_OFS ; i++)
1572 // pr_global_defs[i] = NULL;
1575 // link the function type in so state forward declarations match proper type
1577 // type_function->next = NULL;
1579 pr_warning_count = 0;
1580 recursivefunctiontype = 0;
1587 PR_FinishCompilation
1589 called after all files are compiled to check for errors
1590 Returns false if errors were detected.
1593 int QCC_PR_FinishCompilation (void)
1600 // check to make sure all functions prototyped have code
1601 for (d=pr.def_head.next ; d ; d=d->next)
1603 if (d->type->type == ev_function && !d->scope)// function parms are ok
1605 // f = G_FUNCTION(d->ofs);
1606 // if (!f || (!f->code && !f->builtin) )
1607 if (d->initialized==0)
1609 if (!strncmp(d->name, "ArrayGet*", 9))
1611 QCC_PR_EmitArrayGetFunction(d, d->name+9);
1614 else if (!strncmp(d->name, "ArraySet*", 9))
1616 QCC_PR_EmitArraySetFunction(d, d->name+9);
1619 else if (!strncmp(d->name, "Class*", 6))
1621 QCC_PR_EmitClassFromFunction(d, d->name+6);
1626 QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, d, "function %s was not defined",d->name);
1627 bodylessfuncs = true;
1632 else if (d->initialized==2)
1633 bodylessfuncs = true;
1641 //=============================================================================
1643 // FIXME: byte swap?
1645 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1646 // and the initial and final xor values shown below... in other words, the
1647 // CCITT standard CRC used by XMODEM
1650 #define CRC_INIT_VALUE 0xffff
1651 #define CRC_XOR_VALUE 0x0000
1653 static unsigned short QCC_crctable[256] =
1655 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1656 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1657 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1658 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1659 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1660 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1661 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1662 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1663 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1664 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1665 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1666 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1667 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1668 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1669 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1670 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1671 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1672 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1673 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1674 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1675 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1676 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1677 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1678 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1679 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1680 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1681 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1682 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1683 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1684 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1685 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1686 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1689 void QCC_CRC_Init(unsigned short *crcvalue)
1691 *crcvalue = CRC_INIT_VALUE;
1694 void QCC_CRC_ProcessByte(unsigned short *crcvalue, qbyte data)
1696 *crcvalue = (*crcvalue << 8) ^ QCC_crctable[(*crcvalue >> 8) ^ data];
1699 unsigned short QCC_CRC_Value(unsigned short crcvalue)
1701 return crcvalue ^ CRC_XOR_VALUE;
1703 //=============================================================================
1710 Writes the global and entity structures out
1711 Returns a crc of the header, to be stored in the progs file for comparison
1716 char *Sva(char *msg, ...)
1719 static char buf[1024];
1722 QC_vsnprintf (buf,sizeof(buf)-1, msg, l);
1729 #define PROGDEFS_MAX_SIZE 16384
1730 //write (to file buf) and add to the crc
1731 static void Add(char *p, unsigned short *crc, char *file)
1734 int i = strlen(file);
1735 if (i + strlen(p)+1 >= PROGDEFS_MAX_SIZE)
1739 QCC_CRC_ProcessByte(crc, *s);
1744 #define ADD(p) Add(p, &crc, file)
1745 //#define ADD(p) {char *s;int i = strlen(p);for(s=p;*s;s++,i++){QCC_CRC_ProcessByte(&crc, *s);file[i] = *s;}file[i]='\0';}
1747 static void Add3(char *p, unsigned short *crc, char *file)
1751 QCC_CRC_ProcessByte(crc, *s);
1753 #define ADD3(p) Add3(p, &crc, file)
1755 unsigned short QCC_PR_WriteProgdefs (char *filename)
1757 #define ADD2(p) strncat(file, p, PROGDEFS_MAX_SIZE-1 - strlen(file)) //no crc (later changes)
1758 char file[PROGDEFS_MAX_SIZE];
1766 QCC_CRC_Init (&crc);
1768 // print global vars until the first field is defined
1771 //ADD2: dump but don't crc
1772 //ADD3: crc but don't dump
1775 if (qcc_targetformat == QCF_HEXEN2)
1776 ADD3("generated by hcc, do not modify");
1778 ADD3("file generated by qcc, do not modify");
1779 ADD2("File generated by FTEQCC, relevent for engine modding only, the generated crc must be the same as your engine expects.");
1780 ADD(" */\n\ntypedef struct");
1781 ADD2(" globalvars_s");
1784 "\tint ofs_return[3];\n" //makes it easier with the get globals func
1785 "\tint ofs_parm0[3];\n"
1786 "\tint ofs_parm1[3];\n"
1787 "\tint ofs_parm2[3];\n"
1788 "\tint ofs_parm3[3];\n"
1789 "\tint ofs_parm4[3];\n"
1790 "\tint ofs_parm5[3];\n"
1791 "\tint ofs_parm6[3];\n"
1792 "\tint ofs_parm7[3];\n");
1793 ADD3(qcva("\tint\tpad[%i];\n", RESERVED_OFS));
1794 for (d=pr.def_head.next ; d ; d=d->next)
1796 if (!strcmp (d->name, "end_sys_globals"))
1798 if (d->ofs<RESERVED_OFS)
1801 switch (d->type->type)
1804 ADD(qcva("\tfloat\t%s;\n",d->name));
1807 ADD(qcva("\tvec3_t\t%s;\n",d->name));
1808 d=d->next->next->next; // skip the elements
1811 ADD(qcva("\tstring_t\t%s;\n",d->name));
1814 ADD(qcva("\tfunc_t\t%s;\n",d->name));
1817 ADD(qcva("\tint\t%s;\n",d->name));
1820 ADD(qcva("\tint\t%s;\n",d->name));
1823 ADD(qcva("\tint\t%s;\n",d->name));
1827 ADD("} globalvars_t;\n\n");
1830 ADD("typedef struct");
1833 for (d=pr.def_head.next ; d ; d=d->next)
1835 if (!strcmp (d->name, "end_sys_fields"))
1838 if (d->type->type != ev_field)
1841 switch (d->type->aux_type->type)
1844 ADD(qcva("\tfloat\t%s;\n",d->name));
1847 ADD(qcva("\tvec3_t\t%s;\n",d->name));
1848 d=d->next->next->next; // skip the elements
1851 ADD(qcva("\tstring_t\t%s;\n",d->name));
1854 ADD(qcva("\tfunc_t\t%s;\n",d->name));
1857 ADD(qcva("\tint\t%s;\n",d->name));
1860 ADD(qcva("\tint\t%s;\n",d->name));
1863 ADD(qcva("\tint\t%s;\n",d->name));
1867 ADD("} entvars_t;\n\n");
1870 ADD2("//with this the crc isn't needed for fields.\n#ifdef FIELDSSTRUCT\nstruct fieldvars_s {\n\tint ofs;\n\tint type;\n\tchar *name;\n} fieldvars[] = {\n");
1872 for (d=pr.def_head.next ; d ; d=d->next)
1874 if (!strcmp (d->name, "end_sys_fields"))
1877 if (d->type->type != ev_field)
1881 ADD2(qcva("\t{%i,\t%i,\t\"%s\"}",G_INT(d->ofs), d->type->aux_type->type, d->name));
1884 ADD2("\n};\n#endif\n\n");
1887 ADD2(qcva("#define PROGHEADER_CRC %i\n", crc));
1889 if (QCC_CheckParm("-progdefs"))
1891 printf ("writing %s\n", filename);
1892 f = SafeOpenWrite(filename, 16384);
1893 SafeWrite(f, file, strlen(file));
1903 case 12923: //#pragma sourcefile usage
1907 printf("Recognised progs as QuakeWorld\n");
1911 printf("Recognised progs as NetQuake server gamecode\n");
1916 printf("Recognised progs as Quake pre-release...\n");
1921 printf("Recognised progs as original Hexen2\n");
1925 printf("Recognised progs as Hexen2 Mission Pack\n");
1929 printf("Recognised progs as Hexen2 (demo)\n");
1932 case 22390: //EXT_CSQC_1
1934 printf("Recognised progs as an EXT_CSQC_1 module\n");
1937 case 32199: //outdated ext_csqc
1938 printf("Recognised progs as outdated CSQC module\n");
1941 printf("Recognised progs as outdated CSQC module\n");
1945 printf("Recognised progs as a DP/FTE Menu module\n");
1949 printf("Warning: please update your tenebrae system defs.\n");
1952 printf("Warning: progs CRC not recognised from quake nor clones\n");
1961 /*void QCC_PrintFunction (char *name)
1964 QCC_dstatement_t *ds;
1965 QCC_dfunction_t *df;
1967 for (i=0 ; i<numfunctions ; i++)
1968 if (!strcmp (name, strings + functions[i].s_name))
1970 if (i==numfunctions)
1971 QCC_Error (ERR_NOFUNC, "No function named \"%s\"", name);
1974 printf ("Statements for function %s:\n", name);
1975 ds = statements + df->first_statement;
1978 QCC_PR_PrintStatement (ds);
1985 void QCC_PrintOfs(unsigned int ofs)
1989 QCC_dstatement_t *ds;
1990 QCC_dfunction_t *df;
1992 for (i=0 ; i<numfunctions ; i++)
1995 ds = statements + df->first_statement;
2001 if (ds->a == ofs || ds->b == ofs || ds->c == ofs)
2003 QCC_PR_PrintStatement (ds);
2010 QCC_PrintFunction(strings + functions[i].s_name);
2018 ==============================================================================
2020 DIRECTORY COPYING / PACKFILE CREATION
2022 ==============================================================================
2028 int filepos, filelen;
2038 packfile_t pfiles[4096], *pf;
2048 void QCC_CreatePath (char *path)
2053 for (ofs = path+1 ; *ofs ; ofs++)
2056 { // create the directory
2074 Copy a file into the pak file
2077 void QCC_PackFile (char *src, char *name)
2089 if ( (qbyte *)pf - (qbyte *)pfiles > sizeof(pfiles) )
2090 QCC_Error (ERR_TOOMANYPAKFILES, "Too many files in pak file");
2093 f = FS_ReadToMem(src, NULL, &remaining);
2096 printf ("%64s : %7s\n", name, "");
2097 // QCC_Error("Failed to open file %s", src);
2101 pf->filepos = PRLittleLong (SafeSeek (packhandle, 0, SEEK_CUR));
2102 pf->filelen = PRLittleLong (remaining);
2103 strcpy (pf->name, name);
2104 printf ("%64s : %7i\n", pf->name, remaining);
2106 packbytes += remaining;
2108 SafeWrite (packhandle, f, remaining);
2112 in = SafeOpenRead (src);
2113 remaining = filelength (in);
2115 pf->filepos = PRLittleLong (lseek (packhandle, 0, SEEK_CUR));
2116 pf->filelen = PRLittleLong (remaining);
2117 strcpy (pf->name, name);
2118 printf ("%64s : %7i\n", pf->name, remaining);
2120 packbytes += remaining;
2124 if (remaining < sizeof(buf))
2127 count = sizeof(buf);
2128 SafeRead (in, buf, count);
2129 SafeWrite (packhandle, buf, count);
2143 Copies a file, creating any directories needed
2146 void QCC_CopyFile (char *src, char *dest)
2150 int remaining, count;
2153 print ("%s to %s\n", src, dest);
2155 in = SafeOpenRead (src);
2156 remaining = filelength (in);
2158 QCC_CreatePath (dest);
2159 out = SafeOpenWrite (dest, remaining+10);
2163 if (remaining < sizeof(buf))
2166 count = sizeof(buf);
2167 SafeRead (in, buf, count);
2168 SafeWrite (out, buf, count);
2184 void _QCC_CopyFiles (int blocknum, int copytype, char *srcdir, char *destdir)
2189 packheader_t header;
2191 char srcfile[1024], destfile[1024];
2198 packhandle = SafeOpenWrite (destdir, 1024*1024);
2199 SafeWrite (packhandle, &header, sizeof(header));
2202 for (i=0 ; i<numsounds ; i++)
2204 if (precache_sounds_block[i] != blocknum)
2206 sprintf (srcfile,"%s%s",srcdir, precache_sounds[i]);
2207 sprintf (destfile,"%s%s",destdir, precache_sounds[i]);
2209 QCC_CopyFile (srcfile, destfile);
2211 QCC_PackFile (srcfile, precache_sounds[i]);
2213 for (i=0 ; i<nummodels ; i++)
2215 if (precache_models_block[i] != blocknum)
2217 sprintf (srcfile,"%s%s",srcdir, precache_models[i]);
2218 sprintf (destfile,"%s%s",destdir, precache_models[i]);
2220 QCC_CopyFile (srcfile, destfile);
2222 QCC_PackFile (srcfile, precache_models[i]);
2224 for (i=0 ; i<numtextures ; i++)
2226 if (precache_textures_block[i] != blocknum)
2230 sprintf (name, "%s", precache_textures[i]);
2231 sprintf (srcfile,"%s%s",srcdir, name);
2232 sprintf (destfile,"%s%s",destdir, name);
2234 QCC_CopyFile (srcfile, destfile);
2236 QCC_PackFile (srcfile, name);
2239 sprintf (name, "%s.bmp", precache_textures[i]);
2240 sprintf (srcfile,"%s%s",srcdir, name);
2241 sprintf (destfile,"%s%s",destdir, name);
2243 QCC_CopyFile (srcfile, destfile);
2245 QCC_PackFile (srcfile, name);
2248 sprintf (name, "%s.tga", precache_textures[i]);
2249 sprintf (srcfile,"%s%s",srcdir, name);
2250 sprintf (destfile,"%s%s",destdir, name);
2252 QCC_CopyFile (srcfile, destfile);
2254 QCC_PackFile (srcfile, name);
2257 for (i=0 ; i<numfiles ; i++)
2259 if (precache_files_block[i] != blocknum)
2261 sprintf (srcfile,"%s%s",srcdir, precache_files[i]);
2262 sprintf (destfile,"%s%s",destdir, precache_files[i]);
2264 QCC_CopyFile (srcfile, destfile);
2266 QCC_PackFile (srcfile, precache_files[i]);
2275 dirlen = (qbyte *)pf - (qbyte *)pfiles;
2276 header.dirofs = PRLittleLong(SafeSeek (packhandle, 0, SEEK_CUR));
2277 header.dirlen = PRLittleLong(dirlen);
2279 SafeWrite (packhandle, pfiles, dirlen);
2281 SafeSeek (packhandle, 0, SEEK_SET);
2282 SafeWrite (packhandle, &header, sizeof(header));
2283 SafeClose (packhandle);
2285 // do a crc of the file
2286 QCC_CRC_Init (&crc);
2287 for (i=0 ; i<dirlen ; i++)
2288 QCC_CRC_ProcessByte (&crc, ((qbyte *)pfiles)[i]);
2291 printf ("%i files packed in %i bytes (%i crc)\n",i, packbytes, crc);
2295 void QCC_CopyFiles (void)
2298 char srcdir[1024], destdir[1024];
2304 printf ("%3i unique precache_sounds\n", numsounds);
2306 printf ("%3i unique precache_models\n", nummodels);
2307 if (numtextures > 0)
2308 printf ("%3i unique precache_textures\n", numtextures);
2310 printf ("%3i unique precache_files\n", numfiles);
2313 p = QCC_CheckParm ("-copy");
2314 if (p && p < myargc-2)
2315 { // create a new directory tree
2317 strcpy (srcdir, myargv[p+1]);
2318 strcpy (destdir, myargv[p+2]);
2319 if (srcdir[strlen(srcdir)-1] != '/')
2320 strcat (srcdir, "/");
2321 if (destdir[strlen(destdir)-1] != '/')
2322 strcat (destdir, "/");
2324 _QCC_CopyFiles(0, 1, srcdir, destdir);
2328 for ( p = 0; p < 5; p++)
2330 s = QCC_Packname[p];
2335 _QCC_CopyFiles(p+1, 2, srcdir, destdir);
2341 p = QCC_CheckParm ("-pak2");
2342 if (p && p <myargc-2)
2345 p = QCC_CheckParm ("-pak");
2346 if (p && p < myargc-2)
2347 { // create a pak file
2348 strcpy (srcdir, myargv[p+1]);
2349 strcpy (destdir, myargv[p+2]);
2350 if (srcdir[strlen(srcdir)-1] != '/')
2351 strcat (srcdir, "/");
2352 DefaultExtension (destdir, ".pak");
2357 _QCC_CopyFiles(blocknum, copytype, srcdir, destdir);
2362 //============================================================================
2365 void QCC_PR_CommandLinePrecompilerOptions (void)
2367 CompilerConstant_t *cnst;
2371 for (i = 1;i<myargc;i++)
2374 if ( !strncmp(myargv[i], "-D", 2) )
2376 name = myargv[i] + 2;
2377 val = strchr(name, '=');
2383 cnst = QCC_PR_DefineName(name);
2386 if (strlen(val)+1 >= sizeof(cnst->value))
2387 QCC_Error(ERR_PRECOMPILERCONSTANTTOOLONG, "Compiler constant value is too long\n");
2388 strncpy(cnst->value, val, sizeof(cnst->value)-1);
2389 cnst->value[sizeof(cnst->value)-1] = '\0';
2394 else if ( !strnicmp(myargv[i], "-O", 2) || !strnicmp(myargv[i], "/O", 2) )
2397 if (myargv[i][2] >= '0' && myargv[i][2] <= '3')
2400 else if (!strnicmp(myargv[i]+2, "no-", 3))
2404 for (p = 0; optimisations[p].enabled; p++)
2406 if ((*optimisations[p].abbrev && !stricmp(myargv[i]+5, optimisations[p].abbrev)) || !stricmp(myargv[i]+5, optimisations[p].fullname))
2408 *optimisations[p].enabled = false;
2417 for (p = 0; optimisations[p].enabled; p++)
2418 if ((*optimisations[p].abbrev && !stricmp(myargv[i]+2, optimisations[p].abbrev)) || !stricmp(myargv[i]+2, optimisations[p].fullname))
2420 *optimisations[p].enabled = true;
2424 if (!optimisations[p].enabled)
2425 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised optimisation parameter (%s)", myargv[i]);
2428 else if ( !strnicmp(myargv[i], "-K", 2) || !strnicmp(myargv[i], "/K", 2) )
2431 if (!strnicmp(myargv[i]+2, "no-", 3))
2433 for (p = 0; compiler_flag[p].enabled; p++)
2434 if (!stricmp(myargv[i]+5, compiler_flag[p].abbrev))
2436 *compiler_flag[p].enabled = false;
2442 for (p = 0; compiler_flag[p].enabled; p++)
2443 if (!stricmp(myargv[i]+2, compiler_flag[p].abbrev))
2445 *compiler_flag[p].enabled = true;
2450 if (!compiler_flag[p].enabled)
2451 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised keyword parameter (%s)", myargv[i]);
2453 else if ( !strnicmp(myargv[i], "-F", 2) || !strnicmp(myargv[i], "/F", 2) )
2456 if (!strnicmp(myargv[i]+2, "no-", 3))
2458 for (p = 0; compiler_flag[p].enabled; p++)
2459 if (!stricmp(myargv[i]+5, compiler_flag[p].abbrev))
2461 *compiler_flag[p].enabled = false;
2467 for (p = 0; compiler_flag[p].enabled; p++)
2468 if (!stricmp(myargv[i]+2, compiler_flag[p].abbrev))
2470 *compiler_flag[p].enabled = true;
2475 if (!compiler_flag[p].enabled)
2476 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised flag parameter (%s)", myargv[i]);
2480 else if ( !strncmp(myargv[i], "-T", 2) || !strncmp(myargv[i], "/T", 2) )
2483 for (p = 0; targets[p].name; p++)
2484 if (!stricmp(myargv[i]+2, targets[p].name))
2486 qcc_targetformat = targets[p].target;
2490 if (!targets[p].name)
2491 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised target parameter (%s)", myargv[i]);
2494 else if ( !strnicmp(myargv[i], "-W", 2) || !strnicmp(myargv[i], "/W", 2) )
2496 if (!stricmp(myargv[i]+2, "all"))
2497 memset(qccwarningdisabled, 0, sizeof(qccwarningdisabled));
2498 else if (!stricmp(myargv[i]+2, "none"))
2499 memset(qccwarningdisabled, 1, sizeof(qccwarningdisabled));
2500 else if(!stricmp(myargv[i]+2, "error"))
2502 else if (!stricmp(myargv[i]+2, "no-mundane"))
2503 { //disable mundane performance/efficiency/blah warnings that don't affect code.
2504 qccwarningdisabled[WARN_SAMENAMEASGLOBAL] = true;
2505 qccwarningdisabled[WARN_DUPLICATEDEFINITION] = true;
2506 qccwarningdisabled[WARN_CONSTANTCOMPARISON] = true;
2507 qccwarningdisabled[WARN_ASSIGNMENTINCONDITIONAL] = true;
2508 qccwarningdisabled[WARN_DEADCODE] = true;
2509 qccwarningdisabled[WARN_NOTREFERENCEDCONST] = true;
2510 qccwarningdisabled[WARN_NOTREFERENCED] = true;
2511 qccwarningdisabled[WARN_POINTLESSSTATEMENT] = true;
2512 qccwarningdisabled[WARN_ASSIGNMENTTOCONSTANTFUNC] = true;
2513 qccwarningdisabled[WARN_BADPRAGMA] = true; //C specs say that these should be ignored. We're close enough to C that I consider that a valid statement.
2514 qccwarningdisabled[WARN_IDENTICALPRECOMPILER] = true;
2515 qccwarningdisabled[WARN_UNDEFNOTDEFINED] = true;
2516 qccwarningdisabled[WARN_FIXEDRETURNVALUECONFLICT] = true;
2517 qccwarningdisabled[WARN_EXTRAPRECACHE] = true;
2518 qccwarningdisabled[WARN_CORRECTEDRETURNTYPE] = true;
2523 if (!strnicmp(myargv[i]+2, "no-", 3))
2525 for (p = 0; warningnames[p].name; p++)
2526 if (!strcmp(myargv[i]+5, warningnames[p].name))
2528 qccwarningdisabled[warningnames[p].index] = true;
2534 for (p = 0; warningnames[p].name; p++)
2535 if (!stricmp(myargv[i]+2, warningnames[p].name))
2537 qccwarningdisabled[warningnames[p].index] = false;
2542 if (!warningnames[p].name)
2543 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised warning parameter (%s)", myargv[i]);
2557 char qccmfilename[1024];
2558 char qccmprogsdat[1024];
2559 char qccmsourcedir[1024];
2561 void QCC_FinishCompile(void);
2564 void SetEndian(void);
2568 void QCC_SetDefaultProperties (void)
2573 Hash_InitTable(&compconstantstable, MAX_CONSTANTS, qccHunkAlloc(Hash_BytesForBuckets(MAX_CONSTANTS)));
2578 QCC_PR_DefineName("FTEQCC");
2580 if (QCC_CheckParm("/Oz"))
2582 qcc_targetformat = QCF_FTE;
2583 QCC_PR_DefineName("OP_COMP_STATEMENTS");
2584 QCC_PR_DefineName("OP_COMP_DEFS");
2585 QCC_PR_DefineName("OP_COMP_FIELDS");
2586 QCC_PR_DefineName("OP_COMP_FUNCTIONS");
2587 QCC_PR_DefineName("OP_COMP_STRINGS");
2588 QCC_PR_DefineName("OP_COMP_GLOBALS");
2589 QCC_PR_DefineName("OP_COMP_LINES");
2590 QCC_PR_DefineName("OP_COMP_TYPES");
2593 if (QCC_CheckParm("/O0") || QCC_CheckParm("-O0"))
2595 else if (QCC_CheckParm("/O1") || QCC_CheckParm("-O1"))
2597 else if (QCC_CheckParm("/O2") || QCC_CheckParm("-O2"))
2599 else if (QCC_CheckParm("/O3") || QCC_CheckParm("-O3"))
2606 for (i = 0; optimisations[i].enabled; i++)
2608 if (optimisations[i].flags & FLAG_ASDEFAULT)
2609 *optimisations[i].enabled = true;
2611 *optimisations[i].enabled = false;
2616 for (i = 0; optimisations[i].enabled; i++)
2618 if (level >= optimisations[i].optimisationlevel)
2619 *optimisations[i].enabled = true;
2621 *optimisations[i].enabled = false;
2625 if (QCC_CheckParm ("-h2"))
2626 qcc_targetformat = QCF_HEXEN2;
2627 else if (QCC_CheckParm ("-fte"))
2628 qcc_targetformat = QCF_FTE;
2629 else if (QCC_CheckParm ("-dp"))
2630 qcc_targetformat = QCF_DARKPLACES;
2632 qcc_targetformat = QCF_STANDARD;
2635 //enable all warnings
2636 memset(qccwarningdisabled, 0, sizeof(qccwarningdisabled));
2638 //play with default warnings.
2639 qccwarningdisabled[WARN_NOTREFERENCEDCONST] = true;
2640 qccwarningdisabled[WARN_MACROINSTRING] = true;
2641 // qccwarningdisabled[WARN_ASSIGNMENTTOCONSTANT] = true;
2642 qccwarningdisabled[WARN_FIXEDRETURNVALUECONFLICT] = true;
2643 qccwarningdisabled[WARN_EXTRAPRECACHE] = true;
2644 qccwarningdisabled[WARN_DEADCODE] = true;
2645 qccwarningdisabled[WARN_INEFFICIENTPLUSPLUS] = true;
2646 qccwarningdisabled[WARN_FTE_SPECIFIC] = true;
2647 qccwarningdisabled[WARN_EXTENSION_USED] = true;
2648 qccwarningdisabled[WARN_IFSTRING_USED] = true;
2652 if (QCC_CheckParm("-nowarn") || QCC_CheckParm("-Wnone"))
2653 memset(qccwarningdisabled, 1, sizeof(qccwarningdisabled));
2654 if (QCC_CheckParm("-Wall"))
2655 memset(qccwarningdisabled, 0, sizeof(qccwarningdisabled));
2657 if (QCC_CheckParm("-h2"))
2658 qccwarningdisabled[WARN_CASEINSENSATIVEFRAMEMACRO] = true;
2660 //Check the command line
2661 QCC_PR_CommandLinePrecompilerOptions();
2664 if (qcc_targetformat == QCF_HEXEN2) //force on the thinktime keyword if hexen2 progs.
2665 keyword_thinktime = true;
2667 if (QCC_CheckParm("/Debug")) //disable any debug optimisations
2669 for (i = 0; optimisations[i].enabled; i++)
2671 if (optimisations[i].flags & FLAG_KILLSDEBUGGERS)
2672 *optimisations[i].enabled = false;
2677 //builds a list of files, pretends that they came from a progs.src
2678 int QCC_FindQCFiles()
2685 int numfiles = 0, i, j;
2686 char *filelist[256], *temp;
2689 qccmsrc = qccHunkAlloc(8192);
2690 strcat(qccmsrc, "progs.dat\n");//"#pragma PROGS_DAT progs.dat\n");
2693 h = FindFirstFile("*.qc", &fd);
2694 if (h == INVALID_HANDLE_VALUE)
2699 filelist[numfiles] = qccHunkAlloc (strlen(fd.cFileName)+1);
2700 strcpy(filelist[numfiles], fd.cFileName);
2702 } while(FindNextFile(h, &fd)!=0);
2705 printf("-Facc is not supported on this platform. Please make a progs.src file instead\n");
2708 //Sort alphabetically.
2711 for (i = 0; i < numfiles-1; i++)
2713 for (j = i+1; j < numfiles; j++)
2715 if (stricmp(filelist[i], filelist[j]) > 0)
2718 filelist[j] = filelist[i];
2723 for (i = 0; i < numfiles; i++)
2725 strcat(qccmsrc, filelist[i]);
2726 strcat(qccmsrc, "\n");
2727 // strcat(qccmsrc, "#include \"");
2728 // strcat(qccmsrc, filelist[i]);
2729 // strcat(qccmsrc, "\"\n");
2735 int qcc_compileactive = false;
2736 extern int accglobalsblock;
2737 char *originalqccmsrc; //for autoprototype.
2738 void QCC_main (int argc, char **argv) //as part of the quake engine
2740 extern int pr_bracelevel;
2745 char destfile2[1024], *s2;
2754 qcc_compileactive = true;
2756 pHash_Get = &Hash_Get;
2757 pHash_GetNext = &Hash_GetNext;
2758 pHash_Add = &Hash_Add;
2761 MAX_STRINGS = 1000000;
2762 MAX_GLOBALS = 32768;
2764 MAX_STATEMENTS = 0x80000;
2765 MAX_FUNCTIONS = 16384;
2766 maxtypeinfos = 16384;
2767 MAX_CONSTANTS = 2048;
2771 p = externs->FileSize("qcc.cfg");
2773 p = externs->FileSize("src/qcc.cfg");
2776 s = qccHunkAlloc(p+1);
2777 s = externs->ReadFile("qcc.cfg", s, p);
2781 s = QCC_COM_Parse(s);
2782 if (!strcmp(qcc_token, "MAX_REGS"))
2784 s = QCC_COM_Parse(s);
2785 MAX_REGS = atoi(qcc_token);
2786 } else if (!strcmp(qcc_token, "MAX_STRINGS")) {
2787 s = QCC_COM_Parse(s);
2788 MAX_STRINGS = atoi(qcc_token);
2789 } else if (!strcmp(qcc_token, "MAX_GLOBALS")) {
2790 s = QCC_COM_Parse(s);
2791 MAX_GLOBALS = atoi(qcc_token);
2792 } else if (!strcmp(qcc_token, "MAX_FIELDS")) {
2793 s = QCC_COM_Parse(s);
2794 MAX_FIELDS = atoi(qcc_token);
2795 } else if (!strcmp(qcc_token, "MAX_STATEMENTS")) {
2796 s = QCC_COM_Parse(s);
2797 MAX_STATEMENTS = atoi(qcc_token);
2798 } else if (!strcmp(qcc_token, "MAX_FUNCTIONS")) {
2799 s = QCC_COM_Parse(s);
2800 MAX_FUNCTIONS = atoi(qcc_token);
2801 } else if (!strcmp(qcc_token, "MAX_TYPES")) {
2802 s = QCC_COM_Parse(s);
2803 maxtypeinfos = atoi(qcc_token);
2804 } else if (!strcmp(qcc_token, "MAX_TEMPS")) {
2805 s = QCC_COM_Parse(s);
2806 max_temps = atoi(qcc_token);
2807 } else if (!strcmp(qcc_token, "CONSTANTS")) {
2808 s = QCC_COM_Parse(s);
2809 MAX_CONSTANTS = atoi(qcc_token);
2814 printf("Bad token in qcc.cfg file\n");
2817 /* don't try to be clever
2820 s = qccHunkAlloc(8192);
2821 sprintf(s, "MAX_REGS\t%i\r\nMAX_STRINGS\t%i\r\nMAX_GLOBALS\t%i\r\nMAX_FIELDS\t%i\r\nMAX_STATEMENTS\t%i\r\nMAX_FUNCTIONS\t%i\r\nMAX_TYPES\t%i\r\n",
2822 MAX_REGS, MAX_STRINGS, MAX_GLOBALS, MAX_FIELDS, MAX_STATEMENTS, MAX_FUNCTIONS, maxtypeinfos);
2823 externs->WriteFile("qcc.cfg", s, strlen(s));
2827 strcpy(QCC_copyright, "This file was created with ForeThought's modified QuakeC compiler\nThanks to ID Software");
2828 for (p = 0; p < 5; p++)
2829 strcpy(QCC_Packname[p], "");
2831 for (p = 0; compiler_flag[p].enabled; p++)
2833 *compiler_flag[p].enabled = compiler_flag[p].flags & FLAG_ASDEFAULT;
2837 QCC_SetDefaultProperties();
2839 optres_shortenifnots = 0;
2840 optres_overlaptemps = 0;
2841 optres_noduplicatestrings = 0;
2842 optres_constantarithmatic = 0;
2843 optres_nonvec_parms = 0;
2844 optres_constant_names = 0;
2845 optres_constant_names_strings = 0;
2846 optres_precache_file = 0;
2847 optres_filenames = 0;
2848 optres_assignments = 0;
2849 optres_unreferenced = 0;
2850 optres_function_names = 0;
2852 optres_dupconstdefs = 0;
2853 optres_return_only = 0;
2854 optres_compound_jumps = 0;
2855 // optres_comexprremoval = 0;
2856 optres_stripfunctions = 0;
2857 optres_locals_marshalling = 0;
2858 optres_logicops = 0;
2863 accglobalsblock = 0;
2870 strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS);
2873 statements = (void *)qccHunkAlloc(sizeof(QCC_dstatement_t) * MAX_STATEMENTS);
2875 statement_linenums = (void *)qccHunkAlloc(sizeof(int) * MAX_STATEMENTS);
2877 functions = (void *)qccHunkAlloc(sizeof(QCC_dfunction_t) * MAX_FUNCTIONS);
2882 qcc_pr_globals = (void *)qccHunkAlloc(sizeof(float) * MAX_REGS);
2885 Hash_InitTable(&globalstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2886 Hash_InitTable(&localstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2887 Hash_InitTable(&floatconstdefstable, MAX_REGS+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS+1)));
2888 Hash_InitTable(&stringconstdefstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2889 Hash_InitTable(&stringconstdefstable_dotranslate, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2891 dotranslate_count=0;
2893 // pr_global_defs = (QCC_def_t **)qccHunkAlloc(sizeof(QCC_def_t *) * MAX_REGS);
2895 qcc_globals = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_GLOBALS);
2898 fields = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_FIELDS);
2901 memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
2903 precache_sounds = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_SOUNDS);
2904 precache_sounds_block = (void *)qccHunkAlloc(sizeof(int)*MAX_SOUNDS);
2905 precache_sounds_used = (void *)qccHunkAlloc(sizeof(int)*MAX_SOUNDS);
2908 precache_textures = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_TEXTURES);
2909 precache_textures_block = (void *)qccHunkAlloc(sizeof(int)*MAX_TEXTURES);
2912 precache_models = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_MODELS);
2913 precache_models_block = (void *)qccHunkAlloc(sizeof(int)*MAX_MODELS);
2914 precache_models_used = (void *)qccHunkAlloc(sizeof(int)*MAX_MODELS);
2917 precache_files = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_FILES);
2918 precache_files_block = (void *)qccHunkAlloc(sizeof(int)*MAX_FILES);
2921 qcc_typeinfo = (void *)qccHunkAlloc(sizeof(QCC_type_t)*maxtypeinfos);
2924 qcc_tempofs = qccHunkAlloc(sizeof(int) * max_temps);
2929 memset(&pr, 0, sizeof(pr));
2930 #ifdef MAX_EXTRA_PARMS
2931 memset(&extra_parms, 0, sizeof(extra_parms));
2934 if ( QCC_CheckParm ("/?") || QCC_CheckParm ("?") || QCC_CheckParm ("-?") || QCC_CheckParm ("-help") || QCC_CheckParm ("--help"))
2936 printf ("qcc looks for progs.src in the current directory.\n");
2937 printf ("to look in a different directory: qcc -src <directory>\n");
2938 // printf ("to build a clean data tree: qcc -copy <srcdir> <destdir>\n");
2939 // printf ("to build a clean pak file: qcc -pak <srcdir> <packfile>\n");
2940 // printf ("to bsp all bmodels: qcc -bspmodels <gamedir>\n");
2941 printf ("-Fwasm <funcname> causes FTEQCC to dump all asm to qc.asm\n");
2942 printf ("-O0 to disable optimisations\n");
2943 printf ("-O1 to optimise for size\n");
2944 printf ("-O2 to optimise more - some behaviours may change\n");
2945 printf ("-O3 to optimise lots - experimental or non-future-proof\n");
2946 printf ("-Oname to enable an optimisation\n");
2947 printf ("-Ono-name to disable optimisations\n");
2948 printf ("-Kkeyword to activate keyword\n");
2949 printf ("-Kno-keyword to disable keyword\n");
2950 printf ("-Wall to give a stupid number of warnings\n");
2951 printf ("-Ttarget to set a output format\n");
2952 printf ("-Fautoproto to enable automatic prototyping\n");
2953 printf ("-Fsubscope to enable subscopes\n");
2955 qcc_compileactive = false;
2959 if (flag_caseinsensative)
2961 printf("Compiling without case sensativity\n");
2962 pHash_Get = &Hash_GetInsensative;
2963 pHash_GetNext = &Hash_GetNextInsensative;
2964 pHash_Add = &Hash_AddInsensative;
2968 if (opt_locals_marshalling)
2969 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nLocals marshalling might be buggy. Use with caution\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
2971 p = QCC_CheckParm ("-src");
2972 if (p && p < argc-1 )
2974 strcpy (qccmsourcedir, argv[p+1]);
2975 strcat (qccmsourcedir, "/");
2976 printf ("Source directory: %s\n", qccmsourcedir);
2979 *qccmsourcedir = '\0';
2983 QCC_PR_BeginCompilation ((void *)qccHunkAlloc (0x100000), 0x100000);
2987 if (!QCC_FindQCFiles())
2988 QCC_Error (ERR_COULDNTOPENFILE, "Couldn't open file for asm output.");
2992 if (!numsourcefiles)
2994 p = QCC_CheckParm ("-qc");
2995 if (!p || p >= argc-1 || argv[p+1][0] == '-')
2996 p = QCC_CheckParm ("-srcfile");
2997 if (p && p < argc-1 )
2998 sprintf (qccmprogsdat, "%s%s", qccmsourcedir, argv[p+1]);
3000 { //look for a preprogs.src... :o)
3001 sprintf (qccmprogsdat, "%spreprogs.src", qccmsourcedir);
3002 if (externs->FileSize(qccmprogsdat) <= 0)
3003 sprintf (qccmprogsdat, "%sprogs.src", qccmsourcedir);
3007 strcpy(sourcefileslist[numsourcefiles++], qccmprogsdat);
3008 currentsourcefile = 0;
3010 else if (currentsourcefile == numsourcefiles)
3013 qcc_compileactive = false;
3015 currentsourcefile = 0;
3019 if (currentsourcefile)
3020 printf("-------------------------------------\n");
3022 strcpy(qccmprogsdat, sourcefileslist[currentsourcefile++]);
3024 printf ("Source file: %s\n", qccmprogsdat);
3026 if (QCC_LoadFile (qccmprogsdat, (void *)&qccmsrc) == -1)
3035 asmfile = fopen("qc.asm", "wb");
3037 QCC_Error (ERR_INTERNAL, "Couldn't open file for asm output.");
3041 newstylesource = false;
3042 while(*qccmsrc && *qccmsrc < ' ')
3044 pr_file_p = QCC_COM_Parse(qccmsrc);
3046 if (QCC_CheckParm ("-qc"))
3048 strcpy(destfile, qccmprogsdat);
3049 StripExtension(destfile);
3050 strcat(destfile, ".qco");
3052 p = QCC_CheckParm ("-o");
3053 if (!p || p >= argc-1 || argv[p+1][0] == '-')
3054 if (p && p < argc-1 )
3055 sprintf (destfile, "%s%s", qccmsourcedir, argv[p+1]);
3059 if (*qcc_token == '#')
3061 void StartNewStyleCompile(void);
3063 newstylesource = true;
3064 StartNewStyleCompile();
3068 pr_file_p = qccmsrc;
3069 QCC_PR_LexWhitespace();
3070 qccmsrc = pr_file_p;
3073 pr_file_p = qccmsrc;
3074 QCC_PR_SimpleGetToken ();
3075 strcpy(qcc_token, pr_token);
3076 qccmsrc = pr_file_p;
3079 QCC_Error (ERR_NOOUTPUT, "No destination filename. qcc -help for info.");
3080 strcpy (destfile, qcc_token);
3084 s2 = strcpy(destfile2, destfile);
3085 if (!strncmp(s2, "./", 2))
3089 while(!strncmp(s2, "../", 3))
3095 strcpy(qccmfilename, qccmsourcedir);
3096 for (s=qccmfilename+strlen(qccmfilename);p && s>=qccmfilename; s--)
3098 if (*s == '/' || *s == '\\')
3104 sprintf(destfile, "%s", s2);
3108 memmove(destfile+3, destfile, strlen(destfile)+1);
3116 printf ("outputfile: %s\n", destfile);
3120 currentchunk = NULL;
3122 originalqccmsrc = qccmsrc;
3125 void new_QCC_ContinueCompile(void);
3126 //called between exe frames - won't loose net connection (is the theory)...
3127 void QCC_ContinueCompile(void)
3130 currentchunk = NULL;
3131 if (!qcc_compileactive)
3137 new_QCC_ContinueCompile();
3141 qccmsrc = QCC_COM_Parse(qccmsrc);
3146 qccmsrc = originalqccmsrc;
3147 QCC_SetDefaultProperties();
3148 autoprototype = false;
3151 QCC_FinishCompile();
3156 QCC_main(myargc, myargv);
3161 strcpy (qccmfilename, qccmsourcedir);
3164 if (!strncmp(s, "..\\", 3))
3166 s2 = qccmfilename + strlen(qccmfilename)-2;
3167 while (s2>=qccmfilename)
3169 if (*s2 == '/' || *s2 == '\\')
3179 if (!strncmp(s, ".\\", 2))
3187 strcat (qccmfilename, s);
3189 printf ("prototyping %s\n", qccmfilename);
3192 printf ("compiling %s\n", qccmfilename);
3194 QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
3196 if (!QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
3197 QCC_Error (ERR_PARSEERRORS, "Errors have occured\n");
3199 void QCC_FinishCompile(void)
3201 pbool donesomething;
3204 currentchunk = NULL;
3206 if (setjmp(pr_parse_abort))
3207 QCC_Error(ERR_INTERNAL, "");
3209 if (!QCC_PR_FinishCompilation ())
3211 QCC_Error (ERR_PARSEERRORS, "compilation errors");
3214 /* p = QCC_CheckParm ("-asm");
3217 for (p++ ; p<myargc ; p++)
3219 if (myargv[p][0] == '-')
3221 QCC_PrintFunction (myargv[p]);
3225 /*p = QCC_CheckParm ("-ofs");
3228 for (p++ ; p<myargc ; p++)
3230 if (myargv[p][0] == '-')
3232 QCC_PrintOfs (atoi(myargv[p]));
3236 if (pr_werror && pr_warning_count != 0)
3237 QCC_Error (ERR_PARSEERRORS, "compilation errors");
3240 crc = QCC_PR_WriteProgdefs ("progdefs.h");
3243 donesomething = QCC_WriteData (crc);
3245 // regenerate bmodels if -bspmodels
3248 // report / copy the data files
3255 printf ("Compile Complete\n\n");
3257 if (optres_shortenifnots)
3258 printf("optres_shortenifnots %i\n", optres_shortenifnots);
3259 if (optres_overlaptemps)
3260 printf("optres_overlaptemps %i\n", optres_overlaptemps);
3261 if (optres_noduplicatestrings)
3262 printf("optres_noduplicatestrings %i\n", optres_noduplicatestrings);
3263 if (optres_constantarithmatic)
3264 printf("optres_constantarithmatic %i\n", optres_constantarithmatic);
3265 if (optres_nonvec_parms)
3266 printf("optres_nonvec_parms %i\n", optres_nonvec_parms);
3267 if (optres_constant_names)
3268 printf("optres_constant_names %i\n", optres_constant_names);
3269 if (optres_constant_names_strings)
3270 printf("optres_constant_names_strings %i\n", optres_constant_names_strings);
3271 if (optres_precache_file)
3272 printf("optres_precache_file %i\n", optres_precache_file);
3273 if (optres_filenames)
3274 printf("optres_filenames %i\n", optres_filenames);
3275 if (optres_assignments)
3276 printf("optres_assignments %i\n", optres_assignments);
3277 if (optres_unreferenced)
3278 printf("optres_unreferenced %i\n", optres_unreferenced);
3280 printf("optres_locals %i\n", optres_locals);
3281 if (optres_function_names)
3282 printf("optres_function_names %i\n", optres_function_names);
3283 if (optres_dupconstdefs)
3284 printf("optres_dupconstdefs %i\n", optres_dupconstdefs);
3285 if (optres_return_only)
3286 printf("optres_return_only %i\n", optres_return_only);
3287 if (optres_compound_jumps)
3288 printf("optres_compound_jumps %i\n", optres_compound_jumps);
3289 // if (optres_comexprremoval)
3290 // printf("optres_comexprremoval %i\n", optres_comexprremoval);
3291 if (optres_stripfunctions)
3292 printf("optres_stripfunctions %i\n", optres_stripfunctions);
3293 if (optres_locals_marshalling)
3294 printf("optres_locals_marshalling %i\n", optres_locals_marshalling);
3295 if (optres_logicops)
3296 printf("optres_logicops %i\n", optres_logicops);
3300 printf("optres_test1 %i\n", optres_test1);
3302 printf("optres_test2 %i\n", optres_test2);
3304 printf("numtemps %i\n", numtemps);
3306 if (!flag_msvcstyle)
3307 printf("%i warnings\n", pr_warning_count);
3310 qcc_compileactive = false;
3317 extern char *compilingfile;
3318 extern QCC_string_t s_file, s_file2;
3319 extern char *pr_file_p;
3320 extern int pr_source_line;
3321 extern QCC_def_t *pr_scope;
3322 void QCC_PR_ParseDefs (char *classname);
3328 void StartNewStyleCompile(void)
3330 if (setjmp(pr_parse_abort))
3332 if (++pr_error_count > MAX_ERRORS)
3334 if (setjmp(pr_parse_abort))
3337 QCC_PR_SkipToSemicolon ();
3338 if (pr_token_type == tt_eof)
3343 QCC_PR_ClearGrabMacros (); // clear the frame macros
3345 compilingfile = qccmprogsdat;
3347 pr_file_p = qccmsrc;
3348 s_file = s_file2 = QCC_CopyString (compilingfile);
3352 QCC_PR_NewLine (false);
3354 QCC_PR_Lex (); // read first token
3356 void new_QCC_ContinueCompile(void)
3358 if (setjmp(pr_parse_abort))
3360 // if (pr_error_count != 0)
3362 QCC_Error (ERR_PARSEERRORS, "Errors have occured");
3365 QCC_PR_SkipToSemicolon ();
3366 if (pr_token_type == tt_eof)
3370 if (pr_token_type == tt_eof)
3373 QCC_Error (ERR_PARSEERRORS, "Errors have occured");
3374 QCC_FinishCompile();
3379 QCC_main(myargc, myargv);
3383 pr_scope = NULL; // outside all functions
3385 QCC_PR_ParseDefs (NULL);
3388 /*void new_QCC_ContinueCompile(void)
3391 if (!qcc_compileactive)
3395 // compile all the files
3397 qccmsrc = QCC_COM_Parse(qccmsrc);
3400 QCC_FinishCompile();
3405 strcpy (qccmfilename, qccmsourcedir);
3408 if (!strncmp(s, "..\\", 3))
3410 s2 = qccmfilename + strlen(qccmfilename)-2;
3411 while (s2>=qccmfilename)
3413 if (*s2 == '/' || *s2 == '\\')
3423 if (!strncmp(s, ".\\", 2))
3431 // strcat (qccmfilename, s);
3432 // printf ("compiling %s\n", qccmfilename);
3433 // QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
3435 // if (!new_QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
3436 // QCC_Error ("Errors have occured\n");
3442 QCC_Error ("PR_CompileFile: Didn't clear");
3444 QCC_PR_ClearGrabMacros (); // clear the frame macros
3446 compilingfile = filename;
3448 pr_file_p = qccmsrc2;
3449 s_file = QCC_CopyString (filename);
3455 QCC_PR_Lex (); // read first token
3457 while (pr_token_type != tt_eof)
3459 if (setjmp(pr_parse_abort))
3461 if (++pr_error_count > MAX_ERRORS)
3463 QCC_PR_SkipToSemicolon ();
3464 if (pr_token_type == tt_eof)
3468 pr_scope = NULL; // outside all functions
3470 QCC_PR_ParseDefs ();
3473 return (pr_error_count == 0);