]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/mediasource/extra/fteqcc-src/qccmain.c
fteqcc source
[voretournament/voretournament.git] / misc / mediasource / extra / fteqcc-src / qccmain.c
1 #ifndef MINIMAL
2
3 #define PROGSUSED
4 #include "qcc.h"
5 int mkdir(const char *path);
6
7 char QCC_copyright[1024];
8 int QCC_packid;
9 char QCC_Packname[5][128];
10
11 extern QCC_def_t *functemps;            //floats/strings/funcs/ents...
12
13 extern int optres_test1;
14 extern int optres_test2;
15
16 int writeasm;
17 static pbool pr_werror;
18 pbool verbose;
19
20
21 pbool QCC_PR_SimpleGetToken (void);
22 void QCC_PR_LexWhitespace (void);
23
24 void *FS_ReadToMem(char *fname, void *membuf, int *len);
25 void FS_CloseFromMem(void *mem);
26
27 struct qcc_includechunk_s *currentchunk;
28
29 unsigned int MAX_REGS;
30
31 int     MAX_STRINGS;
32 int     MAX_GLOBALS;
33 int     MAX_FIELDS;
34 int     MAX_STATEMENTS;
35 int     MAX_FUNCTIONS;
36 int MAX_CONSTANTS;
37 int max_temps;
38
39 int *qcc_tempofs;
40 int tempsstart;
41 int numtemps;
42
43 #define MAXSOURCEFILESLIST 8
44 char sourcefileslist[MAXSOURCEFILESLIST][1024];
45 int currentsourcefile;
46 int numsourcefiles;
47
48 void QCC_PR_ResetErrorScope(void);
49
50 pbool   compressoutput;
51
52 pbool newstylesource;
53 char            destfile[1024];
54
55 float           *qcc_pr_globals;
56 unsigned int    numpr_globals;
57
58 char            *strings;
59 int                     strofs;
60
61 QCC_dstatement_t        *statements;
62 int                     numstatements;
63 int                     *statement_linenums;
64
65 QCC_dfunction_t *functions;
66 int                     numfunctions;
67
68 QCC_ddef_t              *qcc_globals;
69 int                     numglobaldefs;
70
71 QCC_ddef_t              *fields;
72 int                     numfielddefs;
73
74 //typedef char PATHSTRING[MAX_DATA_PATH];
75
76 PATHSTRING              *precache_sounds;
77 int                     *precache_sounds_block;
78 int                     numsounds;
79
80 PATHSTRING              *precache_textures;
81 int                     *precache_textures_block;
82 int                     numtextures;
83
84 PATHSTRING              *precache_models;
85 int                     *precache_models_block;
86 int                     nummodels;
87
88 PATHSTRING              *precache_files;
89 int                     *precache_files_block;
90 int                     numfiles;
91
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;
99 int dotranslate;
100 int dotranslate_count;
101
102 pbool qccwarningdisabled[WARN_MAX];
103
104 qcc_targetformat_t qcc_targetformat;
105
106 pbool bodylessfuncs;
107
108 QCC_type_t *qcc_typeinfo;
109 int numtypeinfos;
110 int maxtypeinfos;
111
112
113 struct {
114         char *name;
115         int index;
116 } warningnames[] =
117 {
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},
145         {NULL}
146 };
147
148 int QCC_WarningForName(char *name)
149 {
150         int i;
151         for (i = 0; warningnames[i].name; i++)
152         {
153                 if (!stricmp(name, warningnames[i].name))
154                         return warningnames[i].index;
155         }
156         return -1;
157 }
158
159 optimisations_t optimisations[] =
160 {
161         //level 0 = no optimisations
162         //level 1 = size optimisations
163         //level 2 = speed optimisations
164         //level 3 = dodgy optimisations.
165         //level 4 = experimental...
166
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."},
187         {NULL}
188 };
189
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[] = {
194         //keywords
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."},
223
224
225         //options
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)."},
241         {NULL}
242 };
243
244 struct {
245         qcc_targetformat_t target;
246         char *name;
247 } targets[] = {
248         {QCF_STANDARD,  "standard"},
249         {QCF_STANDARD,  "q1"},
250         {QCF_STANDARD,  "quakec"},
251         {QCF_HEXEN2,    "hexen2"},
252         {QCF_HEXEN2,    "h2"},
253         {QCF_KK7,               "kkqwsv"},
254         {QCF_KK7,               "kk7"},
255         {QCF_KK7,               "bigprogs"},
256         {QCF_KK7,               "version7"},
257         {QCF_KK7,               "kkqwsv"},
258         {QCF_FTE,               "fte"},
259         {QCF_DARKPLACES,"darkplaces"},
260         {QCF_DARKPLACES,"dp"},
261         {0,                             NULL}
262 };
263
264 /*
265 =================
266 BspModels
267
268 Runs qbsp and light on all of the models with a .bsp extension
269 =================
270 */
271 int QCC_CheckParm (char *check);
272
273 void QCC_BspModels (void)
274 {
275         int             p;
276         char    *gamedir;
277         int             i;
278         char    *m;
279         char    cmd[1024];
280         char    name[256];
281
282         p = QCC_CheckParm ("-bspmodels");
283         if (!p)
284                 return;
285         if (p == myargc-1)
286                 QCC_Error (ERR_BADPARMS, "-bspmodels must preceed a game directory");
287         gamedir = myargv[p+1];
288         
289         for (i=0 ; i<nummodels ; i++)
290         {
291                 m = precache_models[i];
292                 if (strcmp(m+strlen(m)-4, ".bsp"))
293                         continue;
294                 strcpy (name, m);
295                 name[strlen(m)-4] = 0;
296                 sprintf (cmd, "qbsp %s/%s ; light -extra %s/%s", gamedir, name, gamedir, name);
297                 system (cmd);
298         }
299 }
300
301 // CopyString returns an offset from the string heap
302 int     QCC_CopyString (char *str)
303 {
304         int             old;
305         char *s;
306
307         if (opt_noduplicatestrings)
308         {
309                 if (!str || !*str)
310                         return 0;
311
312                 for (s = strings; s < strings+strofs; s++)
313                         if (!strcmp(s, str))
314                         {
315                                 optres_noduplicatestrings += strlen(str);
316                                 return s-strings;
317                         }
318         }
319
320         old = strofs;
321         strcpy (strings+strofs, str);
322         strofs += strlen(str)+1;
323         return old;
324 }
325
326 int     QCC_CopyDupBackString (char *str)
327 {
328         int             old;
329         char *s;
330
331         for (s = strings+strofs-1; s>strings ; s--)
332                 if (!strcmp(s, str))
333                         return s-strings;
334         
335         old = strofs;
336         strcpy (strings+strofs, str);
337         strofs += strlen(str)+1;
338         return old;
339 }
340
341 void QCC_PrintStrings (void)
342 {
343         int             i, l, j;
344         
345         for (i=0 ; i<strofs ; i += l)
346         {
347                 l = strlen(strings+i) + 1;
348                 printf ("%5i : ",i);
349                 for (j=0 ; j<l ; j++)
350                 {
351                         if (strings[i+j] == '\n')
352                         {
353                                 putchar ('\\');
354                                 putchar ('n');
355                         }
356                         else
357                                 putchar (strings[i+j]);
358                 }
359                 printf ("\n");
360         }
361 }
362
363
364 /*void QCC_PrintFunctions (void)
365 {
366         int             i,j;
367         QCC_dfunction_t *d;
368         
369         for (i=0 ; i<numfunctions ; i++)
370         {
371                 d = &functions[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]);
375                 printf (")\n");
376         }
377 }*/
378
379 void QCC_PrintFields (void)
380 {
381         int             i;
382         QCC_ddef_t      *d;
383         
384         for (i=0 ; i<numfielddefs ; i++)
385         {
386                 d = &fields[i];
387                 printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
388         }
389 }
390
391 void QCC_PrintGlobals (void)
392 {
393         int             i;
394         QCC_ddef_t      *d;
395         
396         for (i=0 ; i<numglobaldefs ; i++)
397         {
398                 d = &qcc_globals[i];
399                 printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
400         }
401 }
402
403 int encode(int len, int method, char *in, int handle);
404 int WriteSourceFiles(int h, dprograms_t *progs, pbool sourceaswell)
405 {
406         includeddatafile_t *idf;
407         qcc_cachedsourcefile_t *f;
408         int num=0;
409         int ofs;
410
411         /*
412         for (f = qcc_sourcefile; f ; f=f->next)
413         {
414                 if (f->type == FT_CODE && !sourceaswell)
415                         continue;
416
417                 SafeWrite(h, f->filename, strlen(f->filename)+1);
418                 i = PRLittleLong(f->size);
419                 SafeWrite(h, &i, sizeof(int));
420
421                 i = PRLittleLong(encrpytmode);
422                 SafeWrite(h, &i, sizeof(int));
423
424                 if (encrpytmode)
425                         for (i = 0; i < f->size; i++)
426                                 f->file[i] ^= 0xA5;
427
428                 SafeWrite(h, f->file, f->size);
429         }*/
430
431         for (f = qcc_sourcefile,num=0; f ; f=f->next)
432         {
433                 if (f->type == FT_CODE && !sourceaswell)
434                         continue;
435
436                 num++;
437         }
438         if (!num)
439                 return 0;
440         idf = qccHunkAlloc(sizeof(includeddatafile_t)*num);
441         for (f = qcc_sourcefile,num=0; f ; f=f->next)
442         {
443                 if (f->type == FT_CODE && !sourceaswell)
444                         continue;
445
446                 strcpy(idf[num].filename, f->filename);
447                 idf[num].size = f->size;
448 #ifdef AVAIL_ZLIB
449                 idf[num].compmethod = 2;
450 #else
451                 idf[num].compmethod = 1;
452 #endif
453                 idf[num].ofs = SafeSeek(h, 0, SEEK_CUR);
454                 idf[num].compsize = QC_encode(progfuncs, f->size, idf[num].compmethod, f->file, h);
455                 num++;
456         }
457
458         ofs = SafeSeek(h, 0, SEEK_CUR); 
459         SafeWrite(h, &num, sizeof(int));
460         SafeWrite(h, idf, sizeof(includeddatafile_t)*num);
461
462         qcc_sourcefile = NULL;
463
464         return ofs;
465 }
466
467 void QCC_InitData (void)
468 {
469         static char parmname[12][MAX_PARMS];
470         static temp_t ret_temp;
471         int             i;
472
473         qcc_sourcefile = NULL;
474         
475         numstatements = 1;
476         strofs = 1;
477         numfunctions = 1;
478         numglobaldefs = 1;
479         numfielddefs = 1;
480
481         memset(&ret_temp, 0, sizeof(ret_temp));
482         
483         def_ret.ofs = OFS_RETURN;
484         def_ret.name = "return";
485         def_ret.temp = &ret_temp;
486         def_ret.constant = false;
487         def_ret.type    = NULL;
488         ret_temp.ofs = def_ret.ofs;
489         ret_temp.scope = NULL;
490         ret_temp.size = 3;
491         ret_temp.next = NULL;
492         for (i=0 ; i<MAX_PARMS ; i++)
493         {
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);
499         }
500 }
501
502 int WriteBodylessFuncs (int handle)
503 {
504         QCC_def_t               *d;
505         int ret=0;
506         for (d=pr.def_head.next ; d ; d=d->next)
507         {
508                 if (d->type->type == ev_function && !d->scope)// function parms are ok
509                 {
510                         if (d->initialized != 1 && d->references>0)
511                         {
512                                 SafeWrite(handle, d->name, strlen(d->name)+1);
513                                 ret++;
514                         }
515                 }
516         }
517
518         return ret;
519 }
520
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)
524 {
525         QCC_def_t               *def;
526         unsigned int ofs;
527         unsigned int maxo;
528         int i;
529
530         ofs = numpr_globals;
531         maxo = ofs;
532
533         for (def = pr.def_head.next ; def ; def = def->next)
534         {
535                 if (def->ofs >= MAX_REGS)       //unmap defs.
536                 {
537                         def->ofs = def->ofs + ofs - MAX_REGS;
538                         if (maxo < def->ofs)
539                                 maxo = def->ofs;
540                 }
541         }
542
543         for (i = 0; i < numfunctions; i++)
544         {
545                 if (functions[i].parm_start == MAX_REGS)
546                         functions[i].parm_start = ofs;
547         }
548
549         QCC_RemapOffsets(0, numstatements, MAX_REGS, MAX_REGS + maxo-numpr_globals + 3, ofs);
550
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");
554
555         if (maxo-ofs)
556                 printf("Total of %i marshalled globals\n", maxo-ofs);
557 }
558
559 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def);
560 pbool QCC_WriteData (int crc)
561 {
562         char element[MAX_NAME];
563         QCC_def_t               *def, *comp_x, *comp_y, *comp_z;
564         QCC_ddef_t              *dd;
565         dprograms_t     progs;
566         int                     h;
567         int                     i, len;
568         pbool debugtarget = false;
569         pbool types = false;
570         int outputsize = 16;
571
572         if (numstatements==1 && numfunctions==1 && numglobaldefs==1 && numfielddefs==1)
573         {
574                 printf("nothing to write\n");
575                 return false;
576         }
577
578         progs.blockscompressed=0;
579
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);
582
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);
585
586         QCC_UnmarshalLocals();
587
588         switch (qcc_targetformat)
589         {
590         case QCF_HEXEN2:
591         case QCF_STANDARD:
592                 if (bodylessfuncs)
593                         printf("Warning: There are some functions without bodies.\n");
594
595                 if (numpr_globals > 65530 )
596                 {
597                         printf("Forcing target to FTE32 due to numpr_globals\n");
598                         outputsize = 32;
599                 }
600                 else if (qcc_targetformat == QCF_HEXEN2)
601                 {
602                         printf("Progs execution requires a Hexen2 compatible engine\n");
603                         break;
604                 }
605                 else
606                 {
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");
609                         else
610                                 printf("Progs should run on any Quake executor\n");
611                         break;
612                 }
613                 //intentional
614                 qcc_targetformat = QCF_FTE;
615         case QCF_FTEDEBUG:
616         case QCF_FTE:
617         case QCF_DARKPLACES:
618                 if (qcc_targetformat == QCF_FTEDEBUG)
619                         debugtarget = true;
620
621                 if (numpr_globals > 65530)
622                 {
623                         printf("Using 32 bit target due to numpr_globals\n");
624                         outputsize = 32;
625                 }
626
627                 if (qcc_targetformat == QCF_DARKPLACES)
628                         compressoutput = 0;
629
630
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...).
642
643                 if (verbose)
644                 {
645                         if (qcc_targetformat == QCF_DARKPLACES)
646                                 printf("DarkPlaces or FTE will be required\n");
647                         else
648                                 printf("An FTE executor will be required\n");
649                 }
650                 break;
651         case QCF_KK7:
652                 if (bodylessfuncs)
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");
656
657                 printf("A KK compatible executor will be required (FTE/KK)\n");
658                 break;
659         }
660
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);
663         if (def)
664                 def->references++;
665
666         def = QCC_PR_GetDef(NULL, "end_sys_fields", NULL, false, 0, false);
667         if (def)
668                 def->references++;
669
670         for (def = pr.def_head.next ; def ; def = def->next)
671         {
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);
680
681                         h = def->references;
682                         if (comp_x && comp_y && comp_z)
683                         {
684                                 h += comp_x->references;
685                                 h += comp_y->references;
686                                 h += comp_z->references;
687
688                                 if (!def->references)
689                                         if (!comp_x->references || !comp_y->references || !comp_z->references)  //one of these vars is useless...
690                                                 h=0;
691
692                                 def->references = h;
693                                 
694                                         
695                                 if (!h)
696                                         h = 1;
697                                 if (comp_x)
698                                         comp_x->references = h;
699                                 if (comp_y)
700                                         comp_y->references = h;
701                                 if (comp_z)
702                                         comp_z->references = h;
703                         }
704                 }
705                 if (def->references<=0)
706                 {
707                         if (def->constant)
708                                 QCC_PR_Warning(WARN_NOTREFERENCEDCONST, strings + def->s_file, def->s_line, "%s  no references", def->name);
709                         else
710                                 QCC_PR_Warning(WARN_NOTREFERENCED, strings + def->s_file, def->s_line, "%s  no references", def->name);
711
712                         if (opt_unreferenced && def->type->type != ev_field)
713                         {
714                                 optres_unreferenced++;
715                                 continue;
716                         }
717                 }
718
719                 if (def->type->type == ev_function)
720                 {
721                         if (opt_function_names && functions[G_FUNCTION(def->ofs)].first_statement<0)
722                         {
723                                 optres_function_names++;
724                                 def->name = "";
725                         }
726                         if (!def->timescalled)
727                         {
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);
730 //                              else
731 //                                      QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called", def->name);
732                         }
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.
736                                 continue;
737                         }
738
739 //                      df = &functions[numfunctions];
740 //                      numfunctions++;
741
742                 }
743                 else if (def->type->type == ev_field)// && !def->constant)
744                 {
745                         dd = &fields[numfielddefs];
746                         numfielddefs++;
747                         dd->type = def->type->aux_type->type;
748                         dd->s_name = QCC_CopyString (def->name);
749                         dd->ofs = G_INT(def->ofs);
750                 }
751                 else if ((def->scope||def->constant) && (def->type->type != ev_string || opt_constant_names_strings))
752                 {
753                         if (opt_constant_names)
754                         {
755                                 if (def->type->type == ev_string)
756                                         optres_constant_names_strings += strlen(def->name);
757                                 else
758                                         optres_constant_names += strlen(def->name);
759                                 continue;
760                         }
761                 }
762
763 //              if (!def->saved && def->type->type != ev_string)
764 //                      continue;
765                 dd = &qcc_globals[numglobaldefs];
766                 numglobaldefs++;
767
768                 if (types)
769                         dd->type = def->type-qcc_typeinfo;
770                 else
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))
777                 {
778                         dd->type |= DEF_SAVEGLOBAL;
779                 }
780 #endif
781                 if (def->shared)
782                         dd->type |= DEF_SHARED;
783
784                 if (opt_locals && (def->scope || !strcmp(def->name, "IMMEDIATE")))
785                 {
786                         dd->s_name = 0;
787                         optres_locals += strlen(def->name);
788                 }
789                 else
790                         dd->s_name = QCC_CopyString (def->name);
791                 dd->ofs = def->ofs;
792         }
793
794         for (i = 0; i < numglobaldefs; i++)
795         {
796                 dd = &qcc_globals[i];
797                 if (!(dd->type & DEF_SAVEGLOBAL))       //only warn about saved ones.
798                         continue;
799
800                 for (h = 0; h < numglobaldefs; h++)
801                 {
802                         if (i == h)
803                                 continue;
804                         if (dd->ofs == qcc_globals[h].ofs)
805                         {
806                                 if (dd->type != qcc_globals[h].type)
807                                 {
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);
810                                 }
811                                 //remove the saveglobal flag on the duplicate globals.
812                                 qcc_globals[h].type &= ~DEF_SAVEGLOBAL;
813                         }
814                 }
815         }
816         for (i = 1; i < numfielddefs; i++)
817         {
818                 dd = &fields[i];
819
820                 if (dd->type == ev_vector)      //just ignore vectors.
821                         continue;
822
823                 for (h = 1; h < numfielddefs; h++)
824                 {
825                         if (i == h)
826                                 continue;
827                         if (dd->ofs == fields[h].ofs)
828                         {
829                                 if (dd->type != fields[h].type)
830                                 {
831                                         if (fields[h].type != ev_vector)
832                                         {
833                                                 QCC_PR_Warning(0, NULL, 0, "Mismatched union field types (%s and %s)", strings+dd->s_name, strings+fields[h].s_name);
834                                         }
835                                 }
836                         }
837                 }
838         }
839
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);
842
843
844         for (i = 0; i < nummodels; i++)
845         {
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]);
850         }
851 //PrintStrings ();
852 //PrintFunctions ();
853 //PrintFields ();
854 //PrintGlobals ();
855 strofs = (strofs+3)&~3;
856
857         if (verbose)
858         {
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);
865         }
866         
867         if (!*destfile)
868                 strcpy(destfile, "progs.dat");
869         if (verbose)
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
877         {
878                 SafeWrite (h, "\0", 1);
879         }
880
881         progs.ofs_strings = SafeSeek (h, 0, SEEK_CUR);
882         progs.numstrings = strofs;
883
884         if (progs.blockscompressed&16)
885         {               
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);
893         }
894         else
895                 SafeWrite (h, strings, strofs);
896
897         progs.ofs_statements = SafeSeek (h, 0, SEEK_CUR);
898         progs.numstatements = numstatements;
899
900         if (qcc_targetformat == QCF_HEXEN2)
901         {
902                 for (i=0 ; i<numstatements ; i++)
903                 {
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;
908                 }
909         }
910
911         for (i=0 ; i<numstatements ; i++)
912
913         switch(qcc_targetformat == QCF_KK7?32:outputsize)       //KK7 sucks.
914         {
915         case 32:
916                 for (i=0 ; i<numstatements ; i++)
917                 {
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);
922                 }
923                 
924                 if (progs.blockscompressed&1)
925                 {               
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);
933                 }
934                 else
935                         SafeWrite (h, statements, numstatements*sizeof(QCC_dstatement32_t));
936                 break;
937         case 16:
938 #define statements16 ((QCC_dstatement16_t*) statements)
939                 for (i=0 ; i<numstatements ; i++)       //resize as we go - scaling down
940                 {
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);
944                         else
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);
948                         else
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);
952                         else
953                                 statements16[i].c = (unsigned short)PRLittleShort((unsigned short)statements[i].c);
954                 }
955                 
956                 if (progs.blockscompressed&1)
957                 {               
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);
965                 }
966                 else
967                         SafeWrite (h, statements16, numstatements*sizeof(QCC_dstatement16_t));
968                 break;
969         default:
970                 Sys_Error("intsize error");
971         }
972
973         progs.ofs_functions = SafeSeek (h, 0, SEEK_CUR);
974         progs.numfunctions = numfunctions;
975         for (i=0 ; i<numfunctions ; i++)
976         {
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);
983         }
984
985         if (progs.blockscompressed&8)
986         {               
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);
994         }
995         else
996                 SafeWrite (h, functions, numfunctions*sizeof(QCC_dfunction_t));
997
998         switch(outputsize)
999         {
1000         case 32:
1001                 progs.ofs_globaldefs = SafeSeek (h, 0, SEEK_CUR);
1002                 progs.numglobaldefs = numglobaldefs;
1003                 for (i=0 ; i<numglobaldefs ; i++)
1004                 {
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);
1008                 }
1009
1010                 if (progs.blockscompressed&2)
1011                 {               
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);
1019                 }
1020                 else
1021                         SafeWrite (h, qcc_globals, numglobaldefs*sizeof(QCC_ddef_t));
1022
1023                 progs.ofs_fielddefs = SafeSeek (h, 0, SEEK_CUR);
1024                 progs.numfielddefs = numfielddefs;
1025
1026                 for (i=0 ; i<numfielddefs ; i++)
1027                 {
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);
1031                 }
1032
1033                 if (progs.blockscompressed&4)
1034                 {               
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);
1042                 }
1043                 else
1044                         SafeWrite (h, fields, numfielddefs*sizeof(QCC_ddef_t));
1045                 break;
1046         case 16:
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++)
1052                 {
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);
1056                 }
1057
1058                 if (progs.blockscompressed&2)
1059                 {               
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);
1067                 }
1068                 else
1069                         SafeWrite (h, qcc_globals16, numglobaldefs*sizeof(QCC_ddef16_t));
1070
1071                 progs.ofs_fielddefs = SafeSeek (h, 0, SEEK_CUR);
1072                 progs.numfielddefs = numfielddefs;
1073
1074                 for (i=0 ; i<numfielddefs ; i++)
1075                 {
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);
1079                 }
1080
1081                 if (progs.blockscompressed&4)
1082                 {               
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);
1090                 }
1091                 else
1092                         SafeWrite (h, fields16, numfielddefs*sizeof(QCC_ddef16_t));
1093                 break;
1094         default:
1095                 Sys_Error("intsize error");
1096         }
1097
1098         progs.ofs_globals = SafeSeek (h, 0, SEEK_CUR);
1099         progs.numglobals = numpr_globals;
1100
1101         for (i=0 ; (unsigned)i<numpr_globals ; i++)
1102                 ((int *)qcc_pr_globals)[i] = PRLittleLong (((int *)qcc_pr_globals)[i]);
1103
1104         if (progs.blockscompressed&32)
1105         {               
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);
1113         }
1114         else
1115                 SafeWrite (h, qcc_pr_globals, numpr_globals*4); 
1116
1117         if (types)
1118         for (i=0 ; i<numtypeinfos ; i++)
1119         {
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);
1125         }
1126
1127         progs.ofsfiles = 0;
1128         progs.ofslinenums = 0;
1129         progs.secondaryversion = 0;
1130         progs.ofsbodylessfuncs = 0;
1131         progs.numbodylessfuncs = 0;
1132         progs.ofs_types = 0;
1133         progs.numtypes = 0;
1134
1135         switch(qcc_targetformat)
1136         {
1137         case QCF_KK7:
1138                 progs.version = PROG_KKQWSVVERSION;
1139                 break;
1140         case QCF_STANDARD:
1141         case QCF_HEXEN2:        //urgh
1142                 progs.version = PROG_VERSION;
1143                 break;
1144         case QCF_DARKPLACES:
1145         case QCF_FTE:
1146         case QCF_FTEDEBUG:
1147                 progs.version = PROG_EXTENDEDVERSION;
1148
1149                 if (outputsize == 32)
1150                         progs.secondaryversion = PROG_SECONDARYVERSION32;
1151                 else
1152                         progs.secondaryversion = PROG_SECONDARYVERSION16;
1153
1154                 progs.ofsbodylessfuncs = SafeSeek (h, 0, SEEK_CUR);
1155                 progs.numbodylessfuncs = WriteBodylessFuncs(h);         
1156
1157                 if (debugtarget)
1158                 {
1159                         progs.ofslinenums = SafeSeek (h, 0, SEEK_CUR);
1160                         if (progs.blockscompressed&64)
1161                         {               
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);
1169                         }
1170                         else
1171                                 SafeWrite (h, statement_linenums, numstatements*sizeof(int));
1172                 }
1173                 else
1174                         progs.ofslinenums = 0;
1175
1176                 if (types)
1177                 {
1178                         progs.ofs_types = SafeSeek (h, 0, SEEK_CUR);
1179                         if (progs.blockscompressed&128)
1180                         {               
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);
1188                         }
1189                         else
1190                                 SafeWrite (h, qcc_typeinfo, sizeof(QCC_type_t)*numtypeinfos);
1191                         progs.numtypes = numtypeinfos;          
1192                 }
1193                 else
1194                 {
1195                         progs.ofs_types = 0;
1196                         progs.numtypes = 0;
1197                 }
1198
1199                 progs.ofsfiles = WriteSourceFiles(h, &progs, debugtarget);
1200                 break;
1201         }
1202
1203         if (verbose)
1204                 printf ("%6i TOTAL SIZE\n", (int)SafeSeek (h, 0, SEEK_CUR));
1205
1206         progs.entityfields = pr.size_fields;
1207
1208         progs.crc = crc;
1209
1210 // qbyte swap the header and write it out
1211
1212         for (i=0 ; i<sizeof(progs)/4 ; i++)
1213                 ((int *)&progs)[i] = PRLittleLong ( ((int *)&progs)[i] );               
1214
1215         
1216         SafeSeek (h, 0, SEEK_SET);
1217         SafeWrite (h, &progs, sizeof(progs));
1218         SafeClose (h);
1219
1220         if (!debugtarget)
1221         {
1222                 if (opt_filenames)
1223                 {
1224                         printf("Not writing linenumbers file due to conflicting optimisation\n");
1225                 }
1226                 else
1227                 {
1228                         unsigned int lnotype = *(unsigned int*)"LNOF";
1229                         unsigned int version = 1;
1230                         StripExtension(destfile);
1231                         strcat(destfile, ".lno");
1232                         if (verbose)
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));
1242                         SafeClose (h);
1243                 }
1244         }
1245
1246         return true;
1247 }
1248
1249
1250
1251 /*
1252 ===============
1253 PR_String
1254
1255 Returns a string suitable for printing (no newlines, max 60 chars length)
1256 ===============
1257 */
1258 char *QCC_PR_String (char *string)
1259 {
1260         static char buf[80];
1261         char    *s;
1262         
1263         s = buf;
1264         *s++ = '"';
1265         while (string && *string)
1266         {
1267                 if (s == buf + sizeof(buf) - 2)
1268                         break;
1269                 if (*string == '\n')
1270                 {
1271                         *s++ = '\\';
1272                         *s++ = 'n';
1273                 }
1274                 else if (*string == '"')
1275                 {
1276                         *s++ = '\\';
1277                         *s++ = '"';
1278                 }
1279                 else
1280                         *s++ = *string;
1281                 string++;
1282                 if (s - buf > 60)
1283                 {
1284                         *s++ = '.';
1285                         *s++ = '.';
1286                         *s++ = '.';
1287                         break;
1288                 }
1289         }
1290         *s++ = '"';
1291         *s++ = 0;
1292         return buf;
1293 }
1294
1295
1296
1297 QCC_def_t       *QCC_PR_DefForFieldOfs (gofs_t ofs)
1298 {
1299         QCC_def_t       *d;
1300         
1301         for (d=pr.def_head.next ; d ; d=d->next)
1302         {
1303                 if (d->type->type != ev_field)
1304                         continue;
1305                 if (*((unsigned int *)&qcc_pr_globals[d->ofs]) == ofs)
1306                         return d;
1307         }
1308         QCC_Error (ERR_NOTDEFINED, "PR_DefForFieldOfs: couldn't find %i",ofs);
1309         return NULL;
1310 }
1311
1312 /*
1313 ============
1314 PR_ValueString
1315
1316 Returns a string describing *data in a type specific manner
1317 =============
1318 */
1319 char *QCC_PR_ValueString (etype_t type, void *val)
1320 {
1321         static char     line[256];
1322         QCC_def_t               *def;
1323         QCC_dfunction_t *f;
1324         
1325         switch (type)
1326         {
1327         case ev_string:
1328                 sprintf (line, "%s", QCC_PR_String(strings + *(int *)val));
1329                 break;
1330         case ev_entity: 
1331                 sprintf (line, "entity %i", *(int *)val);
1332                 break;
1333         case ev_function:
1334                 f = functions + *(int *)val;
1335                 if (!f)
1336                         sprintf (line, "undefined function");
1337                 else
1338                         sprintf (line, "%s()", strings + f->s_name);
1339                 break;
1340         case ev_field:
1341                 def = QCC_PR_DefForFieldOfs ( *(int *)val );
1342                 sprintf (line, ".%s", def->name);
1343                 break;
1344         case ev_void:
1345                 sprintf (line, "void");
1346                 break;
1347         case ev_float:
1348                 sprintf (line, "%5.1f", *(float *)val);
1349                 break;
1350         case ev_integer:
1351                 sprintf (line, "%i", *(int *)val);
1352                 break;
1353         case ev_vector:
1354                 sprintf (line, "'%5.1f %5.1f %5.1f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
1355                 break;
1356         case ev_pointer:
1357                 sprintf (line, "pointer");
1358                 break;
1359         default:
1360                 sprintf (line, "bad type %i", type);
1361                 break;
1362         }
1363         
1364         return line;
1365 }
1366
1367 /*
1368 ============
1369 PR_GlobalString
1370
1371 Returns a string with a description and the contents of a global,
1372 padded to 20 field width
1373 ============
1374 */
1375 /*char *QCC_PR_GlobalStringNoContents (gofs_t ofs)
1376 {
1377         int             i;
1378         QCC_def_t       *def;
1379         void    *val;
1380         static char     line[128];
1381         
1382         val = (void *)&qcc_pr_globals[ofs];
1383         def = pr_global_defs[ofs];
1384         if (!def)
1385 //              Error ("PR_GlobalString: no def for %i", ofs);
1386                 sprintf (line,"%i(?""?""?)", ofs);
1387         else
1388                 sprintf (line,"%i(%s)", ofs, def->name);
1389         
1390         i = strlen(line);
1391         for ( ; i<16 ; i++)
1392                 strcat (line," ");
1393         strcat (line," ");
1394                 
1395         return line;
1396 }
1397
1398 char *QCC_PR_GlobalString (gofs_t ofs)
1399 {
1400         char    *s;
1401         int             i;
1402         QCC_def_t       *def;
1403         void    *val;
1404         static char     line[128];
1405         
1406         val = (void *)&qcc_pr_globals[ofs];
1407         def = pr_global_defs[ofs];
1408         if (!def)
1409                 return QCC_PR_GlobalStringNoContents(ofs);
1410         if (def->initialized && def->type->type != ev_function)
1411         {
1412                 s = QCC_PR_ValueString (def->type->type, &qcc_pr_globals[ofs]);
1413                 sprintf (line,"%i(%s)", ofs, s);
1414         }
1415         else
1416                 sprintf (line,"%i(%s)", ofs, def->name);
1417         
1418         i = strlen(line);
1419         for ( ; i<16 ; i++)
1420                 strcat (line," ");
1421         strcat (line," ");
1422                 
1423         return line;
1424 }*/
1425
1426 /*
1427 ============
1428 PR_PrintOfs
1429 ============
1430 */
1431 /*void QCC_PR_PrintOfs (gofs_t ofs)
1432 {
1433         printf ("%s\n",QCC_PR_GlobalString(ofs));
1434 }*/
1435
1436 /*
1437 =================
1438 PR_PrintStatement
1439 =================
1440 */
1441 /*void QCC_PR_PrintStatement (QCC_dstatement_t *s)
1442 {
1443         int             i;
1444         
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);
1447         for ( ; i<10 ; i++)
1448                 printf (" ");
1449                 
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)
1453         {
1454                 printf ("branch %i",s->a);
1455         }
1456         else if ( (unsigned)(s->op - OP_STORE_F) < 6)
1457         {
1458                 printf ("%s",QCC_PR_GlobalString(s->a));
1459                 printf ("%s", QCC_PR_GlobalStringNoContents(s->b));
1460         }
1461         else
1462         {
1463                 if (s->a)
1464                         printf ("%s",QCC_PR_GlobalString(s->a));
1465                 if (s->b)
1466                         printf ("%s",QCC_PR_GlobalString(s->b));
1467                 if (s->c)
1468                         printf ("%s", QCC_PR_GlobalStringNoContents(s->c));
1469         }
1470         printf ("\n");
1471 }*/
1472
1473
1474 /*
1475 ============
1476 PR_PrintDefs
1477 ============
1478 */
1479 /*void QCC_PR_PrintDefs (void)
1480 {
1481         QCC_def_t       *d;
1482         
1483         for (d=pr.def_head.next ; d ; d=d->next)
1484                 QCC_PR_PrintOfs (d->ofs);
1485 }*/
1486
1487 QCC_type_t *QCC_PR_NewType (char *name, int basictype)
1488 {
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]; 
1497
1498
1499         numtypeinfos++;
1500
1501         return &qcc_typeinfo[numtypeinfos-1];
1502 }
1503
1504 /*
1505 ==============
1506 PR_BeginCompilation
1507
1508 called before compiling a batch of files, clears the pr struct
1509 ==============
1510 */
1511 void    QCC_PR_BeginCompilation (void *memory, int memsize)
1512 {
1513         extern int recursivefunctiontype;
1514         extern struct freeoffset_s *freeofs;
1515         int             i;
1516         char name[16];
1517         
1518         pr.memory = memory;
1519         pr.max_memory = memsize;
1520
1521         pr.def_tail = &pr.def_head;
1522
1523         QCC_PR_ResetErrorScope();
1524         pr_scope = NULL;
1525
1526 /*      numpr_globals = RESERVED_OFS;   
1527         
1528         for (i=0 ; i<RESERVED_OFS ; i++)
1529                 pr_global_defs[i] = &def_void;
1530 */
1531         
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);
1542
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);
1546
1547         type_function->aux_type = type_void;
1548
1549         //type_field->aux_type = type_float;
1550
1551         if (keyword_integer)
1552                 type_integer = QCC_PR_NewType("integer", ev_integer);
1553         if (keyword_int)
1554                 type_integer = QCC_PR_NewType("int", ev_integer);
1555         
1556
1557
1558         if (output_parms)
1559         {       //this tends to confuse the brains out of decompilers. :)
1560                 numpr_globals = 1;
1561                 QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 1, false)->references++;
1562                 for (i = 0; i < MAX_PARMS; i++)
1563                 {
1564                         sprintf(name, "PARM%i", i);
1565                         QCC_PR_GetDef(type_vector, name, NULL, true, 1, false)->references++;
1566                 }
1567         }
1568         else
1569         {
1570                 numpr_globals = RESERVED_OFS;
1571 //              for (i=0 ; i<RESERVED_OFS ; i++)
1572 //                      pr_global_defs[i] = NULL;
1573         }
1574
1575 // link the function type in so state forward declarations match proper type
1576         pr.types = NULL;
1577 //      type_function->next = NULL;
1578         pr_error_count = 0;
1579         pr_warning_count = 0;
1580         recursivefunctiontype = 0;
1581
1582         freeofs = NULL;
1583 }
1584
1585 /*
1586 ==============
1587 PR_FinishCompilation
1588
1589 called after all files are compiled to check for errors
1590 Returns false if errors were detected.
1591 ==============
1592 */
1593 int QCC_PR_FinishCompilation (void)
1594 {
1595         QCC_def_t               *d;
1596         int     errors;
1597         
1598         errors = false;
1599         
1600 // check to make sure all functions prototyped have code
1601         for (d=pr.def_head.next ; d ; d=d->next)
1602         {
1603                 if (d->type->type == ev_function && !d->scope)// function parms are ok
1604                 {
1605 //                      f = G_FUNCTION(d->ofs);
1606 //                      if (!f || (!f->code && !f->builtin) )
1607                         if (d->initialized==0)
1608                         {
1609                                 if (!strncmp(d->name, "ArrayGet*", 9))
1610                                 {
1611                                         QCC_PR_EmitArrayGetFunction(d, d->name+9);
1612                                         pr_scope = NULL;
1613                                 }
1614                                 else if (!strncmp(d->name, "ArraySet*", 9))
1615                                 {
1616                                         QCC_PR_EmitArraySetFunction(d, d->name+9);
1617                                         pr_scope = NULL;
1618                                 }
1619                                 else if (!strncmp(d->name, "Class*", 6))
1620                                 {
1621                                         QCC_PR_EmitClassFromFunction(d, d->name+6);
1622                                         pr_scope = NULL;
1623                                 }
1624                                 else
1625                                 {
1626                                         QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, d, "function %s was not defined",d->name);
1627                                         bodylessfuncs = true;
1628                                         errors = true;
1629                                 }
1630 //                              errors = true;
1631                         }
1632                         else if (d->initialized==2)
1633                                 bodylessfuncs = true;
1634                 }
1635         }
1636         pr_scope = NULL;
1637
1638         return !errors;
1639 }
1640
1641 //=============================================================================
1642
1643 // FIXME: byte swap?
1644
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
1648
1649
1650 #define CRC_INIT_VALUE  0xffff
1651 #define CRC_XOR_VALUE   0x0000
1652
1653 static unsigned short QCC_crctable[256] =
1654 {
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
1687 };
1688
1689 void QCC_CRC_Init(unsigned short *crcvalue)
1690 {
1691         *crcvalue = CRC_INIT_VALUE;
1692 }
1693
1694 void QCC_CRC_ProcessByte(unsigned short *crcvalue, qbyte data)
1695 {
1696         *crcvalue = (*crcvalue << 8) ^ QCC_crctable[(*crcvalue >> 8) ^ data];
1697 }
1698
1699 unsigned short QCC_CRC_Value(unsigned short crcvalue)
1700 {
1701         return crcvalue ^ CRC_XOR_VALUE;
1702 }
1703 //=============================================================================
1704
1705
1706 /*
1707 ============
1708 PR_WriteProgdefs
1709
1710 Writes the global and entity structures out
1711 Returns a crc of the header, to be stored in the progs file for comparison
1712 at load time.
1713 ============
1714 */
1715 /*
1716 char *Sva(char *msg, ...)
1717 {
1718         va_list l;
1719         static char buf[1024];
1720
1721         va_start(l, msg);
1722         QC_vsnprintf (buf,sizeof(buf)-1, msg, l);
1723         va_end(l);
1724
1725         return buf;
1726 }
1727 */
1728
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)
1732 {
1733         char *s;
1734         int i = strlen(file);
1735         if (i + strlen(p)+1 >= PROGDEFS_MAX_SIZE)
1736                 return;
1737         for(s=p;*s;s++,i++)
1738         {
1739                 QCC_CRC_ProcessByte(crc, *s);
1740                 file[i] = *s;
1741         }
1742         file[i]='\0';
1743 }
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';}
1746
1747 static void Add3(char *p, unsigned short *crc, char *file)
1748 {
1749         char *s;
1750         for(s=p;*s;s++)
1751                 QCC_CRC_ProcessByte(crc, *s);   
1752 }
1753 #define ADD3(p) Add3(p, &crc, file)
1754
1755 unsigned short QCC_PR_WriteProgdefs (char *filename)
1756 {
1757 #define ADD2(p) strncat(file, p, PROGDEFS_MAX_SIZE-1 - strlen(file))    //no crc (later changes)
1758         char file[PROGDEFS_MAX_SIZE];
1759         QCC_def_t       *d;
1760         int     f;
1761         unsigned short          crc;
1762 //      int             c;
1763
1764         file[0] = '\0';
1765
1766         QCC_CRC_Init (&crc);
1767         
1768 // print global vars until the first field is defined
1769
1770         //ADD: crc and dump
1771         //ADD2: dump but don't crc
1772         //ADD3: crc but don't dump
1773
1774         ADD("\n/* ");
1775         if (qcc_targetformat == QCF_HEXEN2)
1776                 ADD3("generated by hcc, do not modify");
1777         else
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");
1782         ADD(qcva("\n{"));       
1783         ADD2("\tint pad;\n"
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)
1795         {
1796                 if (!strcmp (d->name, "end_sys_globals"))
1797                         break;
1798                 if (d->ofs<RESERVED_OFS)
1799                         continue;
1800                         
1801                 switch (d->type->type)
1802                 {
1803                 case ev_float:
1804                         ADD(qcva("\tfloat\t%s;\n",d->name));
1805                         break;
1806                 case ev_vector:
1807                         ADD(qcva("\tvec3_t\t%s;\n",d->name));
1808                         d=d->next->next->next;  // skip the elements
1809                         break;
1810                 case ev_string:
1811                         ADD(qcva("\tstring_t\t%s;\n",d->name));
1812                         break;
1813                 case ev_function:
1814                         ADD(qcva("\tfunc_t\t%s;\n",d->name));
1815                         break;
1816                 case ev_entity:
1817                         ADD(qcva("\tint\t%s;\n",d->name));
1818                         break;
1819                 case ev_integer:
1820                         ADD(qcva("\tint\t%s;\n",d->name));
1821                         break;
1822                 default:
1823                         ADD(qcva("\tint\t%s;\n",d->name));
1824                         break;
1825                 }
1826         }
1827         ADD("} globalvars_t;\n\n");
1828
1829 // print all fields
1830         ADD("typedef struct");
1831         ADD2(" entvars_s");
1832         ADD("\n{\n");
1833         for (d=pr.def_head.next ; d ; d=d->next)
1834         {
1835                 if (!strcmp (d->name, "end_sys_fields"))
1836                         break;
1837                         
1838                 if (d->type->type != ev_field)
1839                         continue;
1840                         
1841                 switch (d->type->aux_type->type)
1842                 {
1843                 case ev_float:
1844                         ADD(qcva("\tfloat\t%s;\n",d->name));
1845                         break;
1846                 case ev_vector:
1847                         ADD(qcva("\tvec3_t\t%s;\n",d->name));
1848                         d=d->next->next->next;  // skip the elements
1849                         break;
1850                 case ev_string:
1851                         ADD(qcva("\tstring_t\t%s;\n",d->name));
1852                         break;
1853                 case ev_function:
1854                         ADD(qcva("\tfunc_t\t%s;\n",d->name));
1855                         break;
1856                 case ev_entity:
1857                         ADD(qcva("\tint\t%s;\n",d->name));
1858                         break;
1859                 case ev_integer:
1860                         ADD(qcva("\tint\t%s;\n",d->name));
1861                         break;
1862                 default:
1863                         ADD(qcva("\tint\t%s;\n",d->name));
1864                         break;
1865                 }
1866         }
1867         ADD("} entvars_t;\n\n");
1868
1869         ///temp
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");
1871         f=0;
1872         for (d=pr.def_head.next ; d ; d=d->next)
1873         {
1874                 if (!strcmp (d->name, "end_sys_fields"))
1875                         break;
1876
1877                 if (d->type->type != ev_field)
1878                         continue;
1879                 if (f)
1880                         ADD2(",\n");    
1881                 ADD2(qcva("\t{%i,\t%i,\t\"%s\"}",G_INT(d->ofs), d->type->aux_type->type, d->name));
1882                 f = 1;
1883         }
1884         ADD2("\n};\n#endif\n\n");
1885         //end temp
1886
1887         ADD2(qcva("#define PROGHEADER_CRC %i\n", crc));
1888
1889         if (QCC_CheckParm("-progdefs"))
1890         {
1891                 printf ("writing %s\n", filename);
1892                 f = SafeOpenWrite(filename, 16384);
1893                 SafeWrite(f, file, strlen(file));
1894                 SafeClose(f);
1895         }
1896
1897
1898         if (ForcedCRC)
1899                 crc = ForcedCRC;
1900
1901         switch (crc)
1902         {
1903         case 12923:     //#pragma sourcefile usage
1904                 break;
1905         case 54730:
1906                 if (verbose)
1907                         printf("Recognised progs as QuakeWorld\n");
1908                 break;
1909         case 5927:
1910                 if (verbose)
1911                         printf("Recognised progs as NetQuake server gamecode\n");
1912                 break;
1913
1914         case 26940:
1915                 if (verbose)
1916                         printf("Recognised progs as Quake pre-release...\n");
1917                 break;
1918
1919         case 38488:
1920                 if (verbose)
1921                         printf("Recognised progs as original Hexen2\n");
1922                 break;
1923         case 26905:
1924                 if (verbose)
1925                         printf("Recognised progs as Hexen2 Mission Pack\n");
1926                 break;
1927         case 14046:
1928                 if (verbose)
1929                         printf("Recognised progs as Hexen2 (demo)\n");
1930                 break;
1931
1932         case 22390: //EXT_CSQC_1
1933                 if (verbose)
1934                         printf("Recognised progs as an EXT_CSQC_1 module\n");
1935                 break;
1936         case 17105:
1937         case 32199:     //outdated ext_csqc
1938                 printf("Recognised progs as outdated CSQC module\n");
1939                 break;
1940         case 52195:
1941                 printf("Recognised progs as outdated CSQC module\n");
1942                 break;
1943         case 10020:
1944                 if (verbose)
1945                         printf("Recognised progs as a DP/FTE Menu module\n");
1946                 break;
1947
1948         case 32401:
1949                 printf("Warning: please update your tenebrae system defs.\n");
1950                 break;
1951         default:
1952                 printf("Warning: progs CRC not recognised from quake nor clones\n");
1953                 break;
1954         }
1955
1956
1957         return crc;
1958 }
1959
1960
1961 /*void QCC_PrintFunction (char *name)
1962 {
1963         int             i;
1964         QCC_dstatement_t        *ds;
1965         QCC_dfunction_t         *df;
1966         
1967         for (i=0 ; i<numfunctions ; i++)
1968                 if (!strcmp (name, strings + functions[i].s_name))
1969                         break;
1970         if (i==numfunctions)
1971                 QCC_Error (ERR_NOFUNC, "No function named \"%s\"", name);
1972         df = functions + i;     
1973         
1974         printf ("Statements for function %s:\n", name);
1975         ds = statements + df->first_statement;
1976         while (1)
1977         {
1978                 QCC_PR_PrintStatement (ds);
1979                 if (!ds->op)
1980                         break;
1981                 ds++;
1982         }
1983 }*/
1984 /*
1985 void QCC_PrintOfs(unsigned int ofs)
1986 {
1987         int i;
1988         bool printfunc;
1989         QCC_dstatement_t        *ds;
1990         QCC_dfunction_t         *df;
1991
1992         for (i=0 ; i<numfunctions ; i++)
1993         {
1994                 df = functions + i;
1995                 ds = statements + df->first_statement;
1996                 printfunc = false;
1997                 while (1)
1998                 {
1999                         if (!ds->op)
2000                                 break;
2001                         if (ds->a == ofs || ds->b == ofs || ds->c == ofs)
2002                         {
2003                                 QCC_PR_PrintStatement (ds);
2004                                 printfunc = true;
2005                         }
2006                         ds++;
2007                 }
2008                 if (printfunc)
2009                 {
2010                         QCC_PrintFunction(strings + functions[i].s_name);
2011                         printf(" \n \n");
2012                 }
2013         }
2014
2015 }
2016 */
2017 /*
2018 ==============================================================================
2019
2020 DIRECTORY COPYING / PACKFILE CREATION
2021
2022 ==============================================================================
2023 */
2024
2025 typedef struct
2026 {
2027         char    name[56];
2028         int             filepos, filelen;
2029 } packfile_t;
2030
2031 typedef struct
2032 {
2033         char    id[4];
2034         int             dirofs;
2035         int             dirlen;
2036 } packheader_t;
2037
2038 packfile_t      pfiles[4096], *pf;
2039 int                     packhandle;
2040 int                     packbytes;
2041
2042
2043 /*
2044 ============
2045 CreatePath
2046 ============
2047 */
2048 void    QCC_CreatePath (char *path)
2049 {
2050         /*
2051         char    *ofs;
2052         
2053         for (ofs = path+1 ; *ofs ; ofs++)
2054         {
2055                 if (*ofs == '/')
2056                 {       // create the directory
2057                         *ofs = 0;
2058 #ifdef QCC
2059                         mkdir(path);
2060 #else
2061                         QCC_mkdir (path);
2062 #endif
2063                         *ofs = '/';
2064                 }
2065         }
2066         */
2067 }
2068
2069
2070 /*
2071 ===========
2072 PackFile
2073
2074 Copy a file into the pak file
2075 ===========
2076 */
2077 void QCC_PackFile (char *src, char *name)
2078 {
2079         int             remaining;
2080 #if 1
2081         char    *f;
2082 #else
2083         int             in;     
2084         int             count;
2085         char    buf[4096];
2086 #endif
2087
2088         
2089         if ( (qbyte *)pf - (qbyte *)pfiles > sizeof(pfiles) )
2090                 QCC_Error (ERR_TOOMANYPAKFILES, "Too many files in pak file");
2091
2092 #if 1
2093         f = FS_ReadToMem(src, NULL, &remaining);
2094         if (!f)
2095         {
2096                 printf ("%64s : %7s\n", name, "");
2097 //              QCC_Error("Failed to open file %s", src);
2098                 return;
2099         }
2100
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);
2105
2106         packbytes += remaining;
2107
2108         SafeWrite (packhandle, f, remaining);
2109
2110         FS_CloseFromMem(f);
2111 #else
2112         in = SafeOpenRead (src);
2113         remaining = filelength (in);
2114
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);
2119
2120         packbytes += remaining;
2121         
2122         while (remaining)
2123         {
2124                 if (remaining < sizeof(buf))
2125                         count = remaining;
2126                 else
2127                         count = sizeof(buf);
2128                 SafeRead (in, buf, count);
2129                 SafeWrite (packhandle, buf, count);
2130                 remaining -= count;
2131         }
2132
2133         close (in);
2134 #endif
2135         pf++;
2136 }
2137
2138
2139 /*
2140 ===========
2141 CopyFile
2142
2143 Copies a file, creating any directories needed
2144 ===========
2145 */
2146 void QCC_CopyFile (char *src, char *dest)
2147 {
2148         /*
2149         int             in, out;
2150         int             remaining, count;
2151         char    buf[4096];
2152         
2153         print ("%s to %s\n", src, dest);
2154
2155         in = SafeOpenRead (src);
2156         remaining = filelength (in);
2157         
2158         QCC_CreatePath (dest);
2159         out = SafeOpenWrite (dest, remaining+10);
2160         
2161         while (remaining)
2162         {
2163                 if (remaining < sizeof(buf))
2164                         count = remaining;
2165                 else
2166                         count = sizeof(buf);
2167                 SafeRead (in, buf, count);
2168                 SafeWrite (out, buf, count);
2169                 remaining -= count;
2170         }
2171
2172         close (in);
2173         SafeClose (out);        
2174         */
2175 }
2176
2177
2178 /*
2179 ===========
2180 CopyFiles
2181 ===========
2182 */
2183
2184 void _QCC_CopyFiles (int blocknum, int copytype, char *srcdir, char *destdir)
2185 {
2186         int i;
2187         int             dirlen;
2188         unsigned short          crc;
2189         packheader_t    header;
2190         char    name[1024];
2191         char    srcfile[1024], destfile[1024];
2192
2193         packbytes = 0;
2194
2195         if (copytype == 2)
2196         {
2197                 pf = pfiles;
2198                 packhandle = SafeOpenWrite (destdir, 1024*1024);
2199                 SafeWrite (packhandle, &header, sizeof(header));
2200         }
2201
2202         for (i=0 ; i<numsounds ; i++)
2203         {
2204                 if (precache_sounds_block[i] != blocknum)
2205                         continue;               
2206                 sprintf (srcfile,"%s%s",srcdir, precache_sounds[i]);
2207                 sprintf (destfile,"%s%s",destdir, precache_sounds[i]);
2208                 if (copytype == 1)
2209                         QCC_CopyFile (srcfile, destfile);
2210                 else
2211                         QCC_PackFile (srcfile, precache_sounds[i]);
2212         }
2213         for (i=0 ; i<nummodels ; i++)
2214         {
2215                 if (precache_models_block[i] != blocknum)
2216                         continue;
2217                 sprintf (srcfile,"%s%s",srcdir, precache_models[i]);
2218                 sprintf (destfile,"%s%s",destdir, precache_models[i]);
2219                 if (copytype == 1)
2220                         QCC_CopyFile (srcfile, destfile);
2221                 else
2222                         QCC_PackFile (srcfile, precache_models[i]);
2223         }
2224         for (i=0 ; i<numtextures ; i++)
2225         {
2226                 if (precache_textures_block[i] != blocknum)
2227                         continue;
2228
2229                 {
2230                         sprintf (name, "%s", precache_textures[i]);
2231                         sprintf (srcfile,"%s%s",srcdir, name);
2232                         sprintf (destfile,"%s%s",destdir, name);
2233                         if (copytype == 1)
2234                                 QCC_CopyFile (srcfile, destfile);
2235                         else
2236                                 QCC_PackFile (srcfile, name);
2237                 }
2238                 {
2239                         sprintf (name, "%s.bmp", precache_textures[i]);
2240                         sprintf (srcfile,"%s%s",srcdir, name);
2241                         sprintf (destfile,"%s%s",destdir, name);
2242                         if (copytype == 1)
2243                                 QCC_CopyFile (srcfile, destfile);
2244                         else
2245                                 QCC_PackFile (srcfile, name);
2246                 }
2247                 {
2248                         sprintf (name, "%s.tga", precache_textures[i]);
2249                         sprintf (srcfile,"%s%s",srcdir, name);
2250                         sprintf (destfile,"%s%s",destdir, name);
2251                         if (copytype == 1)
2252                                 QCC_CopyFile (srcfile, destfile);
2253                         else
2254                                 QCC_PackFile (srcfile, name);
2255                 }
2256         }
2257         for (i=0 ; i<numfiles ; i++)
2258         {
2259                 if (precache_files_block[i] != blocknum)
2260                         continue;
2261                 sprintf (srcfile,"%s%s",srcdir, precache_files[i]);
2262                 sprintf (destfile,"%s%s",destdir, precache_files[i]);
2263                 if (copytype == 1)
2264                         QCC_CopyFile (srcfile, destfile);
2265                 else
2266                         QCC_PackFile (srcfile, precache_files[i]);
2267         }
2268         
2269         if (copytype == 2)
2270         {
2271                 header.id[0] = 'P';
2272                 header.id[1] = 'A';
2273                 header.id[2] = 'C';
2274                 header.id[3] = 'K';
2275                 dirlen = (qbyte *)pf - (qbyte *)pfiles;
2276                 header.dirofs = PRLittleLong(SafeSeek (packhandle, 0, SEEK_CUR));
2277                 header.dirlen = PRLittleLong(dirlen);
2278                 
2279                 SafeWrite (packhandle, pfiles, dirlen);
2280         
2281                 SafeSeek (packhandle, 0, SEEK_SET);
2282                 SafeWrite (packhandle, &header, sizeof(header));
2283                 SafeClose (packhandle); 
2284         
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]);
2289         
2290                 i = pf - pfiles;
2291                 printf ("%i files packed in %i bytes (%i crc)\n",i, packbytes, crc);
2292         }
2293 }
2294
2295 void QCC_CopyFiles (void)
2296 {
2297         char *s;
2298         char    srcdir[1024], destdir[1024];
2299         int             p;                                      
2300
2301         if (verbose)
2302         {
2303                 if (numsounds > 0)
2304                         printf ("%3i unique precache_sounds\n", numsounds);
2305                 if (nummodels > 0)
2306                         printf ("%3i unique precache_models\n", nummodels);
2307                 if (numtextures > 0)
2308                         printf ("%3i unique precache_textures\n", numtextures);
2309                 if (numfiles > 0)
2310                         printf ("%3i unique precache_files\n", numfiles);
2311         }
2312
2313         p = QCC_CheckParm ("-copy");
2314         if (p && p < myargc-2)
2315         {       // create a new directory tree
2316
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, "/");
2323
2324                 _QCC_CopyFiles(0, 1, srcdir, destdir);
2325                 return;
2326         }
2327
2328         for ( p = 0; p < 5; p++)
2329         {
2330                 s = QCC_Packname[p];            
2331                 if (!*s)
2332                         continue;
2333                 strcpy(destdir, s);
2334                 strcpy(srcdir, "");
2335                 _QCC_CopyFiles(p+1, 2, srcdir, destdir);
2336         }
2337         return;
2338         /*
2339
2340         blocknum = 1;
2341         p = QCC_CheckParm ("-pak2");
2342         if (p && p <myargc-2)
2343                 blocknum = 2;
2344         else
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");
2353
2354         
2355                 copytype = 2;
2356
2357                 _QCC_CopyFiles(blocknum, copytype, srcdir, destdir);
2358         }
2359         */
2360 }
2361
2362 //============================================================================
2363
2364
2365 void QCC_PR_CommandLinePrecompilerOptions (void)
2366 {
2367         CompilerConstant_t *cnst;
2368         int             i, p;
2369         char *name, *val;
2370
2371         for (i = 1;i<myargc;i++)
2372         {
2373                 //compiler constant
2374                 if ( !strncmp(myargv[i], "-D", 2) )
2375                 {
2376                         name = myargv[i] + 2;
2377                         val = strchr(name, '=');
2378                         if (val)
2379                         {
2380                                 *val = '\0';
2381                                 val++;
2382                         }
2383                         cnst = QCC_PR_DefineName(name);
2384                         if (val)
2385                         {
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';
2390                         }
2391                 }
2392
2393                 //optimisations.
2394                 else if ( !strnicmp(myargv[i], "-O", 2) || !strnicmp(myargv[i], "/O", 2) )
2395                 {
2396                         p = 0;
2397                         if (myargv[i][2] >= '0' && myargv[i][2] <= '3')
2398                         {
2399                         }
2400                         else if (!strnicmp(myargv[i]+2, "no-", 3))
2401                         {
2402                                 if (myargv[i][5])
2403                                 {
2404                                         for (p = 0; optimisations[p].enabled; p++)
2405                                         {
2406                                                 if ((*optimisations[p].abbrev && !stricmp(myargv[i]+5, optimisations[p].abbrev)) || !stricmp(myargv[i]+5, optimisations[p].fullname))
2407                                                 {
2408                                                         *optimisations[p].enabled = false;
2409                                                         break;
2410                                                 }
2411                                         }
2412                                 }
2413                         }
2414                         else
2415                         {
2416                                 if (myargv[i][2])
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))
2419                                                 {
2420                                                         *optimisations[p].enabled = true;
2421                                                         break;
2422                                                 }
2423                         }
2424                         if (!optimisations[p].enabled)
2425                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised optimisation parameter (%s)", myargv[i]);
2426                 }
2427                 
2428                 else if ( !strnicmp(myargv[i], "-K", 2) || !strnicmp(myargv[i], "/K", 2) )
2429                 {
2430                         p = 0;
2431                         if (!strnicmp(myargv[i]+2, "no-", 3))
2432                         {
2433                                 for (p = 0; compiler_flag[p].enabled; p++)
2434                                         if (!stricmp(myargv[i]+5, compiler_flag[p].abbrev))
2435                                         {
2436                                                 *compiler_flag[p].enabled = false;
2437                                                 break;
2438                                         }
2439                         }
2440                         else
2441                         {
2442                                 for (p = 0; compiler_flag[p].enabled; p++)
2443                                         if (!stricmp(myargv[i]+2, compiler_flag[p].abbrev))
2444                                         {
2445                                                 *compiler_flag[p].enabled = true;
2446                                                 break;
2447                                         }
2448                         }
2449
2450                         if (!compiler_flag[p].enabled)
2451                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised keyword parameter (%s)", myargv[i]);
2452                 }
2453                 else if ( !strnicmp(myargv[i], "-F", 2) || !strnicmp(myargv[i], "/F", 2) )
2454                 {
2455                         p = 0;
2456                         if (!strnicmp(myargv[i]+2, "no-", 3))
2457                         {
2458                                 for (p = 0; compiler_flag[p].enabled; p++)
2459                                         if (!stricmp(myargv[i]+5, compiler_flag[p].abbrev))
2460                                         {
2461                                                 *compiler_flag[p].enabled = false;
2462                                                 break;
2463                                         }
2464                         }
2465                         else
2466                         {
2467                                 for (p = 0; compiler_flag[p].enabled; p++)
2468                                         if (!stricmp(myargv[i]+2, compiler_flag[p].abbrev))
2469                                         {
2470                                                 *compiler_flag[p].enabled = true;
2471                                                 break;
2472                                         }
2473                         }
2474
2475                         if (!compiler_flag[p].enabled)
2476                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised flag parameter (%s)", myargv[i]);
2477                 }
2478
2479
2480                 else if ( !strncmp(myargv[i], "-T", 2) || !strncmp(myargv[i], "/T", 2) )
2481                 {
2482                         p = 0;
2483                         for (p = 0; targets[p].name; p++)
2484                                 if (!stricmp(myargv[i]+2, targets[p].name))
2485                                 {
2486                                         qcc_targetformat = targets[p].target;
2487                                         break;
2488                                 }
2489
2490                         if (!targets[p].name)
2491                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised target parameter (%s)", myargv[i]);
2492                 }
2493
2494                 else if ( !strnicmp(myargv[i], "-W", 2) || !strnicmp(myargv[i], "/W", 2) )
2495                 {
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"))
2501                                 pr_werror = true;
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;
2519                         }
2520                         else
2521                         {
2522                                 p = 0;
2523                                 if (!strnicmp(myargv[i]+2, "no-", 3))
2524                                 {
2525                                         for (p = 0; warningnames[p].name; p++)
2526                                                 if (!strcmp(myargv[i]+5, warningnames[p].name))
2527                                                 {
2528                                                         qccwarningdisabled[warningnames[p].index] = true;
2529                                                         break;
2530                                                 }
2531                                 }
2532                                 else
2533                                 {
2534                                         for (p = 0; warningnames[p].name; p++)
2535                                                 if (!stricmp(myargv[i]+2, warningnames[p].name))
2536                                                 {
2537                                                         qccwarningdisabled[warningnames[p].index] = false;
2538                                                         break;
2539                                                 }
2540                                 }
2541
2542                                 if (!warningnames[p].name)
2543                                         QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised warning parameter (%s)", myargv[i]);
2544                         }
2545                 }
2546         }
2547 }
2548
2549 /*
2550 ============
2551 main
2552 ============
2553 */
2554
2555 char    *qccmsrc;
2556 char    *qccmsrc2;
2557 char    qccmfilename[1024];
2558 char    qccmprogsdat[1024];
2559 char    qccmsourcedir[1024];
2560
2561 void QCC_FinishCompile(void);
2562
2563
2564 void SetEndian(void);
2565
2566
2567
2568 void QCC_SetDefaultProperties (void)
2569 {
2570         int level;
2571         int i;
2572
2573         Hash_InitTable(&compconstantstable, MAX_CONSTANTS, qccHunkAlloc(Hash_BytesForBuckets(MAX_CONSTANTS)));
2574
2575         ForcedCRC = 0;
2576         defaultstatic = 0;
2577
2578         QCC_PR_DefineName("FTEQCC");
2579
2580         if (QCC_CheckParm("/Oz"))
2581         {
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");
2591         }
2592
2593         if (QCC_CheckParm("/O0") || QCC_CheckParm("-O0"))
2594                 level = 0;
2595         else if (QCC_CheckParm("/O1") || QCC_CheckParm("-O1"))
2596                 level = 1;
2597         else if (QCC_CheckParm("/O2") || QCC_CheckParm("-O2"))
2598                 level = 2;
2599         else if (QCC_CheckParm("/O3") || QCC_CheckParm("-O3"))
2600                 level = 3;
2601         else
2602                 level = -1;
2603
2604         if (level == -1)
2605         {
2606                 for (i = 0; optimisations[i].enabled; i++)
2607                 {
2608                         if (optimisations[i].flags & FLAG_ASDEFAULT)
2609                                 *optimisations[i].enabled = true;
2610                         else
2611                                 *optimisations[i].enabled = false;
2612                 }
2613         }
2614         else
2615         {
2616                 for (i = 0; optimisations[i].enabled; i++)
2617                 {
2618                         if (level >= optimisations[i].optimisationlevel)
2619                                 *optimisations[i].enabled = true;
2620                         else
2621                                 *optimisations[i].enabled = false;
2622                 }
2623         }
2624
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;
2631         else
2632                 qcc_targetformat = QCF_STANDARD;
2633
2634
2635         //enable all warnings
2636         memset(qccwarningdisabled, 0, sizeof(qccwarningdisabled));
2637
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;
2649
2650
2651
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));
2656
2657         if (QCC_CheckParm("-h2"))
2658                 qccwarningdisabled[WARN_CASEINSENSATIVEFRAMEMACRO] = true;
2659
2660         //Check the command line
2661         QCC_PR_CommandLinePrecompilerOptions();
2662
2663
2664         if (qcc_targetformat == QCF_HEXEN2)     //force on the thinktime keyword if hexen2 progs.
2665                 keyword_thinktime = true;
2666
2667         if (QCC_CheckParm("/Debug"))    //disable any debug optimisations
2668         {
2669                 for (i = 0; optimisations[i].enabled; i++)
2670                 {
2671                         if (optimisations[i].flags & FLAG_KILLSDEBUGGERS)
2672                                 *optimisations[i].enabled = false;
2673                 }
2674         }
2675 }
2676
2677 //builds a list of files, pretends that they came from a progs.src
2678 int QCC_FindQCFiles()
2679 {
2680 #ifdef _WIN32
2681         WIN32_FIND_DATA fd;
2682         HANDLE h;
2683 #endif
2684
2685         int numfiles = 0, i, j;
2686         char *filelist[256], *temp;
2687
2688
2689         qccmsrc = qccHunkAlloc(8192);
2690         strcat(qccmsrc, "progs.dat\n");//"#pragma PROGS_DAT progs.dat\n");
2691
2692 #ifdef _WIN32
2693         h = FindFirstFile("*.qc", &fd);
2694         if (h == INVALID_HANDLE_VALUE)
2695                 return 0;
2696
2697         do
2698         {
2699                 filelist[numfiles] = qccHunkAlloc (strlen(fd.cFileName)+1);
2700                 strcpy(filelist[numfiles], fd.cFileName);
2701                 numfiles++;
2702         } while(FindNextFile(h, &fd)!=0);
2703         FindClose(h);
2704 #else
2705         printf("-Facc is not supported on this platform. Please make a progs.src file instead\n");
2706 #endif
2707
2708         //Sort alphabetically.
2709         //bubble. :(
2710
2711         for (i = 0; i < numfiles-1; i++)
2712         {
2713                 for (j = i+1; j < numfiles; j++)
2714                 {
2715                         if (stricmp(filelist[i], filelist[j]) > 0)
2716                         {
2717                                 temp = filelist[j];
2718                                 filelist[j] = filelist[i];
2719                                 filelist[i] = temp;
2720                         }
2721                 }
2722         }
2723         for (i = 0; i < numfiles; i++)
2724         {
2725                 strcat(qccmsrc, filelist[i]);
2726                 strcat(qccmsrc, "\n");
2727 //              strcat(qccmsrc, "#include \"");
2728 //              strcat(qccmsrc, filelist[i]);
2729 //              strcat(qccmsrc, "\"\n");
2730         }
2731
2732         return numfiles;
2733 }
2734
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
2739 {
2740         extern int                      pr_bracelevel;
2741
2742         int             p;
2743
2744 #ifndef QCCONLY
2745         char    destfile2[1024], *s2;
2746 #endif
2747         char *s;
2748
2749         SetEndian();
2750
2751         myargc = argc;
2752         myargv = argv;
2753
2754         qcc_compileactive = true;
2755
2756         pHash_Get = &Hash_Get;
2757         pHash_GetNext = &Hash_GetNext;
2758         pHash_Add = &Hash_Add;
2759
2760         MAX_REGS                = 65536;
2761         MAX_STRINGS             = 1000000;
2762         MAX_GLOBALS             = 32768;
2763         MAX_FIELDS              = 2048;
2764         MAX_STATEMENTS  = 0x80000;
2765         MAX_FUNCTIONS   = 16384;
2766         maxtypeinfos    = 16384;
2767         MAX_CONSTANTS   = 2048;
2768
2769         compressoutput = 0;
2770
2771         p = externs->FileSize("qcc.cfg");
2772         if (p < 0)
2773                 p = externs->FileSize("src/qcc.cfg");
2774         if (p>0)
2775         {
2776                 s = qccHunkAlloc(p+1);
2777                 s = externs->ReadFile("qcc.cfg", s, p);
2778
2779                 while(1)
2780                 {
2781                         s = QCC_COM_Parse(s);
2782                         if (!strcmp(qcc_token, "MAX_REGS"))
2783                         {
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);
2810                         }
2811                         else if (!s)
2812                                 break;
2813                         else
2814                                 printf("Bad token in qcc.cfg file\n");
2815                 }
2816         }
2817         /* don't try to be clever
2818         else if (p < 0)
2819         {
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));
2824         }
2825         */
2826
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], "");
2830
2831         for (p = 0; compiler_flag[p].enabled; p++)
2832         {
2833                 *compiler_flag[p].enabled = compiler_flag[p].flags & FLAG_ASDEFAULT;
2834         }
2835         pr_werror = false;
2836
2837         QCC_SetDefaultProperties();
2838
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;
2851         optres_locals = 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;
2859
2860         optres_test1 = 0;
2861         optres_test2 = 0;
2862
2863         accglobalsblock = 0;
2864
2865
2866         numtemps = 0;
2867
2868         functemps=NULL;
2869
2870         strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS);
2871         strofs = 1;
2872
2873         statements = (void *)qccHunkAlloc(sizeof(QCC_dstatement_t) * MAX_STATEMENTS);
2874         numstatements = 0;
2875         statement_linenums = (void *)qccHunkAlloc(sizeof(int) * MAX_STATEMENTS);
2876
2877         functions = (void *)qccHunkAlloc(sizeof(QCC_dfunction_t) * MAX_FUNCTIONS);
2878         numfunctions=0;
2879
2880         pr_bracelevel = 0;
2881
2882         qcc_pr_globals = (void *)qccHunkAlloc(sizeof(float) * MAX_REGS);
2883         numpr_globals=0;
2884
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)));
2890         dotranslate=0;
2891         dotranslate_count=0;
2892         
2893 //      pr_global_defs = (QCC_def_t **)qccHunkAlloc(sizeof(QCC_def_t *) * MAX_REGS);
2894
2895         qcc_globals = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_GLOBALS);
2896         numglobaldefs=0;        
2897
2898         fields = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_FIELDS);
2899         numfielddefs=0;
2900
2901 memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
2902
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);
2906         numsounds=0;
2907
2908         precache_textures = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_TEXTURES);
2909         precache_textures_block = (void *)qccHunkAlloc(sizeof(int)*MAX_TEXTURES);
2910         numtextures=0;
2911
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);
2915         nummodels=0;
2916
2917         precache_files = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_FILES);
2918         precache_files_block = (void *)qccHunkAlloc(sizeof(int)*MAX_FILES);
2919         numfiles = 0;
2920
2921         qcc_typeinfo = (void *)qccHunkAlloc(sizeof(QCC_type_t)*maxtypeinfos);
2922         numtypeinfos = 0;
2923
2924         qcc_tempofs = qccHunkAlloc(sizeof(int) * max_temps);
2925         tempsstart = 0;
2926
2927         bodylessfuncs=0;
2928
2929         memset(&pr, 0, sizeof(pr));
2930 #ifdef MAX_EXTRA_PARMS
2931         memset(&extra_parms, 0, sizeof(extra_parms));
2932 #endif
2933         
2934         if ( QCC_CheckParm ("/?") || QCC_CheckParm ("?") || QCC_CheckParm ("-?") || QCC_CheckParm ("-help") || QCC_CheckParm ("--help"))
2935         {
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");
2954
2955                 qcc_compileactive = false;
2956                 return;
2957         }
2958
2959         if (flag_caseinsensative)
2960         {
2961                 printf("Compiling without case sensativity\n");
2962                 pHash_Get = &Hash_GetInsensative;
2963                 pHash_GetNext = &Hash_GetNextInsensative;
2964                 pHash_Add = &Hash_AddInsensative;
2965         }
2966
2967
2968         if (opt_locals_marshalling)
2969                 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nLocals marshalling might be buggy. Use with caution\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
2970         
2971         p = QCC_CheckParm ("-src");
2972         if (p && p < argc-1 )
2973         {
2974                 strcpy (qccmsourcedir, argv[p+1]);
2975                 strcat (qccmsourcedir, "/");
2976                 printf ("Source directory: %s\n", qccmsourcedir);
2977         }
2978         else
2979                 *qccmsourcedir = '\0';
2980
2981         QCC_InitData ();
2982
2983         QCC_PR_BeginCompilation ((void *)qccHunkAlloc (0x100000), 0x100000);
2984
2985         if (flag_acc)
2986         {
2987                 if (!QCC_FindQCFiles())
2988                         QCC_Error (ERR_COULDNTOPENFILE, "Couldn't open file for asm output.");
2989         }
2990         else
2991         {
2992                 if (!numsourcefiles)
2993                 {
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]);               
2999                         else
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);
3004                         }
3005
3006                         numsourcefiles = 0;
3007                         strcpy(sourcefileslist[numsourcefiles++], qccmprogsdat);
3008                         currentsourcefile = 0;
3009                 }
3010                 else if (currentsourcefile == numsourcefiles)
3011                 {
3012                         //no more.
3013                         qcc_compileactive = false;
3014                         numsourcefiles = 0;
3015                         currentsourcefile = 0;
3016                         return;
3017                 }
3018
3019                 if (currentsourcefile)
3020                         printf("-------------------------------------\n");
3021
3022                 strcpy(qccmprogsdat, sourcefileslist[currentsourcefile++]);
3023
3024                 printf ("Source file: %s\n", qccmprogsdat);
3025
3026                 if (QCC_LoadFile (qccmprogsdat, (void *)&qccmsrc) == -1)
3027                 {               
3028                         return;
3029                 }
3030         }
3031
3032 #ifdef WRITEASM
3033         if (writeasm)
3034         {
3035                 asmfile = fopen("qc.asm", "wb");
3036                 if (!asmfile)
3037                         QCC_Error (ERR_INTERNAL, "Couldn't open file for asm output.");
3038         }
3039 #endif
3040
3041         newstylesource = false;
3042         while(*qccmsrc && *qccmsrc < ' ')
3043                 qccmsrc++;
3044         pr_file_p = QCC_COM_Parse(qccmsrc);
3045
3046         if (QCC_CheckParm ("-qc"))
3047         {
3048                 strcpy(destfile, qccmprogsdat);
3049                 StripExtension(destfile);
3050                 strcat(destfile, ".qco");
3051
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]);
3056                 goto newstyle;
3057         }
3058
3059         if (*qcc_token == '#')
3060         {               
3061                 void StartNewStyleCompile(void);
3062 newstyle:
3063                 newstylesource = true;
3064                 StartNewStyleCompile();
3065                 return;
3066         }
3067
3068         pr_file_p = qccmsrc;
3069         QCC_PR_LexWhitespace();
3070         qccmsrc = pr_file_p;
3071
3072         s = qccmsrc;
3073         pr_file_p = qccmsrc;
3074         QCC_PR_SimpleGetToken ();
3075         strcpy(qcc_token, pr_token);
3076         qccmsrc = pr_file_p;
3077
3078         if (!qccmsrc)
3079                 QCC_Error (ERR_NOOUTPUT, "No destination filename.  qcc -help for info.");
3080         strcpy (destfile, qcc_token);
3081
3082 #ifndef QCCONLY
3083         p=0;
3084         s2 = strcpy(destfile2, destfile);       
3085         if (!strncmp(s2, "./", 2))
3086                 s2+=2;
3087         else
3088         {
3089                 while(!strncmp(s2, "../", 3))
3090                 {
3091                         s2+=3;
3092                         p++;
3093                 }
3094         }
3095         strcpy(qccmfilename, qccmsourcedir);
3096         for (s=qccmfilename+strlen(qccmfilename);p && s>=qccmfilename; s--)
3097         {
3098                 if (*s == '/' || *s == '\\')
3099                 {
3100                         *(s+1) = '\0';
3101                         p--;
3102                 }
3103         }
3104         sprintf(destfile, "%s", s2);
3105
3106         while (p>0)
3107         {
3108                 memmove(destfile+3, destfile, strlen(destfile)+1);
3109                 destfile[0] = '.';
3110                 destfile[1] = '.';
3111                 destfile[2] = '/';
3112                 p--;
3113         }
3114 #endif
3115
3116         printf ("outputfile: %s\n", destfile);
3117         
3118         pr_dumpasm = false;
3119
3120         currentchunk = NULL;
3121
3122         originalqccmsrc = qccmsrc;
3123 }
3124
3125 void new_QCC_ContinueCompile(void);
3126 //called between exe frames - won't loose net connection (is the theory)...
3127 void QCC_ContinueCompile(void)
3128 {
3129         char *s, *s2;
3130         currentchunk = NULL;
3131         if (!qcc_compileactive)
3132                 //HEY!
3133                 return;
3134
3135         if (newstylesource)
3136         {
3137                 new_QCC_ContinueCompile();
3138                 return;
3139         }
3140
3141         qccmsrc = QCC_COM_Parse(qccmsrc);
3142         if (!qccmsrc)
3143         {
3144                 if (autoprototype)
3145                 {
3146                         qccmsrc = originalqccmsrc;
3147                         QCC_SetDefaultProperties();
3148                         autoprototype = false;
3149                         return;
3150                 }
3151                 QCC_FinishCompile();
3152
3153                 PostCompile();
3154                 if (!PreCompile())
3155                         return;
3156                 QCC_main(myargc, myargv);
3157                 return;
3158         }
3159         s = qcc_token;
3160
3161         strcpy (qccmfilename, qccmsourcedir);
3162         while(1)
3163         {
3164                 if (!strncmp(s, "..\\", 3))
3165                 {
3166                         s2 = qccmfilename + strlen(qccmfilename)-2;
3167                         while (s2>=qccmfilename)
3168                         {
3169                                 if (*s2 == '/' || *s2 == '\\')
3170                                 {
3171                                         s2[1] = '\0';
3172                                         break;
3173                                 }
3174                                 s2--;
3175                         }
3176                         s+=3;
3177                         continue;
3178                 }
3179                 if (!strncmp(s, ".\\", 2))
3180                 {
3181                         s+=2;
3182                         continue;
3183                 }
3184
3185                 break;
3186         }
3187         strcat (qccmfilename, s);
3188         if (autoprototype)
3189                 printf ("prototyping %s\n", qccmfilename);
3190         else
3191         {
3192                 printf ("compiling %s\n", qccmfilename);
3193         }
3194         QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
3195
3196         if (!QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
3197                 QCC_Error (ERR_PARSEERRORS, "Errors have occured\n");
3198 }
3199 void QCC_FinishCompile(void)
3200 {       
3201         pbool donesomething;
3202         int crc;
3203 //      int p;
3204         currentchunk = NULL;
3205
3206         if (setjmp(pr_parse_abort))
3207                 QCC_Error(ERR_INTERNAL, "");
3208         
3209         if (!QCC_PR_FinishCompilation ())
3210         {
3211                 QCC_Error (ERR_PARSEERRORS, "compilation errors");
3212         }
3213
3214 /*      p = QCC_CheckParm ("-asm");
3215         if (p)
3216         {
3217                 for (p++ ; p<myargc ; p++)
3218                 {
3219                         if (myargv[p][0] == '-')
3220                                 break;
3221                         QCC_PrintFunction (myargv[p]);
3222                 }
3223         }*/
3224
3225         /*p = QCC_CheckParm ("-ofs");
3226         if (p)
3227         {
3228                 for (p++ ; p<myargc ; p++)
3229                 {
3230                         if (myargv[p][0] == '-')
3231                                 break;
3232                         QCC_PrintOfs (atoi(myargv[p]));
3233                 }
3234         }*/
3235
3236         if (pr_werror && pr_warning_count != 0)
3237                 QCC_Error (ERR_PARSEERRORS, "compilation errors");
3238
3239 // write progdefs.h
3240         crc = QCC_PR_WriteProgdefs ("progdefs.h");
3241         
3242 // write data file
3243         donesomething = QCC_WriteData (crc);
3244         
3245 // regenerate bmodels if -bspmodels
3246         QCC_BspModels ();
3247
3248 // report / copy the data files
3249         QCC_CopyFiles ();
3250
3251         if (donesomething)
3252         {
3253                 if (verbose)
3254                 {
3255                         printf ("Compile Complete\n\n");
3256
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);
3279                         if (optres_locals)
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);
3297
3298
3299                         if (optres_test1)
3300                                 printf("optres_test1 %i\n", optres_test1);
3301                         if (optres_test2)
3302                                 printf("optres_test2 %i\n", optres_test2);
3303                         
3304                         printf("numtemps %i\n", numtemps);
3305                 }
3306                 if (!flag_msvcstyle)
3307                         printf("%i warnings\n", pr_warning_count);
3308         }
3309
3310         qcc_compileactive = false;
3311 }
3312
3313
3314
3315
3316
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);
3323
3324
3325
3326
3327
3328 void StartNewStyleCompile(void)
3329 {
3330         if (setjmp(pr_parse_abort))
3331         {
3332                 if (++pr_error_count > MAX_ERRORS)
3333                         return;
3334                 if (setjmp(pr_parse_abort))
3335                         return;
3336
3337                 QCC_PR_SkipToSemicolon ();
3338                 if (pr_token_type == tt_eof)
3339                         return;
3340         }
3341
3342
3343         QCC_PR_ClearGrabMacros ();      // clear the frame macros
3344
3345         compilingfile = qccmprogsdat;
3346
3347         pr_file_p = qccmsrc;
3348         s_file = s_file2 = QCC_CopyString (compilingfile);
3349
3350         pr_source_line = 0;
3351
3352         QCC_PR_NewLine (false);
3353
3354         QCC_PR_Lex ();  // read first token
3355 }
3356 void new_QCC_ContinueCompile(void)
3357 {
3358         if (setjmp(pr_parse_abort))
3359         {
3360 //              if (pr_error_count != 0)
3361                 {
3362                         QCC_Error (ERR_PARSEERRORS, "Errors have occured");
3363                         return;
3364                 }
3365                 QCC_PR_SkipToSemicolon ();
3366                 if (pr_token_type == tt_eof)
3367                         return;
3368         }
3369
3370         if (pr_token_type == tt_eof)
3371         {
3372                 if (pr_error_count)
3373                         QCC_Error (ERR_PARSEERRORS, "Errors have occured");
3374                 QCC_FinishCompile();
3375
3376                 PostCompile();
3377                 if (!PreCompile())
3378                         return;
3379                 QCC_main(myargc, myargv);
3380                 return;
3381         }
3382
3383         pr_scope = NULL;        // outside all functions
3384                                 
3385         QCC_PR_ParseDefs (NULL);
3386 }
3387
3388 /*void new_QCC_ContinueCompile(void)
3389 {
3390         char *s, *s2;
3391         if (!qcc_compileactive)
3392                 //HEY!
3393                 return;
3394
3395 // compile all the files
3396
3397                 qccmsrc = QCC_COM_Parse(qccmsrc);
3398                 if (!qccmsrc)
3399                 {
3400                         QCC_FinishCompile();
3401                         return;
3402                 }
3403                 s = qcc_token;
3404
3405                 strcpy (qccmfilename, qccmsourcedir);
3406                 while(1)
3407                 {
3408                         if (!strncmp(s, "..\\", 3))
3409                         {
3410                                 s2 = qccmfilename + strlen(qccmfilename)-2;
3411                                 while (s2>=qccmfilename)
3412                                 {
3413                                         if (*s2 == '/' || *s2 == '\\')
3414                                         {
3415                                                 s2[1] = '\0';
3416                                                 break;
3417                                         }
3418                                         s2--;
3419                                 }
3420                                 s+=3;
3421                                 continue;
3422                         }
3423                         if (!strncmp(s, ".\\", 2))
3424                         {
3425                                 s+=2;
3426                                 continue;
3427                         }
3428
3429                         break;
3430                 }
3431 //              strcat (qccmfilename, s);
3432 //              printf ("compiling %s\n", qccmfilename);
3433 //              QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
3434
3435 //              if (!new_QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
3436 //                      QCC_Error ("Errors have occured\n");
3437
3438
3439                 {
3440
3441                         if (!pr.memory)
3442                                 QCC_Error ("PR_CompileFile: Didn't clear");
3443
3444                         QCC_PR_ClearGrabMacros ();      // clear the frame macros
3445
3446                         compilingfile = filename;
3447                                         
3448                         pr_file_p = qccmsrc2;
3449                         s_file = QCC_CopyString (filename);
3450
3451                         pr_source_line = 0;
3452                         
3453                         QCC_PR_NewLine ();
3454
3455                         QCC_PR_Lex ();  // read first token
3456
3457                         while (pr_token_type != tt_eof)
3458                         {
3459                                 if (setjmp(pr_parse_abort))
3460                                 {
3461                                         if (++pr_error_count > MAX_ERRORS)
3462                                                 return false;
3463                                         QCC_PR_SkipToSemicolon ();
3464                                         if (pr_token_type == tt_eof)
3465                                                 return false;           
3466                                 }
3467
3468                                 pr_scope = NULL;        // outside all functions
3469                                 
3470                                 QCC_PR_ParseDefs ();
3471                         }
3472                 }
3473         return (pr_error_count == 0);
3474         
3475 }*/
3476
3477
3478 #endif