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