]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/fteqcc-src/qccmain.c
Better comment on my last change
[voretournament/voretournament.git] / misc / source / fteqcc-src / qccmain.c
1 #ifndef MINIMAL
2
3 #define PROGSUSED
4 #include "qcc.h"
5 #include <sys/stat.h>
6 #ifdef _WIN32
7 #include <direct.h>
8 #endif
9
10 #include "errno.h"
11
12 char QCC_copyright[1024];
13 int QCC_packid;
14 char QCC_Packname[5][128];
15
16 extern int optres_test1;
17 extern int optres_test2;
18
19 int writeasm;
20 static pbool pr_werror;
21 pbool verbose;
22
23
24 pbool QCC_PR_SimpleGetToken (void);
25 void QCC_PR_LexWhitespace (void);
26
27 void *FS_ReadToMem(char *fname, void *membuf, int *len);
28 void FS_CloseFromMem(void *mem);
29
30 struct qcc_includechunk_s *currentchunk;
31
32 unsigned int MAX_REGS;
33
34 int     MAX_STRINGS;
35 int     MAX_GLOBALS;
36 int     MAX_FIELDS;
37 int     MAX_STATEMENTS;
38 int     MAX_FUNCTIONS;
39 int MAX_CONSTANTS;
40 int max_temps;
41
42 int *qcc_tempofs;
43 int tempsstart;
44 int numtemps;
45
46 #define MAXSOURCEFILESLIST 8
47 char sourcefileslist[MAXSOURCEFILESLIST][1024];
48 int currentsourcefile;
49 int numsourcefiles;
50
51 void QCC_PR_ResetErrorScope(void);
52
53 pbool   compressoutput;
54
55 pbool newstylesource;
56 char            destfile[1024];
57
58 float           *qcc_pr_globals;
59 unsigned int    numpr_globals;
60
61 char            *strings;
62 int                     strofs;
63
64 QCC_dstatement_t        *statements;
65 int                     numstatements;
66 int                     *statement_linenums;
67
68 QCC_dfunction_t *functions;
69 int                     numfunctions;
70
71 QCC_ddef_t              *qcc_globals;
72 int                     numglobaldefs;
73
74 QCC_ddef_t              *fields;
75 int                     numfielddefs;
76
77 //typedef char PATHSTRING[MAX_DATA_PATH];
78
79 PATHSTRING              *precache_sounds;
80 int                     *precache_sounds_block;
81 int                     numsounds;
82
83 PATHSTRING              *precache_textures;
84 int                     *precache_textures_block;
85 int                     numtextures;
86
87 PATHSTRING              *precache_models;
88 int                     *precache_models_block;
89 int                     nummodels;
90
91 PATHSTRING              *precache_files;
92 int                     *precache_files_block;
93 int                     numfiles;
94
95 extern int numCompilerConstants;
96 hashtable_t compconstantstable;
97 hashtable_t globalstable;
98 hashtable_t localstable;
99 hashtable_t floatconstdefstable;
100 hashtable_t stringconstdefstable;
101 hashtable_t stringconstdefstable_dotranslate;
102 int dotranslate;
103 int dotranslate_count;
104
105 pbool qccwarningdisabled[WARN_MAX];
106
107 qcc_targetformat_t qcc_targetformat;
108
109 pbool bodylessfuncs;
110
111 QCC_type_t *qcc_typeinfo;
112 int numtypeinfos;
113 int maxtypeinfos;
114
115
116 struct {
117         char *name;
118         int index;
119 } warningnames[] =
120 {
121         {"Q302", WARN_NOTREFERENCED},
122 //      {"", WARN_NOTREFERENCEDCONST},
123 //      {"", WARN_CONFLICTINGRETURNS},
124         {"Q105", WARN_TOOFEWPARAMS},
125         {"Q101", WARN_TOOMANYPARAMS},
126 //      {"", WARN_UNEXPECTEDPUNCT},
127         {"Q106", WARN_ASSIGNMENTTOCONSTANT},
128         {"Q203", WARN_MISSINGRETURNVALUE},
129         {"Q204", WARN_WRONGRETURNTYPE},
130         {"Q205", WARN_POINTLESSSTATEMENT},
131         {"Q206", WARN_MISSINGRETURN},
132         {"Q207", WARN_DUPLICATEDEFINITION},
133         {"Q100", WARN_PRECOMPILERMESSAGE},
134 //      {"", WARN_STRINGTOOLONG},
135 //      {"", WARN_BADTARGET},
136         {"Q120", WARN_BADPRAGMA},
137 //      {"", WARN_HANGINGSLASHR},
138 //      {"", WARN_NOTDEFINED},
139 //      {"", WARN_SWITCHTYPEMISMATCH},
140 //      {"", WARN_CONFLICTINGUNIONMEMBER},
141 //      {"", WARN_KEYWORDDISABLED},
142 //      {"", WARN_ENUMFLAGS_NOTINTEGER},
143 //      {"", WARN_ENUMFLAGS_NOTBINARY},
144 //      {"", WARN_CASEINSENSATIVEFRAMEMACRO},
145         {"Q111", WARN_DUPLICATELABEL},
146         {"Q201", WARN_ASSIGNMENTINCONDITIONAL},
147         {"F300", WARN_DEADCODE},
148         {NULL}
149 };
150
151 int QCC_WarningForName(char *name)
152 {
153         int i;
154         for (i = 0; warningnames[i].name; i++)
155         {
156                 if (!stricmp(name, warningnames[i].name))
157                         return warningnames[i].index;
158         }
159         return -1;
160 }
161
162 optimisations_t optimisations[] =
163 {
164         //level 0 = no optimisations
165         //level 1 = size optimisations
166         //level 2 = speed optimisations
167         //level 3 = dodgy optimisations.
168         //level 4 = experimental...
169
170         {&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."},
171         {&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."},
172         {&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."},
173         {&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."},
174         {&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."},
175         {&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."},
176         {&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."},
177         {&opt_locals,                                   "l",    1,      FLAG_KILLSDEBUGGERS,    "locals",                       "Strips out local names and definitions. This makes it REALLY hard to decompile"},
178         {&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."},
179         {&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."},
180         {&opt_unreferenced,                             "u",    1,      FLAG_ASDEFAULT,                 "unreferenced",         "Removes the entries of unreferenced variables. Doesn't make a difference in well maintained code."},
181         {&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."},
182         {&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"},
183         {&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)."},
184         {&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."},
185         {&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."},
186 //      {&opt_comexprremoval,                   "cer",  4,      0,                                              "expression_removal",   "Eliminate common sub-expressions"},    //this would be too hard...
187         {&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."},
188         {&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."},
189         {&opt_vectorcalls,                              "vc",   4,      FLAG_KILLSDEBUGGERS,                                    "vectorcalls",          "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."},
190         {NULL}
191 };
192
193 #define defaultkeyword FLAG_HIDDENINGUI|FLAG_ASDEFAULT|FLAG_MIDCOMPILE
194 #define nondefaultkeyword FLAG_HIDDENINGUI|0|FLAG_MIDCOMPILE
195 //global to store useage to, flags, codename, human-readable name, help text
196 compiler_flag_t compiler_flag[] = {
197         //keywords
198         {&keyword_asm,                  defaultkeyword, "asm",                  "Keyword: asm",                 "Disables the 'asm' keyword. Use the writeasm flag to see an example of the asm."},
199         {&keyword_break,                defaultkeyword, "break",                "Keyword: break",               "Disables the 'break' keyword."},
200         {&keyword_case,                 defaultkeyword, "case",                 "Keyword: case",                "Disables the 'case' keyword."},
201         {&keyword_class,                defaultkeyword, "class",                "Keyword: class",               "Disables the 'class' keyword."},
202         {&keyword_const,                defaultkeyword, "const",                "Keyword: const",               "Disables the 'const' keyword."},
203         {&keyword_continue,             defaultkeyword, "continue",             "Keyword: continue",    "Disables the 'continue' keyword."},
204         {&keyword_default,              defaultkeyword, "default",              "Keyword: default",             "Disables the 'default' keyword."},
205         {&keyword_entity,               defaultkeyword, "entity",               "Keyword: entity",              "Disables the 'entity' keyword."},
206         {&keyword_enum,                 defaultkeyword, "enum",                 "Keyword: enum",                "Disables the 'enum' keyword."},        //kinda like in c, but typedef not supported.
207         {&keyword_enumflags,    defaultkeyword, "enumflags",    "Keyword: enumflags",   "Disables the 'enumflags' keyword."},   //like enum, but doubles instead of adds 1.
208         {&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
209         {&keyword_float,                defaultkeyword, "float",                "Keyword: float",               "Disables the 'float' keyword. (Disables the float keyword without 'local' preceeding it)"},
210         {&keyword_for,                  defaultkeyword, "for",                  "Keyword: for",                 "Disables the 'for' keyword. Syntax: for(assignment; while; increment) {codeblock;}"},
211         {&keyword_goto,                 defaultkeyword, "goto",                 "Keyword: goto",                "Disables the 'goto' keyword."},
212         {&keyword_int,                  defaultkeyword, "int",                  "Keyword: int",                 "Disables the 'int' keyword."},
213         {&keyword_integer,              defaultkeyword, "integer",              "Keyword: integer",             "Disables the 'integer' keyword."},
214         {&keyword_noref,                defaultkeyword, "noref",                "Keyword: noref",               "Disables the 'noref' keyword."},       //nowhere else references this, don't strip it.
215         {&keyword_nosave,               defaultkeyword, "nosave",               "Keyword: nosave",              "Disables the 'nosave' keyword."},      //don't write the def to the output.
216         {&keyword_shared,               defaultkeyword, "shared",               "Keyword: shared",              "Disables the 'shared' keyword."},      //mark global to be copied over when progs changes (part of FTE_MULTIPROGS)
217         {&keyword_state,                nondefaultkeyword,"state",              "Keyword: state",               "Disables the 'state' keyword."},
218         {&keyword_string,               defaultkeyword, "string",               "Keyword: string",              "Disables the 'string' keyword."},
219         {&keyword_struct,               defaultkeyword, "struct",               "Keyword: struct",              "Disables the 'struct' keyword."},
220         {&keyword_switch,               defaultkeyword, "switch",               "Keyword: switch",              "Disables the 'switch' keyword."},
221         {&keyword_thinktime,    nondefaultkeyword,"thinktime",  "Keyword: thinktime",   "Disables the 'thinktime' keyword which is used in HexenC"},
222         {&keyword_typedef,              defaultkeyword, "typedef",              "Keyword: typedef",             "Disables the 'typedef' keyword."},     //fixme
223         {&keyword_union,                defaultkeyword, "union",                "Keyword: union",               "Disables the 'union' keyword."},       //you surly know what a union is!
224         {&keyword_var,                  defaultkeyword, "var",                  "Keyword: var",                 "Disables the 'var' keyword."},
225         {&keyword_vector,               defaultkeyword, "vector",               "Keyword: vector",              "Disables the 'vector' keyword."},
226
227
228         //options
229         {&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."},
230         {&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)
231         {&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.
232         {&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)
233         {&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.
234         {&flag_iffloat,                 FLAG_MIDCOMPILE,"iffloat","if(-0.0) fix","Fixes certain floating point logic."},
235         {&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.
236         {&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
237         {&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.
238         {&flag_hashonly,                FLAG_MIDCOMPILE,"hashonly",             "Hash-only constants",  "Allows use of only #constant for precompiler constants, allows certain preqcc using mods to compile"},
239         {&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))"},
240         {&flag_msvcstyle,               FLAG_MIDCOMPILE,"msvcstyle",    "MSVC-style errors",    "Generates warning and error messages in a format that msvc understands, to facilitate ide integration."},
241         {&flag_filetimes,               0,                              "filetimes",    "Check Filetimes",              "Recompiles the progs only if the file times are modified."},
242         {&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."},
243         {&flag_assume_integer,  FLAG_MIDCOMPILE,"assumeint",    "Assume Integers",              "Numerical constants are assumed to be integers, instead of floats."},
244         {&pr_subscopedlocals,           FLAG_MIDCOMPILE,                "subscope",     "Subscoped Locals",             "Restrict the scope of locals to the block they are actually defined within, as in C."},
245         {NULL}
246 };
247
248 struct {
249         qcc_targetformat_t target;
250         char *name;
251 } targets[] = {
252         {QCF_STANDARD,  "standard"},
253         {QCF_STANDARD,  "q1"},
254         {QCF_STANDARD,  "quakec"},
255         {QCF_HEXEN2,    "hexen2"},
256         {QCF_HEXEN2,    "h2"},
257         {QCF_KK7,               "kkqwsv"},
258         {QCF_KK7,               "kk7"},
259         {QCF_KK7,               "bigprogs"},
260         {QCF_KK7,               "version7"},
261         {QCF_KK7,               "kkqwsv"},
262         {QCF_FTE,               "fte"},
263         {QCF_DARKPLACES,"darkplaces"},
264         {QCF_DARKPLACES,"dp"},
265         {QCF_QTEST,             "qtest"},
266         {0,                             NULL}
267 };
268
269 /*
270 =================
271 BspModels
272
273 Runs qbsp and light on all of the models with a .bsp extension
274 =================
275 */
276 int QCC_CheckParm (char *check);
277
278 void QCC_BspModels (void)
279 {
280         int             p;
281         char    *gamedir;
282         int             i;
283         char    *m;
284         char    cmd[1024];
285         char    name[256];
286         size_t result;
287
288         p = QCC_CheckParm ("-bspmodels");
289         if (!p)
290                 return;
291         if (p == myargc-1)
292                 QCC_Error (ERR_BADPARMS, "-bspmodels must preceed a game directory");
293         gamedir = myargv[p+1];
294
295         for (i=0 ; i<nummodels ; i++)
296         {
297                 m = precache_models[i];
298                 if (strcmp(m+strlen(m)-4, ".bsp"))
299                         continue;
300                 strcpy (name, m);
301                 name[strlen(m)-4] = 0;
302                 sprintf (cmd, "qbsp %s/%s ; light -extra %s/%s", gamedir, name, gamedir, name);
303                 result = system (cmd); // do something with the result
304
305                 if (result != 0)
306                         QCC_Error(ERR_INTERNAL, "QCC_BspModels() system returned non zero (failure) with: qbsp %s/%s ; light -extra %s/%s (%i)\n", gamedir, name, gamedir, name, errno);
307         }
308 }
309
310 // CopyString returns an offset from the string heap
311 int     QCC_CopyString (char *str)
312 {
313         int             old;
314         char *s;
315
316         if (opt_noduplicatestrings)
317         {
318                 if (!str || !*str)
319                         return 0;
320
321                 for (s = strings; s < strings+strofs; s++)
322                         if (!strcmp(s, str))
323                         {
324                                 optres_noduplicatestrings += strlen(str);
325                                 return s-strings;
326                         }
327         }
328
329         old = strofs;
330         strcpy (strings+strofs, str);
331         strofs += strlen(str)+1;
332         return old;
333 }
334
335 int     QCC_CopyDupBackString (char *str)
336 {
337         int             old;
338         char *s;
339
340         for (s = strings+strofs-1; s>strings ; s--)
341                 if (!strcmp(s, str))
342                         return s-strings;
343
344         old = strofs;
345         strcpy (strings+strofs, str);
346         strofs += strlen(str)+1;
347         return old;
348 }
349
350 void QCC_PrintStrings (void)
351 {
352         int             i, l, j;
353
354         for (i=0 ; i<strofs ; i += l)
355         {
356                 l = strlen(strings+i) + 1;
357                 printf ("%5i : ",i);
358                 for (j=0 ; j<l ; j++)
359                 {
360                         if (strings[i+j] == '\n')
361                         {
362                                 putchar ('\\');
363                                 putchar ('n');
364                         }
365                         else
366                                 putchar (strings[i+j]);
367                 }
368                 printf ("\n");
369         }
370 }
371
372
373 /*void QCC_PrintFunctions (void)
374 {
375         int             i,j;
376         QCC_dfunction_t *d;
377
378         for (i=0 ; i<numfunctions ; i++)
379         {
380                 d = &functions[i];
381                 printf ("%s : %s : %i %i (", strings + d->s_file, strings + d->s_name, d->first_statement, d->parm_start);
382                 for (j=0 ; j<d->numparms ; j++)
383                         printf ("%i ",d->parm_size[j]);
384                 printf (")\n");
385         }
386 }*/
387
388 void QCC_PrintFields (void)
389 {
390         int             i;
391         QCC_ddef_t      *d;
392
393         for (i=0 ; i<numfielddefs ; i++)
394         {
395                 d = &fields[i];
396                 printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
397         }
398 }
399
400 void QCC_PrintGlobals (void)
401 {
402         int             i;
403         QCC_ddef_t      *d;
404
405         for (i=0 ; i<numglobaldefs ; i++)
406         {
407                 d = &qcc_globals[i];
408                 printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
409         }
410 }
411
412 int encode(int len, int method, char *in, int handle);
413 int WriteSourceFiles(int h, dprograms_t *progs, pbool sourceaswell)
414 {
415         includeddatafile_t *idf;
416         qcc_cachedsourcefile_t *f;
417         int num=0;
418         int ofs;
419
420         /*
421         for (f = qcc_sourcefile; f ; f=f->next)
422         {
423                 if (f->type == FT_CODE && !sourceaswell)
424                         continue;
425
426                 SafeWrite(h, f->filename, strlen(f->filename)+1);
427                 i = PRLittleLong(f->size);
428                 SafeWrite(h, &i, sizeof(int));
429
430                 i = PRLittleLong(encrpytmode);
431                 SafeWrite(h, &i, sizeof(int));
432
433                 if (encrpytmode)
434                         for (i = 0; i < f->size; i++)
435                                 f->file[i] ^= 0xA5;
436
437                 SafeWrite(h, f->file, f->size);
438         }*/
439
440         for (f = qcc_sourcefile,num=0; f ; f=f->next)
441         {
442                 if (f->type == FT_CODE && !sourceaswell)
443                         continue;
444
445                 num++;
446         }
447         if (!num)
448                 return 0;
449         idf = qccHunkAlloc(sizeof(includeddatafile_t)*num);
450         for (f = qcc_sourcefile,num=0; f ; f=f->next)
451         {
452                 if (f->type == FT_CODE && !sourceaswell)
453                         continue;
454
455                 strcpy(idf[num].filename, f->filename);
456                 idf[num].size = f->size;
457 #ifdef AVAIL_ZLIB
458                 idf[num].compmethod = 2;
459 #else
460                 idf[num].compmethod = 1;
461 #endif
462                 idf[num].ofs = SafeSeek(h, 0, SEEK_CUR);
463                 idf[num].compsize = QC_encode(progfuncs, f->size, idf[num].compmethod, f->file, h);
464                 num++;
465         }
466
467         ofs = SafeSeek(h, 0, SEEK_CUR);
468         SafeWrite(h, &num, sizeof(int));
469         SafeWrite(h, idf, sizeof(includeddatafile_t)*num);
470
471         qcc_sourcefile = NULL;
472
473         return ofs;
474 }
475
476 void QCC_InitData (void)
477 {
478         static char parmname[12][MAX_PARMS];
479         static temp_t ret_temp;
480         int             i;
481
482         qcc_sourcefile = NULL;
483
484         numstatements = 1;
485         strofs = 1;
486         numfunctions = 1;
487         numglobaldefs = 1;
488         numfielddefs = 1;
489
490         memset(&ret_temp, 0, sizeof(ret_temp));
491
492         def_ret.ofs = OFS_RETURN;
493         def_ret.name = "return";
494         def_ret.temp = &ret_temp;
495         def_ret.constant = false;
496         def_ret.type    = NULL;
497         ret_temp.ofs = def_ret.ofs;
498         ret_temp.scope = NULL;
499         ret_temp.size = 3;
500         ret_temp.next = NULL;
501         for (i=0 ; i<MAX_PARMS ; i++)
502         {
503                 def_parms[i].temp = NULL;
504                 def_parms[i].type = NULL;
505                 def_parms[i].ofs = OFS_PARM0 + 3*i;
506                 def_parms[i].name = parmname[i];
507                 sprintf(parmname[i], "parm%i", i);
508         }
509 }
510
511 int WriteBodylessFuncs (int handle)
512 {
513         QCC_def_t               *d;
514         int ret=0;
515         for (d=pr.def_head.next ; d ; d=d->next)
516         {
517                 if (d->type->type == ev_function && !d->scope)// function parms are ok
518                 {
519                         if (d->initialized != 1 && d->references>0)
520                         {
521                                 SafeWrite(handle, d->name, strlen(d->name)+1);
522                                 ret++;
523                         }
524                 }
525         }
526
527         return ret;
528 }
529
530 //marshalled locals remaps all the functions to use the range MAX_REGS onwards for the offset to their locals.
531 //this function remaps all the locals back into the function.
532 void QCC_UnmarshalLocals(void)
533 {
534         QCC_def_t               *def;
535         unsigned int ofs;
536         unsigned int maxo;
537         int i;
538
539         ofs = numpr_globals;
540         maxo = ofs;
541
542         for (def = pr.def_head.next ; def ; def = def->next)
543         {
544                 if (def->ofs >= MAX_REGS)       //unmap defs.
545                 {
546                         def->ofs = def->ofs + ofs - MAX_REGS;
547                         if (maxo < def->ofs)
548                                 maxo = def->ofs;
549                 }
550         }
551
552         for (i = 0; i < numfunctions; i++)
553         {
554                 if (functions[i].parm_start == MAX_REGS)
555                         functions[i].parm_start = ofs;
556         }
557
558         QCC_RemapOffsets(0, numstatements, MAX_REGS, MAX_REGS + maxo-numpr_globals + 3, ofs);
559
560         numpr_globals = maxo+3;
561         if (numpr_globals > MAX_REGS)
562                 QCC_Error(ERR_TOOMANYGLOBALS, "Too many globals are in use to unmarshal all locals");
563
564         if (maxo-ofs)
565                 printf("Total of %i marshalled globals\n", maxo-ofs);
566 }
567
568 CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def);
569 pbool QCC_WriteData (int crc)
570 {
571         char element[MAX_NAME];
572         QCC_def_t               *def, *comp_x, *comp_y, *comp_z;
573         QCC_ddef_t              *dd;
574         dprograms_t     progs;
575         int                     h;
576         int                     i, len;
577         pbool debugtarget = false;
578         pbool types = false;
579         int outputsttype = PST_DEFAULT;
580         pbool warnedunref = false;
581
582         if (numstatements==1 && numfunctions==1 && numglobaldefs==1 && numfielddefs==1)
583         {
584                 printf("nothing to write\n");
585                 return false;
586         }
587
588         progs.blockscompressed=0;
589
590         if (numstatements > MAX_STATEMENTS)
591                 QCC_Error(ERR_TOOMANYSTATEMENTS, "Too many statements - %i\nAdd \"MAX_STATEMENTS\" \"%i\" to qcc.cfg", numstatements, (numstatements+32768)&~32767);
592
593         if (strofs > MAX_STRINGS)
594                 QCC_Error(ERR_TOOMANYSTRINGS, "Too many strings - %i\nAdd \"MAX_STRINGS\" \"%i\" to qcc.cfg", strofs, (strofs+32768)&~32767);
595
596         QCC_UnmarshalLocals();
597
598         switch (qcc_targetformat)
599         {
600         case QCF_HEXEN2:
601         case QCF_STANDARD:
602                 if (bodylessfuncs)
603                         printf("Warning: There are some functions without bodies.\n");
604
605                 if (numpr_globals > 65530 )
606                 {
607                         printf("Forcing target to FTE32 due to numpr_globals\n");
608                         outputsttype = PST_FTE32;
609                 }
610                 else if (qcc_targetformat == QCF_HEXEN2)
611                 {
612                         printf("Progs execution requires a Hexen2 compatible engine\n");
613                         break;
614                 }
615                 else
616                 {
617                         if (numpr_globals >= 32768)     //not much of a different format. Rewrite output to get it working on original executors?
618                                 printf("An enhanced executor will be required (FTE/QF/KK)\n");
619                         else
620                                 printf("Progs should run on any Quake executor\n");
621                         break;
622                 }
623                 //intentional
624                 qcc_targetformat = QCF_FTE;
625         case QCF_FTEDEBUG:
626         case QCF_FTE:
627         case QCF_DARKPLACES:
628                 if (qcc_targetformat == QCF_FTEDEBUG)
629                         debugtarget = true;
630
631                 if (numpr_globals > 65530)
632                 {
633                         printf("Using 32 bit target due to numpr_globals\n");
634                         outputsttype = PST_FTE32;
635                 }
636
637                 if (qcc_targetformat == QCF_DARKPLACES)
638                         compressoutput = 0;
639
640
641                 //compression of blocks?
642                 if (compressoutput)             progs.blockscompressed |=1;             //statements
643                 if (compressoutput)             progs.blockscompressed |=2;             //defs
644                 if (compressoutput)             progs.blockscompressed |=4;             //fields
645                 if (compressoutput)             progs.blockscompressed |=8;             //functions
646                 if (compressoutput)             progs.blockscompressed |=16;    //strings
647                 if (compressoutput)             progs.blockscompressed |=32;    //globals
648                 if (compressoutput)             progs.blockscompressed |=64;    //line numbers
649                 if (compressoutput)             progs.blockscompressed |=128;   //types
650                 //include a type block?
651                 types = debugtarget;//!!QCC_PR_CheckCompConstDefined("TYPES");  //useful for debugging and saving (maybe, anyway...).
652                 if (sizeof(char *) != sizeof(string_t))
653                 {
654                         //qcc_typeinfo_t has a char* inside it, which changes size
655                         printf("AMD64 builds cannot write typeinfo structures\n");
656                         types = false;
657                 }
658
659                 if (verbose)
660                 {
661                         if (qcc_targetformat == QCF_DARKPLACES)
662                                 printf("DarkPlaces or FTE will be required\n");
663                         else
664                                 printf("An FTE executor will be required\n");
665                 }
666                 break;
667         case QCF_KK7:
668                 if (bodylessfuncs)
669                         printf("Warning: There are some functions without bodies.\n");
670                 if (numpr_globals > 65530)
671                         printf("Warning: Saving is not supported. Ensure all engine read fields and globals are defined early on.\n");
672
673                 printf("A KK compatible executor will be required (FTE/KK)\n");
674                 outputsttype = PST_KKQWSV;
675                 break;
676         case QCF_QTEST:
677                 printf("Compiled QTest progs will most likely not work at all. YOU'VE BEEN WARNED!\n");
678                 outputsttype = PST_QTEST;
679                 break;
680         default:
681                 Sys_Error("invalid progs type chosen!");
682         }
683
684         //part of how compilation works. This def is always present, and never used.
685         def = QCC_PR_GetDef(NULL, "end_sys_globals", NULL, false, 0, false);
686         if (def)
687                 def->references++;
688
689         def = QCC_PR_GetDef(NULL, "end_sys_fields", NULL, false, 0, false);
690         if (def)
691                 def->references++;
692
693         for (def = pr.def_head.next ; def ; def = def->next)
694         {
695                 if (def->type->type == ev_vector || (def->type->type == ev_field && def->type->aux_type->type == ev_vector))
696                 {       //do the references, so we don't get loadsa not referenced VEC_HULL_MINS_x
697                         sprintf(element, "%s_x", def->name);
698                         comp_x = QCC_PR_GetDef(NULL, element, def->scope, false, 0, false);
699                         sprintf(element, "%s_y", def->name);
700                         comp_y = QCC_PR_GetDef(NULL, element, def->scope, false, 0, false);
701                         sprintf(element, "%s_z", def->name);
702                         comp_z = QCC_PR_GetDef(NULL, element, def->scope, false, 0, false);
703
704                         h = def->references;
705                         if (comp_x && comp_y && comp_z)
706                         {
707                                 h += comp_x->references;
708                                 h += comp_y->references;
709                                 h += comp_z->references;
710
711                                 if (!def->references)
712                                         if (!comp_x->references || !comp_y->references || !comp_z->references)  //one of these vars is useless...
713                                                 h=0;
714
715                                 def->references = h;
716
717
718                                 if (!h)
719                                         h = 1;
720                                 if (comp_x)
721                                         comp_x->references = h;
722                                 if (comp_y)
723                                         comp_y->references = h;
724                                 if (comp_z)
725                                         comp_z->references = h;
726                         }
727                 }
728                 if (def->references<=0)
729                 {
730                         if (def->constant)
731                                 QCC_PR_Warning(WARN_NOTREFERENCEDCONST, strings + def->s_file, def->s_line, "%s  no references", def->name);
732                         else
733                                 QCC_PR_Warning(WARN_NOTREFERENCED, strings + def->s_file, def->s_line, "%s  no references", def->name);
734                         if (!warnedunref)
735                         {
736                                 QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "You can use the noref prefix or pragma to silence this message.");
737                                 warnedunref = true;
738                         }
739
740                         if (opt_unreferenced && def->type->type != ev_field)
741                         {
742                                 optres_unreferenced++;
743                                 continue;
744                         }
745                 }
746
747                 if (def->type->type == ev_function)
748                 {
749                         if (opt_function_names && functions[G_FUNCTION(def->ofs)].first_statement<0)
750                         {
751                                 optres_function_names++;
752                                 def->name = "";
753                         }
754                         if (!def->timescalled)
755                         {
756                                 if (def->references<=1)
757                                         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);
758 //                              else
759 //                                      QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called", def->name);
760                         }
761                         if (opt_stripfunctions && def->timescalled >= def->references-1)        //make sure it's not copied into a different var.
762                         {                                                               //if it ever does self.think then it could be needed for saves.
763                                 optres_stripfunctions++;        //if it's only ever called explicitly, the engine doesn't need to know.
764                                 continue;
765                         }
766
767 //                      df = &functions[numfunctions];
768 //                      numfunctions++;
769
770                 }
771                 else if (def->type->type == ev_field && def->constant)
772                 {
773                         dd = &fields[numfielddefs];
774                         numfielddefs++;
775                         dd->type = def->type->aux_type->type;
776                         dd->s_name = QCC_CopyString (def->name);
777                         dd->ofs = G_INT(def->ofs);
778                 }
779                 else if ((def->scope||def->constant) && (def->type->type != ev_string || opt_constant_names_strings))
780                 {
781                         if (opt_constant_names)
782                         {
783                                 if (def->type->type == ev_string)
784                                         optres_constant_names_strings += strlen(def->name);
785                                 else
786                                         optres_constant_names += strlen(def->name);
787                                 continue;
788                         }
789                 }
790
791 //              if (!def->saved && def->type->type != ev_string)
792 //                      continue;
793                 dd = &qcc_globals[numglobaldefs];
794                 numglobaldefs++;
795
796                 if (types)
797                         dd->type = def->type-qcc_typeinfo;
798                 else
799                         dd->type = def->type->type;
800 #ifdef DEF_SAVEGLOBAL
801                 if ( def->saved && ((!def->initialized || def->type->type == ev_function)
802 //              && def->type->type != ev_function
803                 && def->type->type != ev_field
804                 && def->scope == NULL))
805                 {
806                         dd->type |= DEF_SAVEGLOBAL;
807                 }
808 #endif
809                 if (def->shared)
810                         dd->type |= DEF_SHARED;
811
812                 if (opt_locals && (def->scope || !strcmp(def->name, "IMMEDIATE")))
813                 {
814                         dd->s_name = 0;
815                         optres_locals += strlen(def->name);
816                 }
817                 else
818                         dd->s_name = QCC_CopyString (def->name);
819                 dd->ofs = def->ofs;
820         }
821
822         for (i = 0; i < numglobaldefs; i++)
823         {
824                 dd = &qcc_globals[i];
825                 if (!(dd->type & DEF_SAVEGLOBAL))       //only warn about saved ones.
826                         continue;
827
828                 for (h = 0; h < numglobaldefs; h++)
829                 {
830                         if (i == h)
831                                 continue;
832                         if (dd->ofs == qcc_globals[h].ofs)
833                         {
834                                 if (dd->type != qcc_globals[h].type)
835                                 {
836                                         if (dd->type != ev_vector && qcc_globals[h].type != ev_float)
837                                                 QCC_PR_Warning(0, NULL, 0, "Mismatched union global types (%s and %s)", strings+dd->s_name, strings+qcc_globals[h].s_name);
838                                 }
839                                 //remove the saveglobal flag on the duplicate globals.
840                                 qcc_globals[h].type &= ~DEF_SAVEGLOBAL;
841                         }
842                 }
843         }
844         for (i = 1; i < numfielddefs; i++)
845         {
846                 dd = &fields[i];
847
848                 if (dd->type == ev_vector)      //just ignore vectors.
849                         continue;
850
851                 for (h = 1; h < numfielddefs; h++)
852                 {
853                         if (i == h)
854                                 continue;
855                         if (dd->ofs == fields[h].ofs)
856                         {
857                                 if (dd->type != fields[h].type)
858                                 {
859                                         if (fields[h].type != ev_vector)
860                                         {
861                                                 QCC_PR_Warning(0, NULL, 0, "Mismatched union field types (%s and %s)", strings+dd->s_name, strings+fields[h].s_name);
862                                         }
863                                 }
864                         }
865                 }
866         }
867
868         if (numglobaldefs > MAX_GLOBALS)
869                 QCC_Error(ERR_TOOMANYGLOBALS, "Too many globals - %i\nAdd \"MAX_GLOBALS\" \"%i\" to qcc.cfg", numglobaldefs, (numglobaldefs+32768)&~32767);
870
871
872         for (i = 0; i < nummodels; i++)
873         {
874                 if (!precache_models_used[i])
875                         QCC_PR_Warning(WARN_EXTRAPRECACHE, NULL, 0, "Model %s was precached but not directly used", precache_models[i]);
876                 else if (!precache_models_block[i])
877                         QCC_PR_Warning(WARN_NOTPRECACHED, NULL, 0, "Model %s was used but not precached", precache_models[i]);
878         }
879 //PrintStrings ();
880 //PrintFunctions ();
881 //PrintFields ();
882 //PrintGlobals ();
883 strofs = (strofs+3)&~3;
884
885         if (verbose)
886         {
887                 printf ("%6i strofs (of %i)\n", strofs, MAX_STRINGS);
888                 printf ("%6i numstatements (of %i)\n", numstatements, MAX_STATEMENTS);
889                 printf ("%6i numfunctions (of %i)\n", numfunctions, MAX_FUNCTIONS);
890                 printf ("%6i numglobaldefs (of %i)\n", numglobaldefs, MAX_GLOBALS);
891                 printf ("%6i numfielddefs (%i unique) (of %i)\n", numfielddefs, pr.size_fields, MAX_FIELDS);
892                 printf ("%6i numpr_globals (of %i)\n", numpr_globals, MAX_REGS);
893         }
894
895         if (!*destfile)
896                 strcpy(destfile, "progs.dat");
897         if (verbose)
898                 printf("Writing %s\n", destfile);
899         h = SafeOpenWrite (destfile, 2*1024*1024);
900         SafeWrite (h, &progs, sizeof(progs));
901         SafeWrite (h, "\r\n\r\n", 4);
902         SafeWrite (h, QCC_copyright, strlen(QCC_copyright)+1);
903         SafeWrite (h, "\r\n\r\n", 4);
904         while(SafeSeek (h, 0, SEEK_CUR) & 3)//this is a lame way to do it
905         {
906                 SafeWrite (h, "\0", 1);
907         }
908
909         progs.ofs_strings = SafeSeek (h, 0, SEEK_CUR);
910         progs.numstrings = strofs;
911
912         if (progs.blockscompressed&16)
913         {
914                 SafeWrite (h, &len, sizeof(int));       //save for later
915                 len = QC_encode(progfuncs, strofs*sizeof(char), 2, (char *)strings, h); //write
916                 i = SafeSeek (h, 0, SEEK_CUR);
917                 SafeSeek(h, progs.ofs_strings, SEEK_SET);//seek back
918                 len = PRLittleLong(len);
919                 SafeWrite (h, &len, sizeof(int));       //write size.
920                 SafeSeek(h, i, SEEK_SET);
921         }
922         else
923                 SafeWrite (h, strings, strofs);
924
925         progs.ofs_statements = SafeSeek (h, 0, SEEK_CUR);
926         progs.numstatements = numstatements;
927
928         if (qcc_targetformat == QCF_HEXEN2)
929         {
930                 for (i=0 ; i<numstatements ; i++)
931                 {
932                         if (statements[i].op >= OP_CALL1 && statements[i].op <= OP_CALL8)
933                                 QCC_Error(ERR_BADTARGETSWITCH, "Target switching produced incompatible instructions");
934                         else if (statements[i].op >= OP_CALL1H && statements[i].op <= OP_CALL8H)
935                                 statements[i].op = statements[i].op - OP_CALL1H + OP_CALL1;
936                 }
937         }
938
939         for (i=0 ; i<numstatements ; i++)
940
941         switch(outputsttype)
942         {
943         case PST_KKQWSV:
944         case PST_FTE32:
945                 for (i=0 ; i<numstatements ; i++)
946                 {
947                         statements[i].op = PRLittleLong/*PRLittleShort*/(statements[i].op);
948                         statements[i].a = PRLittleLong/*PRLittleShort*/(statements[i].a);
949                         statements[i].b = PRLittleLong/*PRLittleShort*/(statements[i].b);
950                         statements[i].c = PRLittleLong/*PRLittleShort*/(statements[i].c);
951                 }
952
953                 if (progs.blockscompressed&1)
954                 {
955                         SafeWrite (h, &len, sizeof(int));       //save for later
956                         len = QC_encode(progfuncs, numstatements*sizeof(QCC_dstatement32_t), 2, (char *)statements, h); //write
957                         i = SafeSeek (h, 0, SEEK_CUR);
958                         SafeSeek(h, progs.ofs_statements, SEEK_SET);//seek back
959                         len = PRLittleLong(len);
960                         SafeWrite (h, &len, sizeof(int));       //write size.
961                         SafeSeek(h, i, SEEK_SET);
962                 }
963                 else
964                         SafeWrite (h, statements, numstatements*sizeof(QCC_dstatement32_t));
965                 break;
966         case PST_QTEST:
967 #define qtst ((qtest_statement_t*) statements)
968                 for (i=0 ; i<numstatements ; i++) // scale down from 16-byte internal to 12-byte qtest
969                 {
970                         QCC_dstatement_t stmt = statements[i];
971                         qtst[i].line = 0; // no line support
972                         qtst[i].op = PRLittleShort((unsigned short)stmt.op);
973                         if (stmt.a < 0)
974                                 qtst[i].a = PRLittleShort((short)stmt.a);
975                         else
976                                 qtst[i].a = (unsigned short)PRLittleShort((unsigned short)stmt.a);
977                         if (stmt.b < 0)
978                                 qtst[i].b = PRLittleShort((short)stmt.b);
979                         else
980                                 qtst[i].b = (unsigned short)PRLittleShort((unsigned short)stmt.b);
981                         if (stmt.c < 0)
982                                 qtst[i].c = PRLittleShort((short)stmt.c);
983                         else
984                                 qtst[i].c = (unsigned short)PRLittleShort((unsigned short)stmt.c);
985                 }
986
987                 // no compression
988                 SafeWrite (h, qtst, numstatements*sizeof(qtest_statement_t));
989 #undef qtst
990                 break;
991         case PST_DEFAULT:
992 #define statements16 ((QCC_dstatement16_t*) statements)
993                 for (i=0 ; i<numstatements ; i++)       //resize as we go - scaling down
994                 {
995                         statements16[i].op = PRLittleShort((unsigned short)statements[i].op);
996                         if (statements[i].a < 0)
997                                 statements16[i].a = PRLittleShort((short)statements[i].a);
998                         else
999                                 statements16[i].a = (unsigned short)PRLittleShort((unsigned short)statements[i].a);
1000                         if (statements[i].b < 0)
1001                                 statements16[i].b = PRLittleShort((short)statements[i].b);
1002                         else
1003                                 statements16[i].b = (unsigned short)PRLittleShort((unsigned short)statements[i].b);
1004                         if (statements[i].c < 0)
1005                                 statements16[i].c = PRLittleShort((short)statements[i].c);
1006                         else
1007                                 statements16[i].c = (unsigned short)PRLittleShort((unsigned short)statements[i].c);
1008                 }
1009
1010                 if (progs.blockscompressed&1)
1011                 {
1012                         SafeWrite (h, &len, sizeof(int));       //save for later
1013                         len = QC_encode(progfuncs, numstatements*sizeof(QCC_dstatement16_t), 2, (char *)statements16, h);       //write
1014                         i = SafeSeek (h, 0, SEEK_CUR);
1015                         SafeSeek(h, progs.ofs_statements, 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, statements16, numstatements*sizeof(QCC_dstatement16_t));
1022                 break;
1023         default:
1024                 Sys_Error("structtype error");
1025         }
1026
1027         progs.ofs_functions = SafeSeek (h, 0, SEEK_CUR);
1028         progs.numfunctions = numfunctions;
1029
1030         switch (outputsttype)
1031         {
1032         case PST_QTEST:
1033                 {
1034                         // this sucks but the structures are just too different
1035                         qtest_function_t *qtestfuncs = (qtest_function_t *)qccHunkAlloc(sizeof(qtest_function_t)*numfunctions);
1036
1037                         for (i=0 ; i<numfunctions ; i++)
1038                         {
1039                                 int j;
1040
1041                                 qtestfuncs[i].unused1 = 0;
1042                                 qtestfuncs[i].profile = 0;
1043                                 qtestfuncs[i].first_statement = PRLittleLong (functions[i].first_statement);
1044                                 qtestfuncs[i].parm_start = PRLittleLong (functions[i].parm_start);
1045                                 qtestfuncs[i].s_name = PRLittleLong (functions[i].s_name);
1046                                 qtestfuncs[i].s_file = PRLittleLong (functions[i].s_file);
1047                                 qtestfuncs[i].numparms = PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
1048                                 qtestfuncs[i].locals = PRLittleLong (functions[i].locals);
1049                                 for (j = 0; j < MAX_PARMS; j++)
1050                                         qtestfuncs[i].parm_size[j] = PRLittleLong((int)functions[i].parm_size[j]);
1051                         }
1052
1053                         SafeWrite (h, qtestfuncs, numfunctions*sizeof(qtest_function_t));
1054                 }
1055                 break;
1056         case PST_DEFAULT:
1057         case PST_KKQWSV:
1058         case PST_FTE32:
1059                 for (i=0 ; i<numfunctions ; i++)
1060                 {
1061                         functions[i].first_statement = PRLittleLong (functions[i].first_statement);
1062                         functions[i].parm_start = PRLittleLong (functions[i].parm_start);
1063                         functions[i].s_name = PRLittleLong (functions[i].s_name);
1064                         functions[i].s_file = PRLittleLong (functions[i].s_file);
1065                         functions[i].numparms = PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
1066                         functions[i].locals = PRLittleLong (functions[i].locals);
1067                 }
1068
1069                 if (progs.blockscompressed&8)
1070                 {
1071                         SafeWrite (h, &len, sizeof(int));       //save for later
1072                         len = QC_encode(progfuncs, numfunctions*sizeof(QCC_dfunction_t), 2, (char *)functions, h);      //write
1073                         i = SafeSeek (h, 0, SEEK_CUR);
1074                         SafeSeek(h, progs.ofs_functions, SEEK_SET);//seek back
1075                         len = PRLittleLong(len);
1076                         SafeWrite (h, &len, sizeof(int));       //write size.
1077                         SafeSeek(h, i, SEEK_SET);
1078                 }
1079                 else
1080                         SafeWrite (h, functions, numfunctions*sizeof(QCC_dfunction_t));
1081                 break;
1082         default:
1083                 Sys_Error("structtype error");
1084         }
1085
1086         switch(outputsttype)
1087         {
1088         case PST_QTEST:
1089                 // qtest needs a struct remap but should be able to get away with a simple swap here
1090                 for (i=0 ; i<numglobaldefs ; i++)
1091                 {
1092                         qtest_def_t qtdef = ((qtest_def_t *)qcc_globals)[i];
1093                         qcc_globals[i].type = qtdef.type;
1094                         qcc_globals[i].ofs = qtdef.ofs;
1095                         qcc_globals[i].s_name = qtdef.s_name;
1096                 }
1097                 for (i=0 ; i<numfielddefs ; i++)
1098                 {
1099                         qtest_def_t qtdef = ((qtest_def_t *)fields)[i];
1100                         fields[i].type = qtdef.type;
1101                         fields[i].ofs = qtdef.ofs;
1102                         fields[i].s_name = qtdef.s_name;
1103                 }
1104                 // passthrough.. reuse FTE32 code
1105         case PST_FTE32:
1106                 progs.ofs_globaldefs = SafeSeek (h, 0, SEEK_CUR);
1107                 progs.numglobaldefs = numglobaldefs;
1108                 for (i=0 ; i<numglobaldefs ; i++)
1109                 {
1110                         qcc_globals[i].type = PRLittleLong/*PRLittleShort*/ (qcc_globals[i].type);
1111                         qcc_globals[i].ofs = PRLittleLong/*PRLittleShort*/ (qcc_globals[i].ofs);
1112                         qcc_globals[i].s_name = PRLittleLong (qcc_globals[i].s_name);
1113                 }
1114
1115                 if (progs.blockscompressed&2)
1116                 {
1117                         SafeWrite (h, &len, sizeof(int));       //save for later
1118                         len = QC_encode(progfuncs, numglobaldefs*sizeof(QCC_ddef_t), 2, (char *)qcc_globals, h);        //write
1119                         i = SafeSeek (h, 0, SEEK_CUR);
1120                         SafeSeek(h, progs.ofs_globaldefs, SEEK_SET);//seek back
1121                         len = PRLittleLong(len);
1122                         SafeWrite (h, &len, sizeof(int));       //write size.
1123                         SafeSeek(h, i, SEEK_SET);
1124                 }
1125                 else
1126                         SafeWrite (h, qcc_globals, numglobaldefs*sizeof(QCC_ddef_t));
1127
1128                 progs.ofs_fielddefs = SafeSeek (h, 0, SEEK_CUR);
1129                 progs.numfielddefs = numfielddefs;
1130
1131                 for (i=0 ; i<numfielddefs ; i++)
1132                 {
1133                         fields[i].type = PRLittleLong/*PRLittleShort*/ (fields[i].type);
1134                         fields[i].ofs = PRLittleLong/*PRLittleShort*/ (fields[i].ofs);
1135                         fields[i].s_name = PRLittleLong (fields[i].s_name);
1136                 }
1137
1138                 if (progs.blockscompressed&4)
1139                 {
1140                         SafeWrite (h, &len, sizeof(int));       //save for later
1141                         len = QC_encode(progfuncs, numfielddefs*sizeof(QCC_ddef_t), 2, (char *)fields, h);      //write
1142                         i = SafeSeek (h, 0, SEEK_CUR);
1143                         SafeSeek(h, progs.ofs_fielddefs, SEEK_SET);//seek back
1144                         len = PRLittleLong(len);
1145                         SafeWrite (h, &len, sizeof(int));       //write size.
1146                         SafeSeek(h, i, SEEK_SET);
1147                 }
1148                 else
1149                         SafeWrite (h, fields, numfielddefs*sizeof(QCC_ddef_t));
1150                 break;
1151         case PST_KKQWSV:
1152         case PST_DEFAULT:
1153 #define qcc_globals16 ((QCC_ddef16_t*)qcc_globals)
1154 #define fields16 ((QCC_ddef16_t*)fields)
1155                 progs.ofs_globaldefs = SafeSeek (h, 0, SEEK_CUR);
1156                 progs.numglobaldefs = numglobaldefs;
1157                 for (i=0 ; i<numglobaldefs ; i++)
1158                 {
1159                         qcc_globals16[i].type = (unsigned short)PRLittleShort ((unsigned short)qcc_globals[i].type);
1160                         qcc_globals16[i].ofs = (unsigned short)PRLittleShort ((unsigned short)qcc_globals[i].ofs);
1161                         qcc_globals16[i].s_name = PRLittleLong (qcc_globals[i].s_name);
1162                 }
1163
1164                 if (progs.blockscompressed&2)
1165                 {
1166                         SafeWrite (h, &len, sizeof(int));       //save for later
1167                         len = QC_encode(progfuncs, numglobaldefs*sizeof(QCC_ddef16_t), 2, (char *)qcc_globals16, h);    //write
1168                         i = SafeSeek (h, 0, SEEK_CUR);
1169                         SafeSeek(h, progs.ofs_globaldefs, SEEK_SET);//seek back
1170                         len = PRLittleLong(len);
1171                         SafeWrite (h, &len, sizeof(int));       //write size.
1172                         SafeSeek(h, i, SEEK_SET);
1173                 }
1174                 else
1175                         SafeWrite (h, qcc_globals16, numglobaldefs*sizeof(QCC_ddef16_t));
1176
1177                 progs.ofs_fielddefs = SafeSeek (h, 0, SEEK_CUR);
1178                 progs.numfielddefs = numfielddefs;
1179
1180                 for (i=0 ; i<numfielddefs ; i++)
1181                 {
1182                         fields16[i].type = (unsigned short)PRLittleShort ((unsigned short)fields[i].type);
1183                         fields16[i].ofs = (unsigned short)PRLittleShort ((unsigned short)fields[i].ofs);
1184                         fields16[i].s_name = PRLittleLong (fields[i].s_name);
1185                 }
1186
1187                 if (progs.blockscompressed&4)
1188                 {
1189                         SafeWrite (h, &len, sizeof(int));       //save for later
1190                         len = QC_encode(progfuncs, numfielddefs*sizeof(QCC_ddef16_t), 2, (char *)fields16, h);  //write
1191                         i = SafeSeek (h, 0, SEEK_CUR);
1192                         SafeSeek(h, progs.ofs_fielddefs, SEEK_SET);//seek back
1193                         len = PRLittleLong(len);
1194                         SafeWrite (h, &len, sizeof(int));       //write size.
1195                         SafeSeek(h, i, SEEK_SET);
1196                 }
1197                 else
1198                         SafeWrite (h, fields16, numfielddefs*sizeof(QCC_ddef16_t));
1199                 break;
1200         default:
1201                 Sys_Error("structtype error");
1202         }
1203
1204         progs.ofs_globals = SafeSeek (h, 0, SEEK_CUR);
1205         progs.numglobals = numpr_globals;
1206
1207         for (i=0 ; (unsigned)i<numpr_globals ; i++)
1208                 ((int *)qcc_pr_globals)[i] = PRLittleLong (((int *)qcc_pr_globals)[i]);
1209
1210         if (progs.blockscompressed&32)
1211         {
1212                 SafeWrite (h, &len, sizeof(int));       //save for later
1213                 len = QC_encode(progfuncs, numpr_globals*4, 2, (char *)qcc_pr_globals, h);      //write
1214                 i = SafeSeek (h, 0, SEEK_CUR);
1215                 SafeSeek(h, progs.ofs_globals, SEEK_SET);//seek back
1216                 len = PRLittleLong(len);
1217                 SafeWrite (h, &len, sizeof(int));       //write size.
1218                 SafeSeek(h, i, SEEK_SET);
1219         }
1220         else
1221                 SafeWrite (h, qcc_pr_globals, numpr_globals*4);
1222
1223         if (types)
1224         for (i=0 ; i<numtypeinfos ; i++)
1225         {
1226                 if (qcc_typeinfo[i].aux_type)
1227                         qcc_typeinfo[i].aux_type = (QCC_type_t*)(qcc_typeinfo[i].aux_type - qcc_typeinfo);
1228                 if (qcc_typeinfo[i].next)
1229                         qcc_typeinfo[i].next = (QCC_type_t*)(qcc_typeinfo[i].next - qcc_typeinfo);
1230                 qcc_typeinfo[i].name = (char*)QCC_CopyDupBackString(qcc_typeinfo[i].name);
1231         }
1232
1233         progs.ofsfiles = 0;
1234         progs.ofslinenums = 0;
1235         progs.secondaryversion = 0;
1236         progs.ofsbodylessfuncs = 0;
1237         progs.numbodylessfuncs = 0;
1238         progs.ofs_types = 0;
1239         progs.numtypes = 0;
1240
1241         switch(qcc_targetformat)
1242         {
1243         case QCF_QTEST:
1244                 progs.version = PROG_QTESTVERSION;
1245                 break;
1246         case QCF_KK7:
1247                 progs.version = PROG_KKQWSVVERSION;
1248                 break;
1249         case QCF_STANDARD:
1250         case QCF_HEXEN2:        //urgh
1251                 progs.version = PROG_VERSION;
1252                 break;
1253         case QCF_DARKPLACES:
1254         case QCF_FTE:
1255         case QCF_FTEDEBUG:
1256                 progs.version = PROG_EXTENDEDVERSION;
1257
1258                 if (outputsttype == PST_FTE32)
1259                         progs.secondaryversion = PROG_SECONDARYVERSION32;
1260                 else
1261                         progs.secondaryversion = PROG_SECONDARYVERSION16;
1262
1263                 progs.ofsbodylessfuncs = SafeSeek (h, 0, SEEK_CUR);
1264                 progs.numbodylessfuncs = WriteBodylessFuncs(h);
1265
1266                 if (debugtarget)
1267                 {
1268                         progs.ofslinenums = SafeSeek (h, 0, SEEK_CUR);
1269                         if (progs.blockscompressed&64)
1270                         {
1271                                 SafeWrite (h, &len, sizeof(int));       //save for later
1272                                 len = QC_encode(progfuncs, numstatements*sizeof(int), 2, (char *)statement_linenums, h);        //write
1273                                 i = SafeSeek (h, 0, SEEK_CUR);
1274                                 SafeSeek(h, progs.ofslinenums, SEEK_SET);//seek back
1275                                 len = PRLittleLong(len);
1276                                 SafeWrite (h, &len, sizeof(int));       //write size.
1277                                 SafeSeek(h, i, SEEK_SET);
1278                         }
1279                         else
1280                                 SafeWrite (h, statement_linenums, numstatements*sizeof(int));
1281                 }
1282                 else
1283                         progs.ofslinenums = 0;
1284
1285                 if (types)
1286                 {
1287                         progs.ofs_types = SafeSeek (h, 0, SEEK_CUR);
1288                         if (progs.blockscompressed&128)
1289                         {
1290                                 SafeWrite (h, &len, sizeof(int));       //save for later
1291                                 len = QC_encode(progfuncs, sizeof(QCC_type_t)*numtypeinfos, 2, (char *)qcc_typeinfo, h);        //write
1292                                 i = SafeSeek (h, 0, SEEK_CUR);
1293                                 SafeSeek(h, progs.ofs_types, SEEK_SET);//seek back#
1294                                 len = PRLittleLong(len);
1295                                 SafeWrite (h, &len, sizeof(int));       //write size.
1296                                 SafeSeek(h, i, SEEK_SET);
1297                         }
1298                         else
1299                                 SafeWrite (h, qcc_typeinfo, sizeof(QCC_type_t)*numtypeinfos);
1300                         progs.numtypes = numtypeinfos;
1301                 }
1302                 else
1303                 {
1304                         progs.ofs_types = 0;
1305                         progs.numtypes = 0;
1306                 }
1307
1308                 progs.ofsfiles = WriteSourceFiles(h, &progs, debugtarget);
1309                 break;
1310         }
1311
1312         if (verbose)
1313                 printf ("%6i TOTAL SIZE\n", (int)SafeSeek (h, 0, SEEK_CUR));
1314
1315         progs.entityfields = pr.size_fields;
1316
1317         progs.crc = crc;
1318
1319 // qbyte swap the header and write it out
1320
1321         for (i=0 ; i<sizeof(progs)/4 ; i++)
1322                 ((int *)&progs)[i] = PRLittleLong ( ((int *)&progs)[i] );
1323
1324
1325         SafeSeek (h, 0, SEEK_SET);
1326         SafeWrite (h, &progs, sizeof(progs));
1327         SafeClose (h);
1328
1329         if (!debugtarget)
1330         {
1331                 if (opt_filenames)
1332                 {
1333                         printf("Not writing linenumbers file due to conflicting optimisation\n");
1334                 }
1335                 else
1336                 {
1337                         unsigned int lnotype = *(unsigned int*)"LNOF";
1338                         unsigned int version = 1;
1339                         StripExtension(destfile);
1340                         strcat(destfile, ".lno");
1341                         if (verbose)
1342                                 printf("Writing %s for debugging\n", destfile);
1343                         h = SafeOpenWrite (destfile, 2*1024*1024);
1344                         SafeWrite (h, &lnotype, sizeof(int));
1345                         SafeWrite (h, &version, sizeof(int));
1346                         SafeWrite (h, &numglobaldefs, sizeof(int));
1347                         SafeWrite (h, &numpr_globals, sizeof(int));
1348                         SafeWrite (h, &numfielddefs, sizeof(int));
1349                         SafeWrite (h, &numstatements, sizeof(int));
1350                         SafeWrite (h, statement_linenums, numstatements*sizeof(int));
1351                         SafeClose (h);
1352                 }
1353         }
1354
1355         return true;
1356 }
1357
1358
1359
1360 /*
1361 ===============
1362 PR_String
1363
1364 Returns a string suitable for printing (no newlines, max 60 chars length)
1365 ===============
1366 */
1367 char *QCC_PR_String (char *string)
1368 {
1369         static char buf[80];
1370         char    *s;
1371
1372         s = buf;
1373         *s++ = '"';
1374         while (string && *string)
1375         {
1376                 if (s == buf + sizeof(buf) - 2)
1377                         break;
1378                 if (*string == '\n')
1379                 {
1380                         *s++ = '\\';
1381                         *s++ = 'n';
1382                 }
1383                 else if (*string == '"')
1384                 {
1385                         *s++ = '\\';
1386                         *s++ = '"';
1387                 }
1388                 else
1389                         *s++ = *string;
1390                 string++;
1391                 if (s - buf > 60)
1392                 {
1393                         *s++ = '.';
1394                         *s++ = '.';
1395                         *s++ = '.';
1396                         break;
1397                 }
1398         }
1399         *s++ = '"';
1400         *s++ = 0;
1401         return buf;
1402 }
1403
1404
1405
1406 QCC_def_t       *QCC_PR_DefForFieldOfs (gofs_t ofs)
1407 {
1408         QCC_def_t       *d;
1409
1410         for (d=pr.def_head.next ; d ; d=d->next)
1411         {
1412                 if (d->type->type != ev_field)
1413                         continue;
1414                 if (*((unsigned int *)&qcc_pr_globals[d->ofs]) == ofs)
1415                         return d;
1416         }
1417         QCC_Error (ERR_NOTDEFINED, "PR_DefForFieldOfs: couldn't find %i",ofs);
1418         return NULL;
1419 }
1420
1421 /*
1422 ============
1423 PR_ValueString
1424
1425 Returns a string describing *data in a type specific manner
1426 =============
1427 */
1428 char *QCC_PR_ValueString (etype_t type, void *val)
1429 {
1430         static char     line[256];
1431         QCC_def_t               *def;
1432         QCC_dfunction_t *f;
1433
1434         switch (type)
1435         {
1436         case ev_string:
1437                 sprintf (line, "%s", QCC_PR_String(strings + *(int *)val));
1438                 break;
1439         case ev_entity:
1440                 sprintf (line, "entity %i", *(int *)val);
1441                 break;
1442         case ev_function:
1443                 f = functions + *(int *)val;
1444                 if (!f)
1445                         sprintf (line, "undefined function");
1446                 else
1447                         sprintf (line, "%s()", strings + f->s_name);
1448                 break;
1449         case ev_field:
1450                 def = QCC_PR_DefForFieldOfs ( *(int *)val );
1451                 sprintf (line, ".%s", def->name);
1452                 break;
1453         case ev_void:
1454                 sprintf (line, "void");
1455                 break;
1456         case ev_float:
1457                 sprintf (line, "%5.1f", *(float *)val);
1458                 break;
1459         case ev_integer:
1460                 sprintf (line, "%i", *(int *)val);
1461                 break;
1462         case ev_vector:
1463                 sprintf (line, "'%5.1f %5.1f %5.1f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
1464                 break;
1465         case ev_pointer:
1466                 sprintf (line, "pointer");
1467                 break;
1468         default:
1469                 sprintf (line, "bad type %i", type);
1470                 break;
1471         }
1472
1473         return line;
1474 }
1475
1476 /*
1477 ============
1478 PR_GlobalString
1479
1480 Returns a string with a description and the contents of a global,
1481 padded to 20 field width
1482 ============
1483 */
1484 /*char *QCC_PR_GlobalStringNoContents (gofs_t ofs)
1485 {
1486         int             i;
1487         QCC_def_t       *def;
1488         void    *val;
1489         static char     line[128];
1490
1491         val = (void *)&qcc_pr_globals[ofs];
1492         def = pr_global_defs[ofs];
1493         if (!def)
1494 //              Error ("PR_GlobalString: no def for %i", ofs);
1495                 sprintf (line,"%i(?""?""?)", ofs);
1496         else
1497                 sprintf (line,"%i(%s)", ofs, def->name);
1498
1499         i = strlen(line);
1500         for ( ; i<16 ; i++)
1501                 strcat (line," ");
1502         strcat (line," ");
1503
1504         return line;
1505 }
1506
1507 char *QCC_PR_GlobalString (gofs_t ofs)
1508 {
1509         char    *s;
1510         int             i;
1511         QCC_def_t       *def;
1512         void    *val;
1513         static char     line[128];
1514
1515         val = (void *)&qcc_pr_globals[ofs];
1516         def = pr_global_defs[ofs];
1517         if (!def)
1518                 return QCC_PR_GlobalStringNoContents(ofs);
1519         if (def->initialized && def->type->type != ev_function)
1520         {
1521                 s = QCC_PR_ValueString (def->type->type, &qcc_pr_globals[ofs]);
1522                 sprintf (line,"%i(%s)", ofs, s);
1523         }
1524         else
1525                 sprintf (line,"%i(%s)", ofs, def->name);
1526
1527         i = strlen(line);
1528         for ( ; i<16 ; i++)
1529                 strcat (line," ");
1530         strcat (line," ");
1531
1532         return line;
1533 }*/
1534
1535 /*
1536 ============
1537 PR_PrintOfs
1538 ============
1539 */
1540 /*void QCC_PR_PrintOfs (gofs_t ofs)
1541 {
1542         printf ("%s\n",QCC_PR_GlobalString(ofs));
1543 }*/
1544
1545 /*
1546 =================
1547 PR_PrintStatement
1548 =================
1549 */
1550 /*void QCC_PR_PrintStatement (QCC_dstatement_t *s)
1551 {
1552         int             i;
1553
1554         printf ("%4i : %4i : %s ", (int)(s - statements), statement_linenums[s-statements], pr_opcodes[s->op].opname);
1555         i = strlen(pr_opcodes[s->op].opname);
1556         for ( ; i<10 ; i++)
1557                 printf (" ");
1558
1559         if (s->op == OP_IF || s->op == OP_IFNOT)
1560                 printf ("%sbranch %i",QCC_PR_GlobalString(s->a),s->b);
1561         else if (s->op == OP_GOTO)
1562         {
1563                 printf ("branch %i",s->a);
1564         }
1565         else if ( (unsigned)(s->op - OP_STORE_F) < 6)
1566         {
1567                 printf ("%s",QCC_PR_GlobalString(s->a));
1568                 printf ("%s", QCC_PR_GlobalStringNoContents(s->b));
1569         }
1570         else
1571         {
1572                 if (s->a)
1573                         printf ("%s",QCC_PR_GlobalString(s->a));
1574                 if (s->b)
1575                         printf ("%s",QCC_PR_GlobalString(s->b));
1576                 if (s->c)
1577                         printf ("%s", QCC_PR_GlobalStringNoContents(s->c));
1578         }
1579         printf ("\n");
1580 }*/
1581
1582
1583 /*
1584 ============
1585 PR_PrintDefs
1586 ============
1587 */
1588 /*void QCC_PR_PrintDefs (void)
1589 {
1590         QCC_def_t       *d;
1591
1592         for (d=pr.def_head.next ; d ; d=d->next)
1593                 QCC_PR_PrintOfs (d->ofs);
1594 }*/
1595
1596 QCC_type_t *QCC_PR_NewType (char *name, int basictype)
1597 {
1598         if (numtypeinfos>= maxtypeinfos)
1599                 QCC_Error(ERR_TOOMANYTYPES, "Too many types");
1600         memset(&qcc_typeinfo[numtypeinfos], 0, sizeof(QCC_type_t));
1601         qcc_typeinfo[numtypeinfos].type = basictype;
1602         qcc_typeinfo[numtypeinfos].name = name;
1603         qcc_typeinfo[numtypeinfos].num_parms = 0;
1604         qcc_typeinfo[numtypeinfos].param = NULL;
1605         qcc_typeinfo[numtypeinfos].size = type_size[basictype];
1606
1607
1608         numtypeinfos++;
1609
1610         return &qcc_typeinfo[numtypeinfos-1];
1611 }
1612
1613 /*
1614 ==============
1615 PR_BeginCompilation
1616
1617 called before compiling a batch of files, clears the pr struct
1618 ==============
1619 */
1620 void    QCC_PR_BeginCompilation (void *memory, int memsize)
1621 {
1622         extern int recursivefunctiontype;
1623         extern struct freeoffset_s *freeofs;
1624         int             i;
1625         char name[16];
1626
1627         pr.memory = memory;
1628         pr.max_memory = memsize;
1629
1630         pr.def_tail = &pr.def_head;
1631
1632         QCC_PR_ResetErrorScope();
1633         pr_scope = NULL;
1634
1635 /*      numpr_globals = RESERVED_OFS;
1636
1637         for (i=0 ; i<RESERVED_OFS ; i++)
1638                 pr_global_defs[i] = &def_void;
1639 */
1640
1641         type_void = QCC_PR_NewType("void", ev_void);
1642         type_string = QCC_PR_NewType("string", ev_string);
1643         type_float = QCC_PR_NewType("float", ev_float);
1644         type_vector = QCC_PR_NewType("vector", ev_vector);
1645         type_entity = QCC_PR_NewType("entity", ev_entity);
1646         type_field = QCC_PR_NewType("field", ev_field);
1647         type_function = QCC_PR_NewType("function", ev_function);
1648         type_pointer = QCC_PR_NewType("pointer", ev_pointer);
1649         type_integer = QCC_PR_NewType("__integer", ev_integer);
1650         type_variant = QCC_PR_NewType("__variant", ev_variant);
1651
1652         type_floatfield = QCC_PR_NewType("fieldfloat", ev_field);
1653         type_floatfield->aux_type = type_float;
1654         type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float);
1655
1656         type_function->aux_type = type_void;
1657
1658         //type_field->aux_type = type_float;
1659
1660         if (keyword_integer)
1661                 type_integer = QCC_PR_NewType("integer", ev_integer);
1662         if (keyword_int)
1663                 type_integer = QCC_PR_NewType("int", ev_integer);
1664
1665
1666
1667         if (output_parms)
1668         {       //this tends to confuse the brains out of decompilers. :)
1669                 numpr_globals = 1;
1670                 QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 1, false)->references++;
1671                 for (i = 0; i < MAX_PARMS; i++)
1672                 {
1673                         sprintf(name, "PARM%i", i);
1674                         QCC_PR_GetDef(type_vector, name, NULL, true, 1, false)->references++;
1675                 }
1676         }
1677         else
1678         {
1679                 numpr_globals = RESERVED_OFS;
1680 //              for (i=0 ; i<RESERVED_OFS ; i++)
1681 //                      pr_global_defs[i] = NULL;
1682         }
1683
1684 // link the function type in so state forward declarations match proper type
1685         pr.types = NULL;
1686 //      type_function->next = NULL;
1687         pr_error_count = 0;
1688         pr_warning_count = 0;
1689         recursivefunctiontype = 0;
1690
1691         freeofs = NULL;
1692 }
1693
1694 /*
1695 ==============
1696 PR_FinishCompilation
1697
1698 called after all files are compiled to check for errors
1699 Returns false if errors were detected.
1700 ==============
1701 */
1702 int QCC_PR_FinishCompilation (void)
1703 {
1704         QCC_def_t               *d;
1705         int     errors;
1706
1707         errors = false;
1708
1709 // check to make sure all functions prototyped have code
1710         for (d=pr.def_head.next ; d ; d=d->next)
1711         {
1712                 if (d->type->type == ev_function && !d->scope)// function parms are ok
1713                 {
1714 //                      f = G_FUNCTION(d->ofs);
1715 //                      if (!f || (!f->code && !f->builtin) )
1716                         if (d->initialized==0)
1717                         {
1718                                 s_file = d->s_file;
1719                                 if (!strncmp(d->name, "ArrayGet*", 9))
1720                                 {
1721                                         QCC_PR_EmitArrayGetFunction(d, d->name+9);
1722                                         pr_scope = NULL;
1723                                 }
1724                                 else if (!strncmp(d->name, "ArraySet*", 9))
1725                                 {
1726                                         QCC_PR_EmitArraySetFunction(d, d->name+9);
1727                                         pr_scope = NULL;
1728                                 }
1729                                 else if (!strncmp(d->name, "Class*", 6))
1730                                 {
1731                                         QCC_PR_EmitClassFromFunction(d, d->name+6);
1732                                         pr_scope = NULL;
1733                                 }
1734                                 else
1735                                 {
1736                                         QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, d, "function %s was not defined",d->name);
1737                                         bodylessfuncs = true;
1738                                         errors = true;
1739                                 }
1740                                 s_file = NULL;
1741 //                              errors = true;
1742                         }
1743                         else if (d->initialized==2)
1744                                 bodylessfuncs = true;
1745                 }
1746         }
1747         pr_scope = NULL;
1748
1749         return !errors;
1750 }
1751
1752 //=============================================================================
1753
1754 // FIXME: byte swap?
1755
1756 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1757 // and the initial and final xor values shown below...  in other words, the
1758 // CCITT standard CRC used by XMODEM
1759
1760
1761 #define CRC_INIT_VALUE  0xffff
1762 #define CRC_XOR_VALUE   0x0000
1763
1764 static unsigned short QCC_crctable[256] =
1765 {
1766         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1767         0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1768         0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1769         0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1770         0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1771         0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1772         0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1773         0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1774         0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1775         0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1776         0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1777         0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1778         0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1779         0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1780         0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1781         0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1782         0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1783         0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1784         0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1785         0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1786         0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1787         0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1788         0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1789         0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1790         0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1791         0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1792         0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1793         0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1794         0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1795         0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1796         0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1797         0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1798 };
1799
1800 void QCC_CRC_Init(unsigned short *crcvalue)
1801 {
1802         *crcvalue = CRC_INIT_VALUE;
1803 }
1804
1805 void QCC_CRC_ProcessByte(unsigned short *crcvalue, qbyte data)
1806 {
1807         *crcvalue = (*crcvalue << 8) ^ QCC_crctable[(*crcvalue >> 8) ^ data];
1808 }
1809
1810 unsigned short QCC_CRC_Value(unsigned short crcvalue)
1811 {
1812         return crcvalue ^ CRC_XOR_VALUE;
1813 }
1814 //=============================================================================
1815
1816
1817 /*
1818 ============
1819 PR_WriteProgdefs
1820
1821 Writes the global and entity structures out
1822 Returns a crc of the header, to be stored in the progs file for comparison
1823 at load time.
1824 ============
1825 */
1826 /*
1827 char *Sva(char *msg, ...)
1828 {
1829         va_list l;
1830         static char buf[1024];
1831
1832         va_start(l, msg);
1833         QC_vsnprintf (buf,sizeof(buf)-1, msg, l);
1834         va_end(l);
1835
1836         return buf;
1837 }
1838 */
1839
1840 #define PROGDEFS_MAX_SIZE 16384
1841 //write (to file buf) and add to the crc
1842 static void Add(char *p, unsigned short *crc, char *file)
1843 {
1844         char *s;
1845         int i = strlen(file);
1846         if (i + strlen(p)+1 >= PROGDEFS_MAX_SIZE)
1847                 return;
1848         for(s=p;*s;s++,i++)
1849         {
1850                 QCC_CRC_ProcessByte(crc, *s);
1851                 file[i] = *s;
1852         }
1853         file[i]='\0';
1854 }
1855 #define ADD(p) Add(p, &crc, file)
1856 //#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';}
1857
1858 static void Add3(char *p, unsigned short *crc, char *file)
1859 {
1860         char *s;
1861         for(s=p;*s;s++)
1862                 QCC_CRC_ProcessByte(crc, *s);
1863 }
1864 #define ADD3(p) Add3(p, &crc, file)
1865
1866 unsigned short QCC_PR_WriteProgdefs (char *filename)
1867 {
1868 #define ADD2(p) strncat(file, p, PROGDEFS_MAX_SIZE-1 - strlen(file))    //no crc (later changes)
1869         char file[PROGDEFS_MAX_SIZE];
1870         QCC_def_t       *d;
1871         int     f;
1872         unsigned short          crc;
1873 //      int             c;
1874
1875         file[0] = '\0';
1876
1877         QCC_CRC_Init (&crc);
1878
1879 // print global vars until the first field is defined
1880
1881         //ADD: crc and dump
1882         //ADD2: dump but don't crc
1883         //ADD3: crc but don't dump
1884
1885         ADD("\n/* ");
1886         if (qcc_targetformat == QCF_HEXEN2)
1887                 ADD3("generated by hcc, do not modify");
1888         else
1889                 ADD3("file generated by qcc, do not modify");
1890         ADD2("File generated by FTEQCC, relevent for engine modding only, the generated crc must be the same as your engine expects.");
1891         ADD(" */\n\ntypedef struct");
1892         ADD2(" globalvars_s");
1893         ADD(qcva("\n{"));
1894         ADD2("\tint pad;\n"
1895                 "\tint ofs_return[3];\n"        //makes it easier with the get globals func
1896                 "\tint ofs_parm0[3];\n"
1897                 "\tint ofs_parm1[3];\n"
1898                 "\tint ofs_parm2[3];\n"
1899                 "\tint ofs_parm3[3];\n"
1900                 "\tint ofs_parm4[3];\n"
1901                 "\tint ofs_parm5[3];\n"
1902                 "\tint ofs_parm6[3];\n"
1903                 "\tint ofs_parm7[3];\n");
1904         ADD3(qcva("\tint\tpad[%i];\n", RESERVED_OFS));
1905         for (d=pr.def_head.next ; d ; d=d->next)
1906         {
1907                 if (!strcmp (d->name, "end_sys_globals"))
1908                         break;
1909                 if (d->ofs<RESERVED_OFS)
1910                         continue;
1911
1912                 switch (d->type->type)
1913                 {
1914                 case ev_float:
1915                         ADD(qcva("\tfloat\t%s;\n",d->name));
1916                         break;
1917                 case ev_vector:
1918                         ADD(qcva("\tvec3_t\t%s;\n",d->name));
1919                         d=d->next->next->next;  // skip the elements
1920                         break;
1921                 case ev_string:
1922                         ADD(qcva("\tstring_t\t%s;\n",d->name));
1923                         break;
1924                 case ev_function:
1925                         ADD(qcva("\tfunc_t\t%s;\n",d->name));
1926                         break;
1927                 case ev_entity:
1928                         ADD(qcva("\tint\t%s;\n",d->name));
1929                         break;
1930                 case ev_integer:
1931                         ADD(qcva("\tint\t%s;\n",d->name));
1932                         break;
1933                 default:
1934                         ADD(qcva("\tint\t%s;\n",d->name));
1935                         break;
1936                 }
1937         }
1938         ADD("} globalvars_t;\n\n");
1939
1940 // print all fields
1941         ADD("typedef struct");
1942         ADD2(" entvars_s");
1943         ADD("\n{\n");
1944         for (d=pr.def_head.next ; d ; d=d->next)
1945         {
1946                 if (!strcmp (d->name, "end_sys_fields"))
1947                         break;
1948
1949                 if (d->type->type != ev_field)
1950                         continue;
1951
1952                 switch (d->type->aux_type->type)
1953                 {
1954                 case ev_float:
1955                         ADD(qcva("\tfloat\t%s;\n",d->name));
1956                         break;
1957                 case ev_vector:
1958                         ADD(qcva("\tvec3_t\t%s;\n",d->name));
1959                         d=d->next->next->next;  // skip the elements
1960                         break;
1961                 case ev_string:
1962                         ADD(qcva("\tstring_t\t%s;\n",d->name));
1963                         break;
1964                 case ev_function:
1965                         ADD(qcva("\tfunc_t\t%s;\n",d->name));
1966                         break;
1967                 case ev_entity:
1968                         ADD(qcva("\tint\t%s;\n",d->name));
1969                         break;
1970                 case ev_integer:
1971                         ADD(qcva("\tint\t%s;\n",d->name));
1972                         break;
1973                 default:
1974                         ADD(qcva("\tint\t%s;\n",d->name));
1975                         break;
1976                 }
1977         }
1978         ADD("} entvars_t;\n\n");
1979
1980         ///temp
1981         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");
1982         f=0;
1983         for (d=pr.def_head.next ; d ; d=d->next)
1984         {
1985                 if (!strcmp (d->name, "end_sys_fields"))
1986                         break;
1987
1988                 if (d->type->type != ev_field)
1989                         continue;
1990                 if (f)
1991                         ADD2(",\n");
1992                 ADD2(qcva("\t{%i,\t%i,\t\"%s\"}",G_INT(d->ofs), d->type->aux_type->type, d->name));
1993                 f = 1;
1994         }
1995         ADD2("\n};\n#endif\n\n");
1996         //end temp
1997
1998         ADD2(qcva("#define PROGHEADER_CRC %i\n", crc));
1999
2000         if (QCC_CheckParm("-progdefs"))
2001         {
2002                 printf ("writing %s\n", filename);
2003                 f = SafeOpenWrite(filename, 16384);
2004                 SafeWrite(f, file, strlen(file));
2005                 SafeClose(f);
2006         }
2007
2008
2009         if (ForcedCRC)
2010                 crc = ForcedCRC;
2011
2012         switch (crc)
2013         {
2014         case 12923:     //#pragma sourcefile usage
2015                 break;
2016         case 54730:
2017                 if (verbose)
2018                         printf("Recognised progs as QuakeWorld\n");
2019                 break;
2020         case 5927:
2021                 if (verbose)
2022                         printf("Recognised progs as NetQuake server gamecode\n");
2023                 break;
2024
2025         case 26940:
2026                 if (verbose)
2027                         printf("Recognised progs as Quake pre-release...\n");
2028                 break;
2029
2030         case 38488:
2031                 if (verbose)
2032                         printf("Recognised progs as original Hexen2\n");
2033                 break;
2034         case 26905:
2035                 if (verbose)
2036                         printf("Recognised progs as Hexen2 Mission Pack\n");
2037                 break;
2038         case 14046:
2039                 if (verbose)
2040                         printf("Recognised progs as Hexen2 (demo)\n");
2041                 break;
2042
2043         case 22390: //EXT_CSQC_1
2044                 if (verbose)
2045                         printf("Recognised progs as an EXT_CSQC_1 module\n");
2046                 break;
2047         case 17105:
2048         case 32199:     //outdated ext_csqc
2049                 printf("Recognised progs as outdated CSQC module\n");
2050                 break;
2051         case 52195:
2052                 printf("Recognised progs as outdated CSQC module\n");
2053                 break;
2054         case 10020:
2055                 if (verbose)
2056                         printf("Recognised progs as a DP/FTE Menu module\n");
2057                 break;
2058
2059         case 32401:
2060                 printf("Warning: please update your tenebrae system defs.\n");
2061                 break;
2062         default:
2063                 printf("Warning: progs CRC not recognised from quake nor clones\n");
2064                 break;
2065         }
2066
2067
2068         return crc;
2069 }
2070
2071
2072 /*void QCC_PrintFunction (char *name)
2073 {
2074         int             i;
2075         QCC_dstatement_t        *ds;
2076         QCC_dfunction_t         *df;
2077
2078         for (i=0 ; i<numfunctions ; i++)
2079                 if (!strcmp (name, strings + functions[i].s_name))
2080                         break;
2081         if (i==numfunctions)
2082                 QCC_Error (ERR_NOFUNC, "No function named \"%s\"", name);
2083         df = functions + i;
2084
2085         printf ("Statements for function %s:\n", name);
2086         ds = statements + df->first_statement;
2087         while (1)
2088         {
2089                 QCC_PR_PrintStatement (ds);
2090                 if (!ds->op)
2091                         break;
2092                 ds++;
2093         }
2094 }*/
2095 /*
2096 void QCC_PrintOfs(unsigned int ofs)
2097 {
2098         int i;
2099         bool printfunc;
2100         QCC_dstatement_t        *ds;
2101         QCC_dfunction_t         *df;
2102
2103         for (i=0 ; i<numfunctions ; i++)
2104         {
2105                 df = functions + i;
2106                 ds = statements + df->first_statement;
2107                 printfunc = false;
2108                 while (1)
2109                 {
2110                         if (!ds->op)
2111                                 break;
2112                         if (ds->a == ofs || ds->b == ofs || ds->c == ofs)
2113                         {
2114                                 QCC_PR_PrintStatement (ds);
2115                                 printfunc = true;
2116                         }
2117                         ds++;
2118                 }
2119                 if (printfunc)
2120                 {
2121                         QCC_PrintFunction(strings + functions[i].s_name);
2122                         printf(" \n \n");
2123                 }
2124         }
2125
2126 }
2127 */
2128 /*
2129 ==============================================================================
2130
2131 DIRECTORY COPYING / PACKFILE CREATION
2132
2133 ==============================================================================
2134 */
2135
2136 typedef struct
2137 {
2138         char    name[56];
2139         int             filepos, filelen;
2140 } packfile_t;
2141
2142 typedef struct
2143 {
2144         char    id[4];
2145         int             dirofs;
2146         int             dirlen;
2147 } packheader_t;
2148
2149 packfile_t      pfiles[4096], *pf;
2150 int                     packhandle;
2151 int                     packbytes;
2152
2153
2154 /*
2155 ============
2156 CreatePath
2157 ============
2158 */
2159 void    QCC_CreatePath (char *path)
2160 {
2161         /*
2162         char    *ofs;
2163
2164         for (ofs = path+1 ; *ofs ; ofs++)
2165         {
2166                 if (*ofs == '/')
2167                 {       // create the directory
2168                         *ofs = 0;
2169 #ifdef QCC
2170                         mkdir(path);
2171 #else
2172                         QCC_mkdir (path);
2173 #endif
2174                         *ofs = '/';
2175                 }
2176         }
2177         */
2178 }
2179
2180
2181 /*
2182 ===========
2183 PackFile
2184
2185 Copy a file into the pak file
2186 ===========
2187 */
2188 void QCC_PackFile (char *src, char *name)
2189 {
2190         int             remaining;
2191 #if 1
2192         char    *f;
2193 #else
2194         int             in;
2195         int             count;
2196         char    buf[4096];
2197 #endif
2198
2199
2200         if ( (qbyte *)pf - (qbyte *)pfiles > sizeof(pfiles) )
2201                 QCC_Error (ERR_TOOMANYPAKFILES, "Too many files in pak file");
2202
2203 #if 1
2204         f = FS_ReadToMem(src, NULL, &remaining);
2205         if (!f)
2206         {
2207                 printf ("%64s : %7s\n", name, "");
2208 //              QCC_Error("Failed to open file %s", src);
2209                 return;
2210         }
2211
2212         pf->filepos = PRLittleLong (SafeSeek (packhandle, 0, SEEK_CUR));
2213         pf->filelen = PRLittleLong (remaining);
2214         strcpy (pf->name, name);
2215         printf ("%64s : %7i\n", pf->name, remaining);
2216
2217         packbytes += remaining;
2218
2219         SafeWrite (packhandle, f, remaining);
2220
2221         FS_CloseFromMem(f);
2222 #else
2223         in = SafeOpenRead (src);
2224         remaining = filelength (in);
2225
2226         pf->filepos = PRLittleLong (lseek (packhandle, 0, SEEK_CUR));
2227         pf->filelen = PRLittleLong (remaining);
2228         strcpy (pf->name, name);
2229         printf ("%64s : %7i\n", pf->name, remaining);
2230
2231         packbytes += remaining;
2232
2233         while (remaining)
2234         {
2235                 if (remaining < sizeof(buf))
2236                         count = remaining;
2237                 else
2238                         count = sizeof(buf);
2239                 SafeRead (in, buf, count);
2240                 SafeWrite (packhandle, buf, count);
2241                 remaining -= count;
2242         }
2243
2244         close (in);
2245 #endif
2246         pf++;
2247 }
2248
2249
2250 /*
2251 ===========
2252 CopyFile
2253
2254 Copies a file, creating any directories needed
2255 ===========
2256 */
2257 void QCC_CopyFile (char *src, char *dest)
2258 {
2259         /*
2260         int             in, out;
2261         int             remaining, count;
2262         char    buf[4096];
2263
2264         print ("%s to %s\n", src, dest);
2265
2266         in = SafeOpenRead (src);
2267         remaining = filelength (in);
2268
2269         QCC_CreatePath (dest);
2270         out = SafeOpenWrite (dest, remaining+10);
2271
2272         while (remaining)
2273         {
2274                 if (remaining < sizeof(buf))
2275                         count = remaining;
2276                 else
2277                         count = sizeof(buf);
2278                 SafeRead (in, buf, count);
2279                 SafeWrite (out, buf, count);
2280                 remaining -= count;
2281         }
2282
2283         close (in);
2284         SafeClose (out);
2285         */
2286 }
2287
2288
2289 /*
2290 ===========
2291 CopyFiles
2292 ===========
2293 */
2294
2295 void _QCC_CopyFiles (int blocknum, int copytype, char *srcdir, char *destdir)
2296 {
2297         int i;
2298         int             dirlen;
2299         unsigned short          crc;
2300         packheader_t    header;
2301         char    name[1024];
2302         char    srcfile[1024], destfile[1024];
2303
2304         packbytes = 0;
2305
2306         if (copytype == 2)
2307         {
2308                 pf = pfiles;
2309                 packhandle = SafeOpenWrite (destdir, 1024*1024);
2310                 SafeWrite (packhandle, &header, sizeof(header));
2311         }
2312
2313         for (i=0 ; i<numsounds ; i++)
2314         {
2315                 if (precache_sounds_block[i] != blocknum)
2316                         continue;
2317                 sprintf (srcfile,"%s%s",srcdir, precache_sounds[i]);
2318                 sprintf (destfile,"%s%s",destdir, precache_sounds[i]);
2319                 if (copytype == 1)
2320                         QCC_CopyFile (srcfile, destfile);
2321                 else
2322                         QCC_PackFile (srcfile, precache_sounds[i]);
2323         }
2324         for (i=0 ; i<nummodels ; i++)
2325         {
2326                 if (precache_models_block[i] != blocknum)
2327                         continue;
2328                 sprintf (srcfile,"%s%s",srcdir, precache_models[i]);
2329                 sprintf (destfile,"%s%s",destdir, precache_models[i]);
2330                 if (copytype == 1)
2331                         QCC_CopyFile (srcfile, destfile);
2332                 else
2333                         QCC_PackFile (srcfile, precache_models[i]);
2334         }
2335         for (i=0 ; i<numtextures ; i++)
2336         {
2337                 if (precache_textures_block[i] != blocknum)
2338                         continue;
2339
2340                 {
2341                         sprintf (name, "%s", precache_textures[i]);
2342                         sprintf (srcfile,"%s%s",srcdir, name);
2343                         sprintf (destfile,"%s%s",destdir, name);
2344                         if (copytype == 1)
2345                                 QCC_CopyFile (srcfile, destfile);
2346                         else
2347                                 QCC_PackFile (srcfile, name);
2348                 }
2349                 {
2350                         sprintf (name, "%s.bmp", precache_textures[i]);
2351                         sprintf (srcfile,"%s%s",srcdir, name);
2352                         sprintf (destfile,"%s%s",destdir, name);
2353                         if (copytype == 1)
2354                                 QCC_CopyFile (srcfile, destfile);
2355                         else
2356                                 QCC_PackFile (srcfile, name);
2357                 }
2358                 {
2359                         sprintf (name, "%s.tga", precache_textures[i]);
2360                         sprintf (srcfile,"%s%s",srcdir, name);
2361                         sprintf (destfile,"%s%s",destdir, name);
2362                         if (copytype == 1)
2363                                 QCC_CopyFile (srcfile, destfile);
2364                         else
2365                                 QCC_PackFile (srcfile, name);
2366                 }
2367         }
2368         for (i=0 ; i<numfiles ; i++)
2369         {
2370                 if (precache_files_block[i] != blocknum)
2371                         continue;
2372                 sprintf (srcfile,"%s%s",srcdir, precache_files[i]);
2373                 sprintf (destfile,"%s%s",destdir, precache_files[i]);
2374                 if (copytype == 1)
2375                         QCC_CopyFile (srcfile, destfile);
2376                 else
2377                         QCC_PackFile (srcfile, precache_files[i]);
2378         }
2379
2380         if (copytype == 2)
2381         {
2382                 header.id[0] = 'P';
2383                 header.id[1] = 'A';
2384                 header.id[2] = 'C';
2385                 header.id[3] = 'K';
2386                 dirlen = (qbyte *)pf - (qbyte *)pfiles;
2387                 header.dirofs = PRLittleLong(SafeSeek (packhandle, 0, SEEK_CUR));
2388                 header.dirlen = PRLittleLong(dirlen);
2389
2390                 SafeWrite (packhandle, pfiles, dirlen);
2391
2392                 SafeSeek (packhandle, 0, SEEK_SET);
2393                 SafeWrite (packhandle, &header, sizeof(header));
2394                 SafeClose (packhandle);
2395
2396         // do a crc of the file
2397                 QCC_CRC_Init (&crc);
2398                 for (i=0 ; i<dirlen ; i++)
2399                         QCC_CRC_ProcessByte (&crc, ((qbyte *)pfiles)[i]);
2400
2401                 i = pf - pfiles;
2402                 printf ("%i files packed in %i bytes (%i crc)\n",i, packbytes, crc);
2403         }
2404 }
2405
2406 void QCC_CopyFiles (void)
2407 {
2408         char *s;
2409         char    srcdir[1024], destdir[1024];
2410         int             p;
2411
2412         if (verbose)
2413         {
2414                 if (numsounds > 0)
2415                         printf ("%3i unique precache_sounds\n", numsounds);
2416                 if (nummodels > 0)
2417                         printf ("%3i unique precache_models\n", nummodels);
2418                 if (numtextures > 0)
2419                         printf ("%3i unique precache_textures\n", numtextures);
2420                 if (numfiles > 0)
2421                         printf ("%3i unique precache_files\n", numfiles);
2422         }
2423
2424         p = QCC_CheckParm ("-copy");
2425         if (p && p < myargc-2)
2426         {       // create a new directory tree
2427
2428                 strcpy (srcdir, myargv[p+1]);
2429                 strcpy (destdir, myargv[p+2]);
2430                 if (srcdir[strlen(srcdir)-1] != '/')
2431                         strcat (srcdir, "/");
2432                 if (destdir[strlen(destdir)-1] != '/')
2433                         strcat (destdir, "/");
2434
2435                 _QCC_CopyFiles(0, 1, srcdir, destdir);
2436                 return;
2437         }
2438
2439         for ( p = 0; p < 5; p++)
2440         {
2441                 s = QCC_Packname[p];
2442                 if (!*s)
2443                         continue;
2444                 strcpy(destdir, s);
2445                 strcpy(srcdir, "");
2446                 _QCC_CopyFiles(p+1, 2, srcdir, destdir);
2447         }
2448         return;
2449         /*
2450
2451         blocknum = 1;
2452         p = QCC_CheckParm ("-pak2");
2453         if (p && p <myargc-2)
2454                 blocknum = 2;
2455         else
2456                 p = QCC_CheckParm ("-pak");
2457         if (p && p < myargc-2)
2458         {       // create a pak file
2459                 strcpy (srcdir, myargv[p+1]);
2460                 strcpy (destdir, myargv[p+2]);
2461                 if (srcdir[strlen(srcdir)-1] != '/')
2462                         strcat (srcdir, "/");
2463                 DefaultExtension (destdir, ".pak");
2464
2465
2466                 copytype = 2;
2467
2468                 _QCC_CopyFiles(blocknum, copytype, srcdir, destdir);
2469         }
2470         */
2471 }
2472
2473 //============================================================================
2474
2475
2476 void QCC_PR_CommandLinePrecompilerOptions (void)
2477 {
2478         CompilerConstant_t *cnst;
2479         int             i, p;
2480         char *name, *val;
2481
2482         for (i = 1;i<myargc;i++)
2483         {
2484                 //compiler constant
2485                 if ( !strncmp(myargv[i], "-D", 2) )
2486                 {
2487                         name = myargv[i] + 2;
2488                         val = strchr(name, '=');
2489                         if (val)
2490                         {
2491                                 *val = '\0';
2492                                 val++;
2493                         }
2494                         cnst = QCC_PR_DefineName(name);
2495                         if (val)
2496                         {
2497                                 cnst->value = qccHunkAlloc(strlen(val)+1);
2498                                 memcpy(cnst->value, val, strlen(val)+1);
2499                         }
2500                 }
2501
2502                 //optimisations.
2503                 else if ( !strnicmp(myargv[i], "-O", 2) || !strnicmp(myargv[i], "/O", 2) )
2504                 {
2505                         p = 0;
2506                         if (myargv[i][2] >= '0' && myargv[i][2] <= '3')
2507                         {
2508                         }
2509                         else if (!strnicmp(myargv[i]+2, "no-", 3))
2510                         {
2511                                 if (myargv[i][5])
2512                                 {
2513                                         for (p = 0; optimisations[p].enabled; p++)
2514                                         {
2515                                                 if ((*optimisations[p].abbrev && !stricmp(myargv[i]+5, optimisations[p].abbrev)) || !stricmp(myargv[i]+5, optimisations[p].fullname))
2516                                                 {
2517                                                         *optimisations[p].enabled = false;
2518                                                         break;
2519                                                 }
2520                                         }
2521                                 }
2522                         }
2523                         else
2524                         {
2525                                 if (myargv[i][2])
2526                                         for (p = 0; optimisations[p].enabled; p++)
2527                                                 if ((*optimisations[p].abbrev && !stricmp(myargv[i]+2, optimisations[p].abbrev)) || !stricmp(myargv[i]+2, optimisations[p].fullname))
2528                                                 {
2529                                                         *optimisations[p].enabled = true;
2530                                                         break;
2531                                                 }
2532                         }
2533                         if (!optimisations[p].enabled)
2534                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised optimisation parameter (%s)", myargv[i]);
2535                 }
2536
2537                 else if ( !strnicmp(myargv[i], "-K", 2) || !strnicmp(myargv[i], "/K", 2) )
2538                 {
2539                         p = 0;
2540                         if (!strnicmp(myargv[i]+2, "no-", 3))
2541                         {
2542                                 for (p = 0; compiler_flag[p].enabled; p++)
2543                                         if (!stricmp(myargv[i]+5, compiler_flag[p].abbrev))
2544                                         {
2545                                                 *compiler_flag[p].enabled = false;
2546                                                 break;
2547                                         }
2548                         }
2549                         else
2550                         {
2551                                 for (p = 0; compiler_flag[p].enabled; p++)
2552                                         if (!stricmp(myargv[i]+2, compiler_flag[p].abbrev))
2553                                         {
2554                                                 *compiler_flag[p].enabled = true;
2555                                                 break;
2556                                         }
2557                         }
2558
2559                         if (!compiler_flag[p].enabled)
2560                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised keyword parameter (%s)", myargv[i]);
2561                 }
2562                 else if ( !strnicmp(myargv[i], "-F", 2) || !strnicmp(myargv[i], "/F", 2) )
2563                 {
2564                         p = 0;
2565                         if (!strnicmp(myargv[i]+2, "no-", 3))
2566                         {
2567                                 for (p = 0; compiler_flag[p].enabled; p++)
2568                                         if (!stricmp(myargv[i]+5, compiler_flag[p].abbrev))
2569                                         {
2570                                                 *compiler_flag[p].enabled = false;
2571                                                 break;
2572                                         }
2573                         }
2574                         else
2575                         {
2576                                 for (p = 0; compiler_flag[p].enabled; p++)
2577                                         if (!stricmp(myargv[i]+2, compiler_flag[p].abbrev))
2578                                         {
2579                                                 *compiler_flag[p].enabled = true;
2580                                                 break;
2581                                         }
2582                         }
2583
2584                         if (!compiler_flag[p].enabled)
2585                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised flag parameter (%s)", myargv[i]);
2586                 }
2587
2588
2589                 else if ( !strncmp(myargv[i], "-T", 2) || !strncmp(myargv[i], "/T", 2) )
2590                 {
2591                         p = 0;
2592                         for (p = 0; targets[p].name; p++)
2593                                 if (!stricmp(myargv[i]+2, targets[p].name))
2594                                 {
2595                                         qcc_targetformat = targets[p].target;
2596                                         break;
2597                                 }
2598
2599                         if (!targets[p].name)
2600                                 QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised target parameter (%s)", myargv[i]);
2601                 }
2602
2603                 else if ( !strnicmp(myargv[i], "-W", 2) || !strnicmp(myargv[i], "/W", 2) )
2604                 {
2605                         if (!stricmp(myargv[i]+2, "all"))
2606                                 memset(qccwarningdisabled, 0, sizeof(qccwarningdisabled));
2607                         else if (!stricmp(myargv[i]+2, "none"))
2608                                 memset(qccwarningdisabled, 1, sizeof(qccwarningdisabled));
2609                         else if(!stricmp(myargv[i]+2, "error"))
2610                                 pr_werror = true;
2611                         else if (!stricmp(myargv[i]+2, "no-mundane"))
2612                         {       //disable mundane performance/efficiency/blah warnings that don't affect code.
2613                                 qccwarningdisabled[WARN_SAMENAMEASGLOBAL] = true;
2614                                 qccwarningdisabled[WARN_DUPLICATEDEFINITION] = true;
2615                                 qccwarningdisabled[WARN_CONSTANTCOMPARISON] = true;
2616                                 qccwarningdisabled[WARN_ASSIGNMENTINCONDITIONAL] = true;
2617                                 qccwarningdisabled[WARN_DEADCODE] = true;
2618                                 qccwarningdisabled[WARN_NOTREFERENCEDCONST] = true;
2619                                 qccwarningdisabled[WARN_NOTREFERENCED] = true;
2620                                 qccwarningdisabled[WARN_POINTLESSSTATEMENT] = true;
2621                                 qccwarningdisabled[WARN_ASSIGNMENTTOCONSTANTFUNC] = true;
2622                                 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.
2623                                 qccwarningdisabled[WARN_IDENTICALPRECOMPILER] = true;
2624                                 qccwarningdisabled[WARN_UNDEFNOTDEFINED] = true;
2625                                 qccwarningdisabled[WARN_FIXEDRETURNVALUECONFLICT] = true;
2626                                 qccwarningdisabled[WARN_EXTRAPRECACHE] = true;
2627                                 qccwarningdisabled[WARN_CORRECTEDRETURNTYPE] = true;
2628                         }
2629                         else
2630                         {
2631                                 p = 0;
2632                                 if (!strnicmp(myargv[i]+2, "no-", 3))
2633                                 {
2634                                         for (p = 0; warningnames[p].name; p++)
2635                                                 if (!strcmp(myargv[i]+5, warningnames[p].name))
2636                                                 {
2637                                                         qccwarningdisabled[warningnames[p].index] = true;
2638                                                         break;
2639                                                 }
2640                                 }
2641                                 else
2642                                 {
2643                                         for (p = 0; warningnames[p].name; p++)
2644                                                 if (!stricmp(myargv[i]+2, warningnames[p].name))
2645                                                 {
2646                                                         qccwarningdisabled[warningnames[p].index] = false;
2647                                                         break;
2648                                                 }
2649                                 }
2650
2651                                 if (!warningnames[p].name)
2652                                         QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised warning parameter (%s)", myargv[i]);
2653                         }
2654                 }
2655         }
2656 }
2657
2658 /*
2659 ============
2660 main
2661 ============
2662 */
2663
2664 char    *qccmsrc;
2665 char    *qccmsrc2;
2666 char    qccmfilename[1024];
2667 char    qccmprogsdat[1024];
2668 char    qccmsourcedir[1024];
2669
2670 void QCC_FinishCompile(void);
2671
2672
2673 void SetEndian(void);
2674
2675
2676
2677 void QCC_SetDefaultProperties (void)
2678 {
2679         int level;
2680         int i;
2681
2682         Hash_InitTable(&compconstantstable, MAX_CONSTANTS, qccHunkAlloc(Hash_BytesForBuckets(MAX_CONSTANTS)));
2683
2684         ForcedCRC = 0;
2685         defaultstatic = 0;
2686
2687         QCC_PR_DefineName("FTEQCC");
2688
2689         if (QCC_CheckParm("/Oz"))
2690         {
2691                 qcc_targetformat = QCF_FTE;
2692                 QCC_PR_DefineName("OP_COMP_STATEMENTS");
2693                 QCC_PR_DefineName("OP_COMP_DEFS");
2694                 QCC_PR_DefineName("OP_COMP_FIELDS");
2695                 QCC_PR_DefineName("OP_COMP_FUNCTIONS");
2696                 QCC_PR_DefineName("OP_COMP_STRINGS");
2697                 QCC_PR_DefineName("OP_COMP_GLOBALS");
2698                 QCC_PR_DefineName("OP_COMP_LINES");
2699                 QCC_PR_DefineName("OP_COMP_TYPES");
2700         }
2701
2702         if (QCC_CheckParm("/O0") || QCC_CheckParm("-O0"))
2703                 level = 0;
2704         else if (QCC_CheckParm("/O1") || QCC_CheckParm("-O1"))
2705                 level = 1;
2706         else if (QCC_CheckParm("/O2") || QCC_CheckParm("-O2"))
2707                 level = 2;
2708         else if (QCC_CheckParm("/O3") || QCC_CheckParm("-O3"))
2709                 level = 3;
2710         else
2711                 level = -1;
2712
2713         if (level == -1)
2714         {
2715                 for (i = 0; optimisations[i].enabled; i++)
2716                 {
2717                         if (optimisations[i].flags & FLAG_ASDEFAULT)
2718                                 *optimisations[i].enabled = true;
2719                         else
2720                                 *optimisations[i].enabled = false;
2721                 }
2722         }
2723         else
2724         {
2725                 for (i = 0; optimisations[i].enabled; i++)
2726                 {
2727                         if (level >= optimisations[i].optimisationlevel)
2728                                 *optimisations[i].enabled = true;
2729                         else
2730                                 *optimisations[i].enabled = false;
2731                 }
2732         }
2733
2734         if (QCC_CheckParm ("-h2"))
2735                 qcc_targetformat = QCF_HEXEN2;
2736         else if (QCC_CheckParm ("-fte"))
2737                 qcc_targetformat = QCF_FTE;
2738         else if (QCC_CheckParm ("-dp"))
2739                 qcc_targetformat = QCF_DARKPLACES;
2740         else
2741                 qcc_targetformat = QCF_STANDARD;
2742
2743
2744         //enable all warnings
2745         memset(qccwarningdisabled, 0, sizeof(qccwarningdisabled));
2746
2747         //play with default warnings.
2748         qccwarningdisabled[WARN_NOTREFERENCEDCONST] = true;
2749         qccwarningdisabled[WARN_MACROINSTRING] = true;
2750 //      qccwarningdisabled[WARN_ASSIGNMENTTOCONSTANT] = true;
2751         qccwarningdisabled[WARN_FIXEDRETURNVALUECONFLICT] = true;
2752         qccwarningdisabled[WARN_EXTRAPRECACHE] = true;
2753         qccwarningdisabled[WARN_DEADCODE] = true;
2754         qccwarningdisabled[WARN_INEFFICIENTPLUSPLUS] = true;
2755         qccwarningdisabled[WARN_FTE_SPECIFIC] = true;
2756         qccwarningdisabled[WARN_EXTENSION_USED] = true;
2757         qccwarningdisabled[WARN_IFSTRING_USED] = true;
2758
2759
2760
2761         if (QCC_CheckParm("-nowarn") || QCC_CheckParm("-Wnone"))
2762                 memset(qccwarningdisabled, 1, sizeof(qccwarningdisabled));
2763         if (QCC_CheckParm("-Wall"))
2764                 memset(qccwarningdisabled, 0, sizeof(qccwarningdisabled));
2765
2766         if (QCC_CheckParm("-h2"))
2767                 qccwarningdisabled[WARN_CASEINSENSATIVEFRAMEMACRO] = true;
2768
2769         //Check the command line
2770         QCC_PR_CommandLinePrecompilerOptions();
2771
2772
2773         if (qcc_targetformat == QCF_HEXEN2)     //force on the thinktime keyword if hexen2 progs.
2774                 keyword_thinktime = true;
2775
2776         if (QCC_CheckParm("/Debug"))    //disable any debug optimisations
2777         {
2778                 for (i = 0; optimisations[i].enabled; i++)
2779                 {
2780                         if (optimisations[i].flags & FLAG_KILLSDEBUGGERS)
2781                                 *optimisations[i].enabled = false;
2782                 }
2783         }
2784 }
2785
2786 //builds a list of files, pretends that they came from a progs.src
2787 int QCC_FindQCFiles()
2788 {
2789 #ifdef _WIN32
2790         WIN32_FIND_DATA fd;
2791         HANDLE h;
2792 #endif
2793
2794         int numfiles = 0, i, j;
2795         char *filelist[256], *temp;
2796
2797
2798         qccmsrc = qccHunkAlloc(8192);
2799         strcat(qccmsrc, "progs.dat\n");//"#pragma PROGS_DAT progs.dat\n");
2800
2801 #ifdef _WIN32
2802         h = FindFirstFile("*.qc", &fd);
2803         if (h == INVALID_HANDLE_VALUE)
2804                 return 0;
2805
2806         do
2807         {
2808                 filelist[numfiles] = qccHunkAlloc (strlen(fd.cFileName)+1);
2809                 strcpy(filelist[numfiles], fd.cFileName);
2810                 numfiles++;
2811         } while(FindNextFile(h, &fd)!=0);
2812         FindClose(h);
2813 #else
2814         printf("-Facc is not supported on this platform. Please make a progs.src file instead\n");
2815 #endif
2816
2817         //Sort alphabetically.
2818         //bubble. :(
2819
2820         for (i = 0; i < numfiles-1; i++)
2821         {
2822                 for (j = i+1; j < numfiles; j++)
2823                 {
2824                         if (stricmp(filelist[i], filelist[j]) > 0)
2825                         {
2826                                 temp = filelist[j];
2827                                 filelist[j] = filelist[i];
2828                                 filelist[i] = temp;
2829                         }
2830                 }
2831         }
2832         for (i = 0; i < numfiles; i++)
2833         {
2834                 strcat(qccmsrc, filelist[i]);
2835                 strcat(qccmsrc, "\n");
2836 //              strcat(qccmsrc, "#include \"");
2837 //              strcat(qccmsrc, filelist[i]);
2838 //              strcat(qccmsrc, "\"\n");
2839         }
2840
2841         return numfiles;
2842 }
2843
2844 int qcc_compileactive = false;
2845 extern int accglobalsblock;
2846 char *originalqccmsrc;  //for autoprototype.
2847 void QCC_main (int argc, char **argv)   //as part of the quake engine
2848 {
2849         extern int                      pr_bracelevel;
2850
2851         int             p;
2852
2853 #ifndef QCCONLY
2854         char    destfile2[1024], *s2;
2855 #endif
2856         char *s;
2857
2858         SetEndian();
2859
2860         myargc = argc;
2861         myargv = argv;
2862
2863         qcc_compileactive = true;
2864
2865         pHash_Get = &Hash_Get;
2866         pHash_GetNext = &Hash_GetNext;
2867         pHash_Add = &Hash_Add;
2868
2869         MAX_REGS                = 65536;
2870         MAX_STRINGS             = 1000000;
2871         MAX_GLOBALS             = 65535;
2872         MAX_FIELDS              = 2048;
2873         MAX_STATEMENTS  = 0x80000;
2874         MAX_FUNCTIONS   = 16384;
2875         maxtypeinfos    = 16384;
2876         MAX_CONSTANTS   = 2048;
2877
2878         compressoutput = 0;
2879
2880         p = externs->FileSize("qcc.cfg");
2881         if (p < 0)
2882                 p = externs->FileSize("src/qcc.cfg");
2883         if (p>0)
2884         {
2885                 s = qccHunkAlloc(p+1);
2886                 s = externs->ReadFile("qcc.cfg", s, p);
2887
2888                 while(1)
2889                 {
2890                         s = QCC_COM_Parse(s);
2891                         if (!strcmp(qcc_token, "MAX_REGS"))
2892                         {
2893                                 s = QCC_COM_Parse(s);
2894                                 MAX_REGS = atoi(qcc_token);
2895                         } else if (!strcmp(qcc_token, "MAX_STRINGS")) {
2896                                 s = QCC_COM_Parse(s);
2897                                 MAX_STRINGS = atoi(qcc_token);
2898                         } else if (!strcmp(qcc_token, "MAX_GLOBALS")) {
2899                                 s = QCC_COM_Parse(s);
2900                                 MAX_GLOBALS = atoi(qcc_token);
2901                         } else if (!strcmp(qcc_token, "MAX_FIELDS")) {
2902                                 s = QCC_COM_Parse(s);
2903                                 MAX_FIELDS = atoi(qcc_token);
2904                         } else if (!strcmp(qcc_token, "MAX_STATEMENTS")) {
2905                                 s = QCC_COM_Parse(s);
2906                                 MAX_STATEMENTS = atoi(qcc_token);
2907                         } else if (!strcmp(qcc_token, "MAX_FUNCTIONS")) {
2908                                 s = QCC_COM_Parse(s);
2909                                 MAX_FUNCTIONS = atoi(qcc_token);
2910                         } else if (!strcmp(qcc_token, "MAX_TYPES")) {
2911                                 s = QCC_COM_Parse(s);
2912                                 maxtypeinfos = atoi(qcc_token);
2913                         } else if (!strcmp(qcc_token, "MAX_TEMPS")) {
2914                                 s = QCC_COM_Parse(s);
2915                                 max_temps = atoi(qcc_token);
2916                         } else if (!strcmp(qcc_token, "CONSTANTS")) {
2917                                 s = QCC_COM_Parse(s);
2918                                 MAX_CONSTANTS = atoi(qcc_token);
2919                         }
2920                         else if (!s)
2921                                 break;
2922                         else
2923                                 printf("Bad token in qcc.cfg file\n");
2924                 }
2925         }
2926         /* don't try to be clever
2927         else if (p < 0)
2928         {
2929                 s = qccHunkAlloc(8192);
2930                 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",
2931                                         MAX_REGS,    MAX_STRINGS,    MAX_GLOBALS,    MAX_FIELDS,    MAX_STATEMENTS,    MAX_FUNCTIONS,    maxtypeinfos);
2932                 externs->WriteFile("qcc.cfg", s, strlen(s));
2933         }
2934         */
2935
2936         strcpy(QCC_copyright, "This file was created with ForeThought's modified QuakeC compiler\nThanks to ID Software");
2937         for (p = 0; p < 5; p++)
2938                 strcpy(QCC_Packname[p], "");
2939
2940         for (p = 0; compiler_flag[p].enabled; p++)
2941         {
2942                 *compiler_flag[p].enabled = compiler_flag[p].flags & FLAG_ASDEFAULT;
2943         }
2944         pr_werror = false;
2945
2946         QCC_SetDefaultProperties();
2947
2948         optres_shortenifnots = 0;
2949         optres_overlaptemps = 0;
2950         optres_noduplicatestrings = 0;
2951         optres_constantarithmatic = 0;
2952         optres_nonvec_parms = 0;
2953         optres_constant_names = 0;
2954         optres_constant_names_strings = 0;
2955         optres_precache_file = 0;
2956         optres_filenames = 0;
2957         optres_assignments = 0;
2958         optres_unreferenced = 0;
2959         optres_function_names = 0;
2960         optres_locals = 0;
2961         optres_dupconstdefs = 0;
2962         optres_return_only = 0;
2963         optres_compound_jumps = 0;
2964 //      optres_comexprremoval = 0;
2965         optres_stripfunctions = 0;
2966         optres_locals_marshalling = 0;
2967         optres_logicops = 0;
2968
2969         optres_test1 = 0;
2970         optres_test2 = 0;
2971
2972         accglobalsblock = 0;
2973
2974
2975         numtemps = 0;
2976
2977         QCC_PurgeTemps();
2978
2979         strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS);
2980         strofs = 1;
2981
2982         statements = (void *)qccHunkAlloc(sizeof(QCC_dstatement_t) * MAX_STATEMENTS);
2983         numstatements = 0;
2984         statement_linenums = (void *)qccHunkAlloc(sizeof(int) * MAX_STATEMENTS);
2985
2986         functions = (void *)qccHunkAlloc(sizeof(QCC_dfunction_t) * MAX_FUNCTIONS);
2987         numfunctions=0;
2988
2989         pr_bracelevel = 0;
2990
2991         qcc_pr_globals = (void *)qccHunkAlloc(sizeof(float) * MAX_REGS);
2992         numpr_globals=0;
2993
2994         Hash_InitTable(&globalstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2995         Hash_InitTable(&localstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2996         Hash_InitTable(&floatconstdefstable, MAX_REGS+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS+1)));
2997         Hash_InitTable(&stringconstdefstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2998         Hash_InitTable(&stringconstdefstable_dotranslate, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
2999         dotranslate=0;
3000         dotranslate_count=0;
3001
3002 //      pr_global_defs = (QCC_def_t **)qccHunkAlloc(sizeof(QCC_def_t *) * MAX_REGS);
3003
3004         qcc_globals = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_GLOBALS);
3005         numglobaldefs=0;
3006
3007         fields = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_FIELDS);
3008         numfielddefs=0;
3009
3010 memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
3011
3012         precache_sounds = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_SOUNDS);
3013         precache_sounds_block = (void *)qccHunkAlloc(sizeof(int)*MAX_SOUNDS);
3014         precache_sounds_used = (void *)qccHunkAlloc(sizeof(int)*MAX_SOUNDS);
3015         numsounds=0;
3016
3017         precache_textures = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_TEXTURES);
3018         precache_textures_block = (void *)qccHunkAlloc(sizeof(int)*MAX_TEXTURES);
3019         numtextures=0;
3020
3021         precache_models = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_MODELS);
3022         precache_models_block = (void *)qccHunkAlloc(sizeof(int)*MAX_MODELS);
3023         precache_models_used = (void *)qccHunkAlloc(sizeof(int)*MAX_MODELS);
3024         nummodels=0;
3025
3026         precache_files = (void *)qccHunkAlloc(sizeof(char)*MAX_DATA_PATH*MAX_FILES);
3027         precache_files_block = (void *)qccHunkAlloc(sizeof(int)*MAX_FILES);
3028         numfiles = 0;
3029
3030         qcc_typeinfo = (void *)qccHunkAlloc(sizeof(QCC_type_t)*maxtypeinfos);
3031         numtypeinfos = 0;
3032
3033         qcc_tempofs = qccHunkAlloc(sizeof(int) * max_temps);
3034         tempsstart = 0;
3035
3036         bodylessfuncs=0;
3037
3038         memset(&pr, 0, sizeof(pr));
3039 #ifdef MAX_EXTRA_PARMS
3040         memset(&extra_parms, 0, sizeof(extra_parms));
3041 #endif
3042
3043         if ( QCC_CheckParm ("/?") || QCC_CheckParm ("?") || QCC_CheckParm ("-?") || QCC_CheckParm ("-help") || QCC_CheckParm ("--help"))
3044         {
3045                 printf ("qcc looks for progs.src in the current directory.\n");
3046                 printf ("to look in a different directory: qcc -src <directory>\n");
3047 //              printf ("to build a clean data tree: qcc -copy <srcdir> <destdir>\n");
3048 //              printf ("to build a clean pak file: qcc -pak <srcdir> <packfile>\n");
3049 //              printf ("to bsp all bmodels: qcc -bspmodels <gamedir>\n");
3050                 printf ("-Fwasm <funcname> causes FTEQCC to dump all asm to qc.asm\n");
3051                 printf ("-O0 to disable optimisations\n");
3052                 printf ("-O1 to optimise for size\n");
3053                 printf ("-O2 to optimise more - some behaviours may change\n");
3054                 printf ("-O3 to optimise lots - experimental or non-future-proof\n");
3055                 printf ("-Oname to enable an optimisation\n");
3056                 printf ("-Ono-name to disable optimisations\n");
3057                 printf ("-Kkeyword to activate keyword\n");
3058                 printf ("-Kno-keyword to disable keyword\n");
3059                 printf ("-Wall to give a stupid number of warnings\n");
3060                 printf ("-Ttarget to set a output format\n");
3061                 printf ("-Fautoproto to enable automatic prototyping\n");
3062                 printf ("-Fsubscope to make locals specific to their subscope\n");
3063
3064                 qcc_compileactive = false;
3065                 return;
3066         }
3067
3068         if (flag_caseinsensative)
3069         {
3070                 printf("Compiling without case sensativity\n");
3071                 pHash_Get = &Hash_GetInsensative;
3072                 pHash_GetNext = &Hash_GetNextInsensative;
3073                 pHash_Add = &Hash_AddInsensative;
3074         }
3075
3076
3077         if (opt_locals_marshalling)
3078                 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nLocals marshalling might be buggy. Use with caution\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
3079
3080         p = QCC_CheckParm ("-src");
3081         if (p && p < argc-1 )
3082         {
3083                 strcpy (qccmsourcedir, argv[p+1]);
3084                 strcat (qccmsourcedir, "/");
3085                 printf ("Source directory: %s\n", qccmsourcedir);
3086         }
3087         else
3088                 *qccmsourcedir = '\0';
3089
3090         QCC_InitData ();
3091
3092         QCC_PR_BeginCompilation ((void *)qccHunkAlloc (0x100000), 0x100000);
3093
3094         if (flag_acc)
3095         {
3096                 if (!QCC_FindQCFiles())
3097                         QCC_Error (ERR_COULDNTOPENFILE, "Couldn't open file for asm output.");
3098         }
3099         else
3100         {
3101                 if (!numsourcefiles)
3102                 {
3103                         p = QCC_CheckParm ("-qc");
3104                         if (!p || p >= argc-1 || argv[p+1][0] == '-')
3105                                 p = QCC_CheckParm ("-srcfile");
3106                         if (p && p < argc-1 )
3107                                 sprintf (qccmprogsdat, "%s", argv[p+1]);
3108                         else
3109                         {       //look for a preprogs.src... :o)
3110                                 sprintf (qccmprogsdat, "preprogs.src");
3111                                 if (externs->FileSize(qccmprogsdat) <= 0)
3112                                         sprintf (qccmprogsdat, "progs.src");
3113                         }
3114
3115                         numsourcefiles = 0;
3116                         strcpy(sourcefileslist[numsourcefiles++], qccmprogsdat);
3117                         currentsourcefile = 0;
3118                 }
3119                 else if (currentsourcefile == numsourcefiles)
3120                 {
3121                         //no more.
3122                         qcc_compileactive = false;
3123                         numsourcefiles = 0;
3124                         currentsourcefile = 0;
3125                         return;
3126                 }
3127
3128                 if (currentsourcefile)
3129                         printf("-------------------------------------\n");
3130
3131                 sprintf (qccmprogsdat, "%s%s", qccmsourcedir, sourcefileslist[currentsourcefile++]);
3132                 printf ("Source file: %s\n", qccmprogsdat);
3133
3134                 if (QCC_LoadFile (qccmprogsdat, (void *)&qccmsrc) == -1)
3135                 {
3136                         return;
3137                 }
3138         }
3139
3140 #ifdef WRITEASM
3141         if (writeasm)
3142         {
3143                 asmfile = fopen("qc.asm", "wb");
3144                 if (!asmfile)
3145                         QCC_Error (ERR_INTERNAL, "Couldn't open file for asm output.");
3146         }
3147 #endif
3148
3149         newstylesource = false;
3150         while(*qccmsrc && *qccmsrc < ' ')
3151                 qccmsrc++;
3152         pr_file_p = QCC_COM_Parse(qccmsrc);
3153
3154         if (QCC_CheckParm ("-qc"))
3155         {
3156                 strcpy(destfile, qccmprogsdat);
3157                 StripExtension(destfile);
3158                 strcat(destfile, ".qco");
3159
3160                 p = QCC_CheckParm ("-o");
3161                 if (!p || p >= argc-1 || argv[p+1][0] == '-')
3162                 if (p && p < argc-1 )
3163                         sprintf (destfile, "%s%s", qccmsourcedir, argv[p+1]);
3164                 goto newstyle;
3165         }
3166
3167         if (*qcc_token == '#')
3168         {
3169                 void StartNewStyleCompile(void);
3170 newstyle:
3171                 newstylesource = true;
3172                 StartNewStyleCompile();
3173                 return;
3174         }
3175
3176         pr_file_p = qccmsrc;
3177         QCC_PR_LexWhitespace();
3178         qccmsrc = pr_file_p;
3179
3180         s = qccmsrc;
3181         pr_file_p = qccmsrc;
3182         QCC_PR_SimpleGetToken ();
3183         strcpy(qcc_token, pr_token);
3184         qccmsrc = pr_file_p;
3185
3186         if (!qccmsrc)
3187                 QCC_Error (ERR_NOOUTPUT, "No destination filename.  qcc -help for info.");
3188         strcpy (destfile, qcc_token);
3189
3190 #ifndef QCCONLY
3191         p=0;
3192         s2 = strcpy(destfile2, destfile);
3193         if (!strncmp(s2, "./", 2))
3194                 s2+=2;
3195         else
3196         {
3197                 while(!strncmp(s2, "../", 3))
3198                 {
3199                         s2+=3;
3200                         p++;
3201                 }
3202         }
3203         strcpy(qccmfilename, qccmsourcedir);
3204         for (s=qccmfilename+strlen(qccmfilename);p && s>=qccmfilename; s--)
3205         {
3206                 if (*s == '/' || *s == '\\')
3207                 {
3208                         *(s+1) = '\0';
3209                         p--;
3210                 }
3211         }
3212         sprintf(destfile, "%s", s2);
3213
3214         while (p>0)
3215         {
3216                 memmove(destfile+3, destfile, strlen(destfile)+1);
3217                 destfile[0] = '.';
3218                 destfile[1] = '.';
3219                 destfile[2] = '/';
3220                 p--;
3221         }
3222 #endif
3223
3224         if (flag_filetimes)
3225         {
3226                 struct stat s, os;
3227                 pbool modified = false;
3228
3229                 if (stat(destfile, &os) != -1)
3230                 {
3231                         while ((pr_file_p=QCC_COM_Parse(pr_file_p)))
3232                         {
3233                                 if (stat(qcc_token, &s) == -1 || s.st_mtime > os.st_mtime)
3234                                 {
3235                                         printf("%s changed\n", qcc_token);
3236                                         modified = true;
3237                                         break;
3238                                 }
3239                         }
3240                         if (!modified)
3241                         {
3242                                 printf("No changes\n");
3243                                 qcc_compileactive = false;
3244                                 return;
3245                         }
3246                         else
3247                         {
3248                                 pr_file_p = qccmsrc;
3249                         }
3250                 }
3251         }
3252
3253         printf ("outputfile: %s\n", destfile);
3254
3255         pr_dumpasm = false;
3256
3257         currentchunk = NULL;
3258
3259         originalqccmsrc = qccmsrc;
3260 }
3261
3262 void new_QCC_ContinueCompile(void);
3263 //called between exe frames - won't loose net connection (is the theory)...
3264 void QCC_ContinueCompile(void)
3265 {
3266         char *s, *s2;
3267         currentchunk = NULL;
3268         if (!qcc_compileactive)
3269                 //HEY!
3270                 return;
3271
3272         if (newstylesource)
3273         {
3274                 new_QCC_ContinueCompile();
3275                 return;
3276         }
3277
3278         qccmsrc = QCC_COM_Parse(qccmsrc);
3279         if (!qccmsrc)
3280         {
3281                 if (autoprototype)
3282                 {
3283                         qccmsrc = originalqccmsrc;
3284                         QCC_SetDefaultProperties();
3285                         autoprototype = false;
3286                         return;
3287                 }
3288                 QCC_FinishCompile();
3289
3290                 PostCompile();
3291                 if (!PreCompile())
3292                         return;
3293                 QCC_main(myargc, myargv);
3294                 return;
3295         }
3296         s = qcc_token;
3297
3298         strcpy (qccmfilename, qccmsourcedir);
3299         while(1)
3300         {
3301                 if (!strncmp(s, "..\\", 3) || !strncmp(s, "../", 3))
3302                 {
3303                         s2 = qccmfilename + strlen(qccmfilename)-2;
3304                         while (s2>=qccmfilename)
3305                         {
3306                                 if (*s2 == '/' || *s2 == '\\')
3307                                 {
3308                                         s2[1] = '\0';
3309                                         break;
3310                                 }
3311                                 s2--;
3312                         }
3313                         if (s2>=qccmfilename)
3314                         {
3315                                 s+=3;
3316                                 continue;
3317                         }
3318                 }
3319                 if (!strncmp(s, ".\\", 2) || !strncmp(s, "./", 2))
3320                 {
3321                         s+=2;
3322                         continue;
3323                 }
3324
3325                 break;
3326         }
3327         strcat (qccmfilename, s);
3328         if (autoprototype)
3329                 printf ("prototyping %s\n", qccmfilename);
3330         else
3331         {
3332                 printf ("compiling %s\n", qccmfilename);
3333         }
3334         QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
3335
3336         if (!QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
3337                 QCC_Error (ERR_PARSEERRORS, "Errors have occured\n");
3338 }
3339 void QCC_FinishCompile(void)
3340 {
3341         pbool donesomething;
3342         int crc;
3343 //      int p;
3344         currentchunk = NULL;
3345
3346         if (setjmp(pr_parse_abort))
3347                 QCC_Error(ERR_INTERNAL, "");
3348
3349         if (!QCC_PR_FinishCompilation ())
3350         {
3351                 QCC_Error (ERR_PARSEERRORS, "compilation errors");
3352         }
3353
3354 /*      p = QCC_CheckParm ("-asm");
3355         if (p)
3356         {
3357                 for (p++ ; p<myargc ; p++)
3358                 {
3359                         if (myargv[p][0] == '-')
3360                                 break;
3361                         QCC_PrintFunction (myargv[p]);
3362                 }
3363         }*/
3364
3365         /*p = QCC_CheckParm ("-ofs");
3366         if (p)
3367         {
3368                 for (p++ ; p<myargc ; p++)
3369                 {
3370                         if (myargv[p][0] == '-')
3371                                 break;
3372                         QCC_PrintOfs (atoi(myargv[p]));
3373                 }
3374         }*/
3375
3376         if (pr_werror && pr_warning_count != 0)
3377                 QCC_Error (ERR_PARSEERRORS, "compilation errors");
3378
3379 // write progdefs.h
3380         crc = QCC_PR_WriteProgdefs ("progdefs.h");
3381
3382 // write data file
3383         donesomething = QCC_WriteData (crc);
3384
3385 // regenerate bmodels if -bspmodels
3386         QCC_BspModels ();
3387
3388 // report / copy the data files
3389         QCC_CopyFiles ();
3390
3391         if (donesomething)
3392         {
3393                 if (verbose)
3394                 {
3395                         printf ("Compile Complete\n\n");
3396
3397                         if (optres_shortenifnots)
3398                                 printf("optres_shortenifnots %i\n", optres_shortenifnots);
3399                         if (optres_overlaptemps)
3400                                 printf("optres_overlaptemps %i\n", optres_overlaptemps);
3401                         if (optres_noduplicatestrings)
3402                                 printf("optres_noduplicatestrings %i\n", optres_noduplicatestrings);
3403                         if (optres_constantarithmatic)
3404                                 printf("optres_constantarithmatic %i\n", optres_constantarithmatic);
3405                         if (optres_nonvec_parms)
3406                                 printf("optres_nonvec_parms %i\n", optres_nonvec_parms);
3407                         if (optres_constant_names)
3408                                 printf("optres_constant_names %i\n", optres_constant_names);
3409                         if (optres_constant_names_strings)
3410                                 printf("optres_constant_names_strings %i\n", optres_constant_names_strings);
3411                         if (optres_precache_file)
3412                                 printf("optres_precache_file %i\n", optres_precache_file);
3413                         if (optres_filenames)
3414                                 printf("optres_filenames %i\n", optres_filenames);
3415                         if (optres_assignments)
3416                                 printf("optres_assignments %i\n", optres_assignments);
3417                         if (optres_unreferenced)
3418                                 printf("optres_unreferenced %i\n", optres_unreferenced);
3419                         if (optres_locals)
3420                                 printf("optres_locals %i\n", optres_locals);
3421                         if (optres_function_names)
3422                                 printf("optres_function_names %i\n", optres_function_names);
3423                         if (optres_dupconstdefs)
3424                                 printf("optres_dupconstdefs %i\n", optres_dupconstdefs);
3425                         if (optres_return_only)
3426                                 printf("optres_return_only %i\n", optres_return_only);
3427                         if (optres_compound_jumps)
3428                                 printf("optres_compound_jumps %i\n", optres_compound_jumps);
3429                 //      if (optres_comexprremoval)
3430                 //              printf("optres_comexprremoval %i\n", optres_comexprremoval);
3431                         if (optres_stripfunctions)
3432                                 printf("optres_stripfunctions %i\n", optres_stripfunctions);
3433                         if (optres_locals_marshalling)
3434                                 printf("optres_locals_marshalling %i\n", optres_locals_marshalling);
3435                         if (optres_logicops)
3436                                 printf("optres_logicops %i\n", optres_logicops);
3437
3438
3439                         if (optres_test1)
3440                                 printf("optres_test1 %i\n", optres_test1);
3441                         if (optres_test2)
3442                                 printf("optres_test2 %i\n", optres_test2);
3443
3444                         printf("numtemps %i\n", numtemps);
3445                 }
3446                 if (!flag_msvcstyle)
3447                         printf("%i warnings\n", pr_warning_count);
3448         }
3449
3450         qcc_compileactive = false;
3451 }
3452
3453
3454
3455
3456
3457 extern char *compilingfile;
3458 extern QCC_string_t     s_file, s_file2;
3459 extern char             *pr_file_p;
3460 extern int                      pr_source_line;
3461 extern QCC_def_t                *pr_scope;
3462 void QCC_PR_ParseDefs (char *classname);
3463
3464
3465
3466
3467
3468 void StartNewStyleCompile(void)
3469 {
3470         if (setjmp(pr_parse_abort))
3471         {
3472                 if (++pr_error_count > MAX_ERRORS)
3473                         return;
3474                 if (setjmp(pr_parse_abort))
3475                         return;
3476
3477                 QCC_PR_SkipToSemicolon ();
3478                 if (pr_token_type == tt_eof)
3479                         return;
3480         }
3481
3482
3483         QCC_PR_ClearGrabMacros ();      // clear the frame macros
3484
3485         compilingfile = qccmprogsdat;
3486
3487         pr_file_p = qccmsrc;
3488         s_file = s_file2 = QCC_CopyString (compilingfile);
3489
3490         pr_source_line = 0;
3491
3492         QCC_PR_NewLine (false);
3493
3494         QCC_PR_Lex ();  // read first token
3495 }
3496 void new_QCC_ContinueCompile(void)
3497 {
3498         if (setjmp(pr_parse_abort))
3499         {
3500 //              if (pr_error_count != 0)
3501                 {
3502                         QCC_Error (ERR_PARSEERRORS, "Errors have occured");
3503                         return;
3504                 }
3505                 QCC_PR_SkipToSemicolon ();
3506                 if (pr_token_type == tt_eof)
3507                         return;
3508         }
3509
3510         if (pr_token_type == tt_eof)
3511         {
3512                 if (pr_error_count)
3513                         QCC_Error (ERR_PARSEERRORS, "Errors have occured");
3514                 QCC_FinishCompile();
3515
3516                 PostCompile();
3517                 if (!PreCompile())
3518                         return;
3519                 QCC_main(myargc, myargv);
3520                 return;
3521         }
3522
3523         pr_scope = NULL;        // outside all functions
3524
3525         QCC_PR_ParseDefs (NULL);
3526 }
3527
3528 /*void new_QCC_ContinueCompile(void)
3529 {
3530         char *s, *s2;
3531         if (!qcc_compileactive)
3532                 //HEY!
3533                 return;
3534
3535 // compile all the files
3536
3537                 qccmsrc = QCC_COM_Parse(qccmsrc);
3538                 if (!qccmsrc)
3539                 {
3540                         QCC_FinishCompile();
3541                         return;
3542                 }
3543                 s = qcc_token;
3544
3545                 strcpy (qccmfilename, qccmsourcedir);
3546                 while(1)
3547                 {
3548                         if (!strncmp(s, "..\\", 3))
3549                         {
3550                                 s2 = qccmfilename + strlen(qccmfilename)-2;
3551                                 while (s2>=qccmfilename)
3552                                 {
3553                                         if (*s2 == '/' || *s2 == '\\')
3554                                         {
3555                                                 s2[1] = '\0';
3556                                                 break;
3557                                         }
3558                                         s2--;
3559                                 }
3560                                 s+=3;
3561                                 continue;
3562                         }
3563                         if (!strncmp(s, ".\\", 2))
3564                         {
3565                                 s+=2;
3566                                 continue;
3567                         }
3568
3569                         break;
3570                 }
3571 //              strcat (qccmfilename, s);
3572 //              printf ("compiling %s\n", qccmfilename);
3573 //              QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
3574
3575 //              if (!new_QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
3576 //                      QCC_Error ("Errors have occured\n");
3577
3578
3579                 {
3580
3581                         if (!pr.memory)
3582                                 QCC_Error ("PR_CompileFile: Didn't clear");
3583
3584                         QCC_PR_ClearGrabMacros ();      // clear the frame macros
3585
3586                         compilingfile = filename;
3587
3588                         pr_file_p = qccmsrc2;
3589                         s_file = QCC_CopyString (filename);
3590
3591                         pr_source_line = 0;
3592
3593                         QCC_PR_NewLine ();
3594
3595                         QCC_PR_Lex ();  // read first token
3596
3597                         while (pr_token_type != tt_eof)
3598                         {
3599                                 if (setjmp(pr_parse_abort))
3600                                 {
3601                                         if (++pr_error_count > MAX_ERRORS)
3602                                                 return false;
3603                                         QCC_PR_SkipToSemicolon ();
3604                                         if (pr_token_type == tt_eof)
3605                                                 return false;
3606                                 }
3607
3608                                 pr_scope = NULL;        // outside all functions
3609
3610                                 QCC_PR_ParseDefs ();
3611                         }
3612                 }
3613         return (pr_error_count == 0);
3614
3615 }*/
3616
3617
3618 #endif