4 void QCC_PR_ParseAsm(void);
6 #define MEMBERFIELDNAME "__m%s"
8 #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc
9 #define STRNCMP(s1,s2,l) (((*s1)!=(*s2)) || strncmp(s1+1,s2+1,l)) //pathetic saving here.
11 extern char *compilingfile;
15 extern int dotranslate;
16 extern int dotranslate_count;
18 //standard qcc keywords
20 #define keyword_return 1
22 #define keyword_else 1
23 #define keyword_local 1
24 #define keyword_while 1
31 pbool keyword_const; //fixme
32 pbool keyword_continue;
33 pbool keyword_default;
34 pbool keyword_entity; //for skipping the local
35 pbool keyword_float; //for skipping the local
38 pbool keyword_int; //for skipping the local
39 pbool keyword_integer; //for skipping the local
41 pbool keyword_string; //for skipping the local
44 pbool keyword_thinktime;
45 pbool keyword_var; //allow it to be initialised and set around the place.
46 pbool keyword_vector; //for skipping the local
49 pbool keyword_enum; //kinda like in c, but typedef not supported.
50 pbool keyword_enumflags; //like enum, but doubles instead of adds 1.
51 pbool keyword_typedef; //fixme
52 #define keyword_codesys flag_acc //reacc needs this (forces the resultant crc)
53 #define keyword_function flag_acc //reacc needs this (reacc has this on all functions, wierd eh?)
54 #define keyword_objdata flag_acc //reacc needs this (following defs are fields rather than globals, use var to disable)
55 #define keyword_object flag_acc //reacc needs this (an entity)
56 #define keyword_pfunc flag_acc //reacc needs this (pointer to function)
57 #define keyword_system flag_acc //reacc needs this (potatos)
58 #define keyword_real flag_acc //reacc needs this (a float)
59 #define keyword_exit flag_acc //emits an OP_DONE opcode.
60 #define keyword_external flag_acc //reacc needs this (a builtin)
61 pbool keyword_extern; //function is external, don't error or warn if the body was not found
62 pbool keyword_shared; //mark global to be copied over when progs changes (part of FTE_MULTIPROGS)
63 pbool keyword_noref; //nowhere else references this, don't strip it.
64 pbool keyword_nosave; //don't write the def to the output.
65 pbool keyword_union; //you surly know what a union is!
67 #define keyword_not 1 //hexenc support needs this, and fteqcc can optimise without it, but it adds an extra token after the if, so it can cause no namespace conflicts
69 pbool keywords_coexist; //don't disable a keyword simply because a var was made with the same name.
70 pbool output_parms; //emit some PARMX fields. confuses decompilers.
71 pbool autoprototype; //take two passes over the source code. First time round doesn't enter and functions or initialise variables.
72 pbool pr_subscopedlocals; //causes locals to be valid ONLY within their statement block. (they simply can't be referenced by name outside of it)
73 pbool flag_ifstring; //makes if (blah) equivelent to if (blah != "") which resolves some issues in multiprogs situations.
74 pbool flag_iffloat; //use an op_if_f instruction instead of op_if so if(-0) evaluates to false.
75 pbool flag_acc; //reacc like behaviour of src files (finds *.qc in start dir and compiles all in alphabetical order)
76 pbool flag_caseinsensative; //symbols will be matched to an insensative case if the specified case doesn't exist. This should b usable for any mod
77 pbool flag_laxcasts; //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code.
78 pbool flag_hashonly; //Allows use of only #constant for precompiler constants, allows certain preqcc using mods to compile
79 pbool flag_fasttrackarrays; //Faster arrays, dynamically detected, activated only in supporting engines.
80 pbool flag_msvcstyle; //MSVC style warnings, so msvc's ide works properly
81 pbool flag_assume_integer; //5 - is that an integer or a float? qcc says float. but we support int too, so maybe we want that instead?
83 pbool opt_overlaptemps; //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation)
84 pbool opt_assignments; //STORE_F isn't used if an operation wrote to a temp.
85 pbool opt_shortenifnots; //if(!var) is made an IF rather than NOT IFNOT
86 pbool opt_noduplicatestrings; //brute force string check. time consuming but more effective than the equivelent in frikqcc.
87 pbool opt_constantarithmatic; //3*5 appears as 15 instead of the extra statement.
88 pbool opt_nonvec_parms; //store_f instead of store_v on function calls, where possible.
89 pbool opt_constant_names; //take out the defs and name strings of constants.
90 pbool opt_constant_names_strings;//removes the defs of strings too. plays havok with multiprogs.
91 pbool opt_precache_file; //remove the call, the parameters, everything.
92 pbool opt_filenames; //strip filenames. hinders older decompilers.
93 pbool opt_unreferenced; //strip defs that are not referenced.
94 pbool opt_function_names; //strip out the names of builtin functions.
95 pbool opt_locals; //strip out the names of locals and immediates.
96 pbool opt_dupconstdefs; //float X = 5; and float Y = 5; occupy the same global with this.
97 pbool opt_return_only; //RETURN; DONE; at the end of a function strips out the done statement if there is no way to get to it.
98 pbool opt_compound_jumps; //jumps to jump statements jump to the final point.
99 pbool opt_stripfunctions; //if a functions is only ever called directly or by exe, don't emit the def.
100 pbool opt_locals_marshalling; //make the local vars of all functions occupy the same globals.
101 pbool opt_logicops; //don't make conditions enter functions if the return value will be discarded due to a previous value. (C style if statements)
102 pbool opt_vectorcalls; //vectors can be packed into 3 floats, which can yield lower numpr_globals, but cost two more statements per call (only works for q1 calling conventions).
103 pbool opt_simplifiedifs; //if (f != 0) -> if (f). if (f == 0) -> ifnot (f)
104 //bool opt_comexprremoval;
106 //these are the results of the opt_. The values are printed out when compilation is compleate, showing effectivness.
107 int optres_shortenifnots;
108 int optres_assignments;
109 int optres_overlaptemps;
110 int optres_noduplicatestrings;
111 int optres_constantarithmatic;
112 int optres_nonvec_parms;
113 int optres_constant_names;
114 int optres_constant_names_strings;
115 int optres_precache_file;
116 int optres_filenames;
117 int optres_unreferenced;
118 int optres_function_names;
120 int optres_dupconstdefs;
121 int optres_return_only;
122 int optres_compound_jumps;
123 //int optres_comexprremoval;
124 int optres_stripfunctions;
125 int optres_locals_marshalling;
131 void *(*pHash_Get)(hashtable_t *table, char *name);
132 void *(*pHash_GetNext)(hashtable_t *table, char *name, void *old);
133 void *(*pHash_Add)(hashtable_t *table, char *name, void *data, bucket_t *);
135 QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable, pbool saved);
136 QCC_type_t *QCC_PR_NewType (char *name, int basictype);
137 QCC_type_t *QCC_PR_FindType (QCC_type_t *type);
138 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto);
139 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto);
141 void QCC_PR_ParseState (void);
143 pbool expandedemptymacro;
146 //QCC_def_t **pr_global_defs/*[MAX_REGS]*/; // to find def for a global variable
148 //keeps track of how many funcs are called while parsing a statement
149 //int qcc_functioncalled;
151 //========================================
153 QCC_def_t *pr_scope; // the function being parsed, or NULL
154 QCC_type_t *pr_classtype;
156 QCC_string_t s_file, s_file2; // filename for function definition
158 unsigned int locals_start; // for tracking local variables vs temps
159 unsigned int locals_end; // for tracking local variables vs temps
161 jmp_buf pr_parse_abort; // longjump with this on parse error
163 void QCC_PR_ParseDefs (char *classname);
165 pbool qcc_usefulstatement;
176 QCC_def_t **pr_casesdef;
177 QCC_def_t **pr_casesdef2;
187 gotooperator_t *pr_labels;
188 gotooperator_t *pr_gotos;
192 QCC_def_t *extra_parms[MAX_EXTRA_PARMS];
194 #define ASSOC_RIGHT_RESULT ASSOC_RIGHT
196 //========================================
198 //FIXME: modifiy list so most common GROUPS are first
199 //use look up table for value of first char and sort by first char and most common...?
201 //if true, effectivly {b=a; return a;}
202 QCC_opcode_t pr_opcodes[] =
204 {6, "<DONE>", "DONE", -1, ASSOC_LEFT, &type_void, &type_void, &type_void},
206 {6, "*", "MUL_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
207 {6, "*", "MUL_V", 3, ASSOC_LEFT, &type_vector, &type_vector, &type_float},
208 {6, "*", "MUL_FV", 3, ASSOC_LEFT, &type_float, &type_vector, &type_vector},
209 {6, "*", "MUL_VF", 3, ASSOC_LEFT, &type_vector, &type_float, &type_vector},
211 {6, "/", "DIV_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
213 {6, "+", "ADD_F", 4, ASSOC_LEFT, &type_float, &type_float, &type_float},
214 {6, "+", "ADD_V", 4, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
216 {6, "-", "SUB_F", 4, ASSOC_LEFT, &type_float, &type_float, &type_float},
217 {6, "-", "SUB_V", 4, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
219 {6, "==", "EQ_F", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
220 {6, "==", "EQ_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_float},
221 {6, "==", "EQ_S", 5, ASSOC_LEFT, &type_string, &type_string, &type_float},
222 {6, "==", "EQ_E", 5, ASSOC_LEFT, &type_entity, &type_entity, &type_float},
223 {6, "==", "EQ_FNC", 5, ASSOC_LEFT, &type_function, &type_function, &type_float},
225 {6, "!=", "NE_F", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
226 {6, "!=", "NE_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_float},
227 {6, "!=", "NE_S", 5, ASSOC_LEFT, &type_string, &type_string, &type_float},
228 {6, "!=", "NE_E", 5, ASSOC_LEFT, &type_entity, &type_entity, &type_float},
229 {6, "!=", "NE_FNC", 5, ASSOC_LEFT, &type_function, &type_function, &type_float},
231 {6, "<=", "LE", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
232 {6, ">=", "GE", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
233 {6, "<", "LT", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
234 {6, ">", "GT", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
236 {6, ".", "INDIRECT_F", 1, ASSOC_LEFT, &type_entity, &type_field, &type_float},
237 {6, ".", "INDIRECT_V", 1, ASSOC_LEFT, &type_entity, &type_field, &type_vector},
238 {6, ".", "INDIRECT_S", 1, ASSOC_LEFT, &type_entity, &type_field, &type_string},
239 {6, ".", "INDIRECT_E", 1, ASSOC_LEFT, &type_entity, &type_field, &type_entity},
240 {6, ".", "INDIRECT_FI", 1, ASSOC_LEFT, &type_entity, &type_field, &type_field},
241 {6, ".", "INDIRECT_FU", 1, ASSOC_LEFT, &type_entity, &type_field, &type_function},
243 {6, ".", "ADDRESS", 1, ASSOC_LEFT, &type_entity, &type_field, &type_pointer},
245 {6, "=", "STORE_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float},
246 {6, "=", "STORE_V", 6, ASSOC_RIGHT, &type_vector, &type_vector, &type_vector},
247 {6, "=", "STORE_S", 6, ASSOC_RIGHT, &type_string, &type_string, &type_string},
248 {6, "=", "STORE_ENT", 6, ASSOC_RIGHT, &type_entity, &type_entity, &type_entity},
249 {6, "=", "STORE_FLD", 6, ASSOC_RIGHT, &type_field, &type_field, &type_field},
250 {6, "=", "STORE_FNC", 6, ASSOC_RIGHT, &type_function, &type_function, &type_function},
252 {6, "=", "STOREP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float},
253 {6, "=", "STOREP_V", 6, ASSOC_RIGHT, &type_pointer, &type_vector, &type_vector},
254 {6, "=", "STOREP_S", 6, ASSOC_RIGHT, &type_pointer, &type_string, &type_string},
255 {6, "=", "STOREP_ENT", 6, ASSOC_RIGHT, &type_pointer, &type_entity, &type_entity},
256 {6, "=", "STOREP_FLD", 6, ASSOC_RIGHT, &type_pointer, &type_field, &type_field},
257 {6, "=", "STOREP_FNC", 6, ASSOC_RIGHT, &type_pointer, &type_function, &type_function},
259 {6, "<RETURN>", "RETURN", -1, ASSOC_LEFT, &type_float, &type_void, &type_void},
261 {6, "!", "NOT_F", -1, ASSOC_LEFT, &type_float, &type_void, &type_float},
262 {6, "!", "NOT_V", -1, ASSOC_LEFT, &type_vector, &type_void, &type_float},
263 {6, "!", "NOT_S", -1, ASSOC_LEFT, &type_vector, &type_void, &type_float},
264 {6, "!", "NOT_ENT", -1, ASSOC_LEFT, &type_entity, &type_void, &type_float},
265 {6, "!", "NOT_FNC", -1, ASSOC_LEFT, &type_function, &type_void, &type_float},
267 {6, "<IF>", "IF", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
268 {6, "<IFNOT>", "IFNOT", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
270 // calls returns REG_RETURN
271 {6, "<CALL0>", "CALL0", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
272 {6, "<CALL1>", "CALL1", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
273 {6, "<CALL2>", "CALL2", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
274 {6, "<CALL3>", "CALL3", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
275 {6, "<CALL4>", "CALL4", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
276 {6, "<CALL5>", "CALL5", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
277 {6, "<CALL6>", "CALL6", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
278 {6, "<CALL7>", "CALL7", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
279 {6, "<CALL8>", "CALL8", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
281 {6, "<STATE>", "STATE", -1, ASSOC_LEFT, &type_float, &type_float, &type_void},
283 {6, "<GOTO>", "GOTO", -1, ASSOC_RIGHT, NULL, &type_void, &type_void},
285 {6, "&&", "AND", 7, ASSOC_LEFT, &type_float, &type_float, &type_float},
286 {6, "||", "OR", 7, ASSOC_LEFT, &type_float, &type_float, &type_float},
288 {6, "&", "BITAND", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
289 {6, "|", "BITOR", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
291 //version 6 are in normal progs.
296 {7, "*=", "MULSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
297 {7, "*=", "MULSTORE_V", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector},
298 {7, "*=", "MULSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
299 {7, "*=", "MULSTOREP_V", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector},
301 {7, "/=", "DIVSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
302 {7, "/=", "DIVSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
304 {7, "+=", "ADDSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
305 {7, "+=", "ADDSTORE_V", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector},
306 {7, "+=", "ADDSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
307 {7, "+=", "ADDSTOREP_V", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector},
309 {7, "-=", "SUBSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
310 {7, "-=", "SUBSTORE_V", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector},
311 {7, "-=", "SUBSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
312 {7, "-=", "SUBSTOREP_V", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector},
314 {7, "<FETCH_GBL_F>", "FETCH_GBL_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
315 {7, "<FETCH_GBL_V>", "FETCH_GBL_V", -1, ASSOC_LEFT, &type_vector, &type_float, &type_vector},
316 {7, "<FETCH_GBL_S>", "FETCH_GBL_S", -1, ASSOC_LEFT, &type_string, &type_float, &type_string},
317 {7, "<FETCH_GBL_E>", "FETCH_GBL_E", -1, ASSOC_LEFT, &type_entity, &type_float, &type_entity},
318 {7, "<FETCH_GBL_FNC>", "FETCH_GBL_FNC", -1, ASSOC_LEFT, &type_function, &type_float, &type_function},
320 {7, "<CSTATE>", "CSTATE", -1, ASSOC_LEFT, &type_float, &type_float, &type_void},
322 {7, "<CWSTATE>", "CWSTATE", -1, ASSOC_LEFT, &type_float, &type_float, &type_void},
324 {7, "<THINKTIME>", "THINKTIME", -1, ASSOC_LEFT, &type_entity, &type_float, &type_void},
326 {7, "|=", "BITSET_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float},
327 {7, "|=", "BITSETP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float},
328 {7, "&~=", "BITCLR_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float},
329 {7, "&~=", "BITCLRP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float},
331 {7, "<RAND0>", "RAND0", -1, ASSOC_LEFT, &type_void, &type_void, &type_float},
332 {7, "<RAND1>", "RAND1", -1, ASSOC_LEFT, &type_float, &type_void, &type_float},
333 {7, "<RAND2>", "RAND2", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
334 {7, "<RANDV0>", "RANDV0", -1, ASSOC_LEFT, &type_void, &type_void, &type_vector},
335 {7, "<RANDV1>", "RANDV1", -1, ASSOC_LEFT, &type_vector, &type_void, &type_vector},
336 {7, "<RANDV2>", "RANDV2", -1, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
338 {7, "<SWITCH_F>", "SWITCH_F", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
339 {7, "<SWITCH_V>", "SWITCH_V", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
340 {7, "<SWITCH_S>", "SWITCH_S", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
341 {7, "<SWITCH_E>", "SWITCH_E", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
342 {7, "<SWITCH_FNC>", "SWITCH_FNC", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
344 {7, "<CASE>", "CASE", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
345 {7, "<CASERANGE>", "CASERANGE", -1, ASSOC_LEFT, &type_void, &type_void, NULL},
348 //Later are additions by DMW.
350 {7, "<CALL1H>", "CALL1H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_void},
351 {7, "<CALL2H>", "CALL2H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
352 {7, "<CALL3H>", "CALL3H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
353 {7, "<CALL4H>", "CALL4H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
354 {7, "<CALL5H>", "CALL5H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
355 {7, "<CALL6H>", "CALL6H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
356 {7, "<CALL7H>", "CALL7H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
357 {7, "<CALL8H>", "CALL8H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
359 {7, "=", "STORE_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer},
360 {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_integer},
361 {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_float},
363 {7, "+", "ADD_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
364 {7, "+", "ADD_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float},
365 {7, "+", "ADD_IF", 4, ASSOC_LEFT, &type_integer, &type_float, &type_float},
367 {7, "-", "SUB_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
368 {7, "-", "SUB_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float},
369 {7, "-", "SUB_IF", 4, ASSOC_LEFT, &type_integer, &type_float, &type_float},
371 {7, "<CIF>", "C_ITOF", -1, ASSOC_LEFT, &type_integer, &type_void, &type_float},
372 {7, "<CFI>", "C_FTOI", -1, ASSOC_LEFT, &type_float, &type_void, &type_integer},
373 {7, "<CPIF>", "CP_ITOF", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_float},
374 {7, "<CPFI>", "CP_FTOI", -1, ASSOC_LEFT, &type_pointer, &type_float, &type_integer},
376 {7, ".", "INDIRECT", 1, ASSOC_LEFT, &type_entity, &type_field, &type_integer},
377 {7, "=", "STOREP_I", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer},
378 {7, "=", "STOREP_IF", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_integer},
379 {7, "=", "STOREP_FI", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_float},
381 {7, "&", "BITAND_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
382 {7, "|", "BITOR_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
384 {7, "*", "MUL_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
385 {7, "/", "DIV_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
386 {7, "==", "EQ_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
387 {7, "!=", "NE_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
389 {7, "<IFNOTS>", "IFNOTS", -1, ASSOC_RIGHT, &type_string, NULL, &type_void},
390 {7, "<IFS>", "IFS", -1, ASSOC_RIGHT, &type_string, NULL, &type_void},
392 {7, "!", "NOT_I", -1, ASSOC_LEFT, &type_integer, &type_void, &type_integer},
394 {7, "/", "DIV_VF", 3, ASSOC_LEFT, &type_vector, &type_float, &type_float},
396 {7, "^", "XOR_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
397 {7, ">>", "RSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
398 {7, "<<", "LSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
401 {7, "<ARRAY>", "GET_POINTER", -1, ASSOC_LEFT, &type_float, &type_integer, &type_pointer},
402 {7, "<ARRAY>", "ARRAY_OFS", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer},
404 {7, "=", "LOADA_F", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float},
405 {7, "=", "LOADA_V", 6, ASSOC_LEFT, &type_vector, &type_integer, &type_vector},
406 {7, "=", "LOADA_S", 6, ASSOC_LEFT, &type_string, &type_integer, &type_string},
407 {7, "=", "LOADA_ENT", 6, ASSOC_LEFT, &type_entity, &type_integer, &type_entity},
408 {7, "=", "LOADA_FLD", 6, ASSOC_LEFT, &type_field, &type_integer, &type_field},
409 {7, "=", "LOADA_FNC", 6, ASSOC_LEFT, &type_function, &type_integer, &type_function},
410 {7, "=", "LOADA_I", 6, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
412 {7, "=", "STORE_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void},
413 {7, ".", "INDIRECT_P", 1, ASSOC_LEFT, &type_entity, &type_field, &type_pointer},
415 {7, "=", "LOADP_F", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_float},
416 {7, "=", "LOADP_V", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_vector},
417 {7, "=", "LOADP_S", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_string},
418 {7, "=", "LOADP_ENT", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_entity},
419 {7, "=", "LOADP_FLD", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_field},
420 {7, "=", "LOADP_FNC", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_function},
421 {7, "=", "LOADP_I", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_integer},
424 {7, "<=", "LE_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
425 {7, ">=", "GE_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
426 {7, "<", "LT_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
427 {7, ">", "GT_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
429 {7, "<=", "LE_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
430 {7, ">=", "GE_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
431 {7, "<", "LT_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
432 {7, ">", "GT_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
434 {7, "<=", "LE_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
435 {7, ">=", "GE_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
436 {7, "<", "LT_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
437 {7, ">", "GT_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
439 {7, "==", "EQ_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
440 {7, "==", "EQ_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
442 //-------------------------------------
443 //string manipulation.
444 {7, "+", "ADD_SF", 4, ASSOC_LEFT, &type_string, &type_float, &type_string},
445 {7, "-", "SUB_S", 4, ASSOC_LEFT, &type_string, &type_string, &type_float},
446 {7, "<STOREP_C>", "STOREP_C", 1, ASSOC_RIGHT, &type_string, &type_float, &type_float},
447 {7, "<LOADP_C>", "LOADP_C", 1, ASSOC_LEFT, &type_string, &type_void, &type_float},
448 //-------------------------------------
452 {7, "*", "MUL_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
453 {7, "*", "MUL_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
454 {7, "*", "MUL_VI", 5, ASSOC_LEFT, &type_vector, &type_integer, &type_vector},
455 {7, "*", "MUL_IV", 5, ASSOC_LEFT, &type_integer, &type_vector, &type_vector},
457 {7, "/", "DIV_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
458 {7, "/", "DIV_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
460 {7, "&", "BITAND_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
461 {7, "|", "BITOR_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
462 {7, "&", "BITAND_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
463 {7, "|", "BITOR_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
465 {7, "&&", "AND_I", 7, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
466 {7, "||", "OR_I", 7, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
467 {7, "&&", "AND_IF", 7, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
468 {7, "||", "OR_IF", 7, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
469 {7, "&&", "AND_FI", 7, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
470 {7, "||", "OR_FI", 7, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
471 {7, "!=", "NE_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
472 {7, "!=", "NE_FI", 5, ASSOC_LEFT, &type_float, &type_float, &type_integer},
479 {7, "<>", "GSTOREP_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
480 {7, "<>", "GSTOREP_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
481 {7, "<>", "GSTOREP_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
482 {7, "<>", "GSTOREP_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
483 {7, "<>", "GSTOREP_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
484 {7, "<>", "GSTOREP_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
485 {7, "<>", "GSTOREP_V", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
487 {7, "<>", "GADDRESS", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
489 {7, "<>", "GLOAD_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
490 {7, "<>", "GLOAD_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
491 {7, "<>", "GLOAD_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
492 {7, "<>", "GLOAD_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
493 {7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
494 {7, "<>", "GLOAD_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
496 {7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
498 {7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void},
499 {7, "<PUSH>", "PUSH", -1, ASSOC_RIGHT, &type_float, &type_void, &type_pointer},
500 {7, "<POP>", "POP", -1, ASSOC_RIGHT, &type_float, &type_void, &type_void},
502 {7, "<SWITCH_I>", "SWITCH_I", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
503 {7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
505 {6, "<IF_F>", "IF_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
506 {6, "<IFNOT_F>","IFNOT_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
508 /* emulated ops begin here */
509 {7, "<>", "OP_EMULATED", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
512 {7, "|=", "BITSET_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer},
513 {7, "|=", "BITSETP_I", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer},
516 {7, "*=", "MULSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
517 {7, "/=", "DIVSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
518 {7, "+=", "ADDSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
519 {7, "-=", "SUBSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
521 {7, "*=", "MULSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
522 {7, "/=", "DIVSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
523 {7, "+=", "ADDSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
524 {7, "-=", "SUBSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
526 {7, "*=", "OP_MULSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
527 {7, "*=", "OP_MULSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
528 {7, "/=", "OP_DIVSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
529 {7, "/=", "OP_DIVSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
530 {7, "+=", "OP_ADDSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
531 {7, "+=", "OP_ADDSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
532 {7, "-=", "OP_SUBSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
533 {7, "-=", "OP_SUBSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer},
535 {7, "*=", "OP_MULSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
536 {7, "*=", "OP_MULSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
537 {7, "/=", "OP_DIVSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
538 {7, "/=", "OP_DIVSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
539 {7, "+=", "OP_ADDSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
540 {7, "+=", "OP_ADDSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
541 {7, "-=", "OP_SUBSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
542 {7, "-=", "OP_SUBSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float},
548 pbool OpAssignsToC(unsigned int op)
550 // calls, switches and cases DON'T
551 if(pr_opcodes[op].type_c == &type_void)
553 if(op >= OP_SWITCH_F && op <= OP_CALL8H)
555 if(op >= OP_RAND0 && op <= OP_RANDV2)
557 // they use a and b, but have 3 types
559 if(op >= OP_BITSET && op <= OP_BITCLRP)
561 /*if(op >= OP_STORE_I && op <= OP_STORE_FI)
562 return false; <- add STOREP_*?*/
563 if(op == OP_STOREP_C || op == OP_LOADP_C)
565 if(op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V)
569 pbool OpAssignsToB(unsigned int op)
571 if(op >= OP_BITSET && op <= OP_BITCLRP)
573 if(op >= OP_STORE_I && op <= OP_STORE_FI)
575 if(op == OP_STOREP_C || op == OP_LOADP_C)
577 if(op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V)
579 if(op >= OP_STORE_F && op <= OP_STOREP_FNC)
583 /*pbool OpAssignedTo(QCC_def_t *v, unsigned int op)
588 else if(OpAssignsToB(op))
594 #undef ASSOC_RIGHT_RESULT
596 #define TOP_PRIORITY 7
597 #define UNARY_PRIORITY 1
598 #define NOT_PRIORITY 5
600 #define CONDITION_PRIORITY 7
603 //this system cuts out 10/120
604 //these evaluate as top first.
605 QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
608 /* &pr_opcodes[OP_DONE],
609 &pr_opcodes[OP_RETURN],
611 &pr_opcodes[OP_NOT_F],
612 &pr_opcodes[OP_NOT_V],
613 &pr_opcodes[OP_NOT_S],
614 &pr_opcodes[OP_NOT_ENT],
615 &pr_opcodes[OP_NOT_FNC],
618 &pr_opcodes[OP_IFNOT],
619 &pr_opcodes[OP_CALL0],
620 &pr_opcodes[OP_CALL1],
621 &pr_opcodes[OP_CALL2],
622 &pr_opcodes[OP_CALL3],
623 &pr_opcodes[OP_CALL4],
624 &pr_opcodes[OP_CALL5],
625 &pr_opcodes[OP_CALL6],
626 &pr_opcodes[OP_CALL7],
627 &pr_opcodes[OP_CALL8],
628 &pr_opcodes[OP_STATE],
629 &pr_opcodes[OP_GOTO],
631 &pr_opcodes[OP_IFNOTS],
634 &pr_opcodes[OP_NOT_I],
638 &pr_opcodes[OP_LOAD_F],
639 &pr_opcodes[OP_LOAD_V],
640 &pr_opcodes[OP_LOAD_S],
641 &pr_opcodes[OP_LOAD_ENT],
642 &pr_opcodes[OP_LOAD_FLD],
643 &pr_opcodes[OP_LOAD_FNC],
644 &pr_opcodes[OP_LOAD_I],
645 &pr_opcodes[OP_LOAD_P],
646 &pr_opcodes[OP_ADDRESS],
649 /* //conversion. don't use
650 &pr_opcodes[OP_C_ITOF],
651 &pr_opcodes[OP_C_FTOI],
652 &pr_opcodes[OP_CP_ITOF],
653 &pr_opcodes[OP_CP_FTOI],
656 &pr_opcodes[OP_MUL_F],
657 &pr_opcodes[OP_MUL_V],
658 &pr_opcodes[OP_MUL_FV],
659 &pr_opcodes[OP_MUL_VF],
660 &pr_opcodes[OP_MUL_I],
662 &pr_opcodes[OP_DIV_F],
663 &pr_opcodes[OP_DIV_I],
664 &pr_opcodes[OP_DIV_VF],
666 &pr_opcodes[OP_BITAND],
667 &pr_opcodes[OP_BITAND_I],
668 &pr_opcodes[OP_BITAND_IF],
669 &pr_opcodes[OP_BITAND_FI],
671 &pr_opcodes[OP_BITOR],
672 &pr_opcodes[OP_BITOR_I],
673 &pr_opcodes[OP_BITOR_IF],
674 &pr_opcodes[OP_BITOR_FI],
676 &pr_opcodes[OP_XOR_I],
677 &pr_opcodes[OP_RSHIFT_I],
678 &pr_opcodes[OP_LSHIFT_I],
683 &pr_opcodes[OP_ADD_F],
684 &pr_opcodes[OP_ADD_V],
685 &pr_opcodes[OP_ADD_I],
686 &pr_opcodes[OP_ADD_FI],
687 &pr_opcodes[OP_ADD_IF],
688 &pr_opcodes[OP_ADD_SF],
690 &pr_opcodes[OP_SUB_F],
691 &pr_opcodes[OP_SUB_V],
692 &pr_opcodes[OP_SUB_I],
693 &pr_opcodes[OP_SUB_FI],
694 &pr_opcodes[OP_SUB_IF],
695 &pr_opcodes[OP_SUB_S],
699 &pr_opcodes[OP_EQ_F],
700 &pr_opcodes[OP_EQ_V],
701 &pr_opcodes[OP_EQ_S],
702 &pr_opcodes[OP_EQ_E],
703 &pr_opcodes[OP_EQ_FNC],
704 &pr_opcodes[OP_EQ_I],
705 &pr_opcodes[OP_EQ_IF],
706 &pr_opcodes[OP_EQ_FI],
708 &pr_opcodes[OP_NE_F],
709 &pr_opcodes[OP_NE_V],
710 &pr_opcodes[OP_NE_S],
711 &pr_opcodes[OP_NE_E],
712 &pr_opcodes[OP_NE_FNC],
713 &pr_opcodes[OP_NE_I],
714 &pr_opcodes[OP_NE_IF],
715 &pr_opcodes[OP_NE_FI],
718 &pr_opcodes[OP_LE_I],
719 &pr_opcodes[OP_LE_IF],
720 &pr_opcodes[OP_LE_FI],
722 &pr_opcodes[OP_GE_I],
723 &pr_opcodes[OP_GE_IF],
724 &pr_opcodes[OP_GE_FI],
726 &pr_opcodes[OP_LT_I],
727 &pr_opcodes[OP_LT_IF],
728 &pr_opcodes[OP_LT_FI],
730 &pr_opcodes[OP_GT_I],
731 &pr_opcodes[OP_GT_IF],
732 &pr_opcodes[OP_GT_FI],
736 &pr_opcodes[OP_STORE_F],
737 &pr_opcodes[OP_STORE_V],
738 &pr_opcodes[OP_STORE_S],
739 &pr_opcodes[OP_STORE_ENT],
740 &pr_opcodes[OP_STORE_FLD],
741 &pr_opcodes[OP_STORE_FNC],
742 &pr_opcodes[OP_STORE_I],
743 &pr_opcodes[OP_STORE_IF],
744 &pr_opcodes[OP_STORE_FI],
745 &pr_opcodes[OP_STORE_P],
747 &pr_opcodes[OP_STOREP_F],
748 &pr_opcodes[OP_STOREP_V],
749 &pr_opcodes[OP_STOREP_S],
750 &pr_opcodes[OP_STOREP_ENT],
751 &pr_opcodes[OP_STOREP_FLD],
752 &pr_opcodes[OP_STOREP_FNC],
753 &pr_opcodes[OP_STOREP_I],
754 &pr_opcodes[OP_STOREP_IF],
755 &pr_opcodes[OP_STOREP_FI],
756 &pr_opcodes[OP_STOREP_P],
758 &pr_opcodes[OP_DIVSTORE_F],
759 &pr_opcodes[OP_DIVSTORE_I],
760 &pr_opcodes[OP_DIVSTORE_FI],
761 &pr_opcodes[OP_DIVSTORE_IF],
762 &pr_opcodes[OP_DIVSTOREP_F],
763 &pr_opcodes[OP_DIVSTOREP_I],
764 &pr_opcodes[OP_DIVSTOREP_IF],
765 &pr_opcodes[OP_DIVSTOREP_FI],
766 &pr_opcodes[OP_MULSTORE_F],
767 &pr_opcodes[OP_MULSTORE_V],
768 &pr_opcodes[OP_MULSTORE_I],
769 &pr_opcodes[OP_MULSTORE_IF],
770 &pr_opcodes[OP_MULSTORE_FI],
771 &pr_opcodes[OP_MULSTOREP_F],
772 &pr_opcodes[OP_MULSTOREP_V],
773 &pr_opcodes[OP_MULSTOREP_I],
774 &pr_opcodes[OP_MULSTOREP_IF],
775 &pr_opcodes[OP_MULSTOREP_FI],
776 &pr_opcodes[OP_ADDSTORE_F],
777 &pr_opcodes[OP_ADDSTORE_V],
778 &pr_opcodes[OP_ADDSTORE_I],
779 &pr_opcodes[OP_ADDSTORE_IF],
780 &pr_opcodes[OP_ADDSTORE_FI],
781 &pr_opcodes[OP_ADDSTOREP_F],
782 &pr_opcodes[OP_ADDSTOREP_V],
783 &pr_opcodes[OP_ADDSTOREP_I],
784 &pr_opcodes[OP_ADDSTOREP_IF],
785 &pr_opcodes[OP_ADDSTOREP_FI],
786 &pr_opcodes[OP_SUBSTORE_F],
787 &pr_opcodes[OP_SUBSTORE_V],
788 &pr_opcodes[OP_SUBSTORE_I],
789 &pr_opcodes[OP_SUBSTORE_IF],
790 &pr_opcodes[OP_SUBSTORE_FI],
791 &pr_opcodes[OP_SUBSTOREP_F],
792 &pr_opcodes[OP_SUBSTOREP_V],
793 &pr_opcodes[OP_SUBSTOREP_I],
794 &pr_opcodes[OP_SUBSTOREP_IF],
795 &pr_opcodes[OP_SUBSTOREP_FI],
797 &pr_opcodes[OP_BITSET],
798 &pr_opcodes[OP_BITSET_I],
799 // &pr_opcodes[OP_BITSET_IF],
800 // &pr_opcodes[OP_BITSET_FI],
801 &pr_opcodes[OP_BITSETP],
802 &pr_opcodes[OP_BITSETP_I],
803 // &pr_opcodes[OP_BITSETP_IF],
804 // &pr_opcodes[OP_BITSETP_FI],
805 &pr_opcodes[OP_BITCLR],
806 &pr_opcodes[OP_BITCLRP],
811 &pr_opcodes[OP_AND_I],
812 &pr_opcodes[OP_AND_IF],
813 &pr_opcodes[OP_AND_FI],
815 &pr_opcodes[OP_OR_I],
816 &pr_opcodes[OP_OR_IF],
817 &pr_opcodes[OP_OR_FI],
822 pbool QCC_OPCodeValid(QCC_opcode_t *op)
825 num = op - pr_opcodes;
827 switch(qcc_targetformat)
831 if (num < OP_MULSTORE_F)
835 if (num >= OP_SWITCH_V && num <= OP_SWITCH_FNC) //these were assigned numbers but were never actually implemtented in standard h2.
837 // if (num >= OP_MULSTORE_F && num <= OP_SUBSTOREP_V)
839 if (num <= OP_CALL8H) //CALLXH are fixed up. This is to provide more dynamic switching...??
844 //no emulated opcodes
845 if (num >= OP_NUMREALOPS)
850 if (num < OP_MULSTORE_F)
853 //no emulated opcodes
854 if (num >= OP_NUMREALOPS)
858 //DPFIXME: this is a list of the extended opcodes. I was conservative regarding supported ones.
859 // at the time of writing, these are the ones that look like they'll work just fine in Blub\0's patch.
860 // the ones that looked too permissive with bounds checks, or would give false positives are disabled.
861 // if the DP guys want I can change them as desired.
864 //maths and conditionals (simple opcodes that read from specific globals and write to a global)
912 //stores into a pointer (generated from 'ent.field=XXX')
913 case OP_STOREP_I: //no worse than the other OP_STOREP_X functions
915 //reads from an entity field
916 case OP_LOAD_I: //no worse than the other OP_LOAD_X functions.
920 //stores into the globals array.
921 //they can change any global dynamically, but thats no security risk.
922 //fteqcc will not automatically generate these.
923 //fteqw does not support them either.
933 //this opcode looks weird
934 case OP_GADDRESS://floatc = globals[inta + floatb] (fte does not support)
937 //fteqcc will not automatically generate these
938 //fteqw does not support them either, for that matter.
939 case OP_GLOAD_I://c = globals[inta]
940 case OP_GLOAD_F://note: fte does not support these
947 return false; //DPFIXME: this is commented out in the patch I was given a link to... because the opcode wasn't defined.
949 //these are reportedly functional.
968 case OP_BITSET: // b |= a
969 case OP_BITCLR: // b &= ~a
970 case OP_BITSETP: // *b |= a
971 case OP_BITCLRP: // *b &= ~a
972 return false; //FIXME: I do not fully follow the controversy over these.
983 //assuming the pointers here are fine, the return values are a little strange.
987 case OP_ADDSTOREP_F: // e.f += f
988 case OP_ADDSTOREP_V: // e.v += v
991 case OP_SUBSTOREP_F: // e.f += f
992 case OP_SUBSTOREP_V: // e.v += v
1002 return false; //DPFIXME: DP does not bounds check these properly. I won't generate them.
1006 return true; //these look fine.
1008 case OP_STOREP_C: // store a char in a string
1009 return false; //DPFIXME: dp's bounds check may give false positives with expected uses.
1013 case OP_MULSTOREP_F:
1014 case OP_MULSTOREP_V: // e.v *= f
1016 case OP_DIVSTOREP_F:
1020 case OP_STOREP_IF: // store a value to a pointer
1026 case OP_IFNOT_F: //added, but not in dp yet
1032 return false; //DPFIXME: These are not bounds checked at all.
1033 case OP_GLOBALADDRESS:
1034 return true; //DPFIXME: DP will reject these pointers if they are ever used.
1035 case OP_POINTER_ADD:
1036 return true; //just maths.
1038 case OP_ADD_SF: //(char*)c = (char*)a + (float)b
1039 case OP_SUB_S: //(float)c = (char*)a - (char*)b
1041 case OP_LOADP_C: //load character from a string
1042 return false; //DPFIXME: DP looks like it'll reject these or wrongly allow.
1058 case OP_FETCH_GBL_F:
1059 case OP_FETCH_GBL_S:
1060 case OP_FETCH_GBL_E:
1061 case OP_FETCH_GBL_FNC:
1062 case OP_FETCH_GBL_V:
1063 return false; //DPFIXME: DP will not bounds check this properly, it is too permissive.
1066 return false; //DP does not support this hexenc opcode.
1068 return true; //but it does support this one.
1070 default: //anything I forgot to mention is new.
1077 #define EXPR_WARN_ABOVE_1 2
1078 #define EXPR_DISALLOW_COMMA 4
1079 QCC_def_t *QCC_PR_Expression (int priority, int exprflags);
1080 int QCC_AStatementJumpsTo(int targ, int first, int last);
1081 pbool QCC_StatementIsAJump(int stnum, int notifdest);
1083 temp_t *functemps; //floats/strings/funcs/ents...
1085 //===========================================================================
1092 Emits a primitive statement, returning the var it places it's value in
1095 QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement);
1096 static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted)
1098 if (var->type->type == ev_integer && wanted == ev_function)
1100 if (var->type->type == ev_pointer && var->type->aux_type)
1102 if (var->type->aux_type->type == ev_float && wanted == ev_integer)
1105 if (var->type->aux_type->type == ev_integer && wanted == ev_float)
1110 if (var->type->type == ev_float && wanted == ev_integer)
1111 return OP_CONV_FTOI;
1113 if (var->type->type == ev_integer && wanted == ev_float)
1114 return OP_CONV_ITOF;
1119 QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted)
1123 if (pr_classtype && var->type->type == ev_field && wanted != ev_field)
1126 { //load self.var into a temp
1128 self = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
1132 return QCC_PR_Statement(pr_opcodes+OP_LOAD_F, self, var, NULL);
1134 return QCC_PR_Statement(pr_opcodes+OP_LOAD_S, self, var, NULL);
1136 return QCC_PR_Statement(pr_opcodes+OP_LOAD_FNC, self, var, NULL);
1138 return QCC_PR_Statement(pr_opcodes+OP_LOAD_V, self, var, NULL);
1140 return QCC_PR_Statement(pr_opcodes+OP_LOAD_ENT, self, var, NULL);
1142 QCC_Error(ERR_INTERNAL, "Inexplicit field load failed, try explicit");
1147 o = QCC_ShouldConvert(var, wanted);
1149 if (o <= 0) //no conversion
1153 return QCC_PR_Statement(&pr_opcodes[o], var, NULL, NULL); //conversion return value
1155 QCC_def_t *QCC_MakeStringDef(char *value);
1156 QCC_def_t *QCC_MakeFloatDef(float value);
1157 QCC_def_t *QCC_MakeIntDef(int value);
1158 QCC_def_t *QCC_MakeVectorDef(float a, float b, float c);
1160 typedef struct freeoffset_s {
1161 struct freeoffset_s *next;
1166 freeoffset_t *freeofs;
1168 //assistant functions. This can safly be bipassed with the old method for more complex things.
1169 gofs_t QCC_GetFreeOffsetSpace(unsigned int size)
1172 if (opt_locals_marshalling)
1174 freeoffset_t *fofs, *prev;
1175 for (fofs = freeofs, prev = NULL; fofs; fofs=fofs->next)
1177 if (fofs->size == size)
1180 prev->next = fofs->next;
1182 freeofs = fofs->next;
1188 for (fofs = freeofs, prev = NULL; fofs; fofs=fofs->next)
1190 if (fofs->size > size)
1195 return fofs->ofs-size;
1201 ofs = numpr_globals;
1202 numpr_globals+=size;
1204 if (numpr_globals >= MAX_REGS)
1206 if (!opt_overlaptemps || !opt_locals_marshalling)
1207 QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS - you'll need to use more optimisations");
1209 QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS");
1215 void QCC_FreeOffset(gofs_t ofs, unsigned int size)
1218 if (ofs+size == numpr_globals)
1219 { //fixme: is this a bug?
1220 numpr_globals -= size;
1224 for (fofs = freeofs; fofs; fofs=fofs->next)
1226 //fixme: if this means the last block becomes free, free them all.
1227 if (fofs->ofs == ofs + size)
1233 if (fofs->ofs+fofs->size == ofs)
1240 fofs = qccHunkAlloc(sizeof(freeoffset_t));
1241 fofs->next = freeofs;
1249 static QCC_def_t *QCC_GetTemp(QCC_type_t *type)
1251 //#define CRAZYTEMPOPTS //not worth it. saves 2 temps with hexen2 (without even touching numpr_globals)
1254 #ifdef CRAZYTEMPOPTS
1255 temp_t *best = NULL;
1258 var_c = (void *)qccHunkAlloc (sizeof(QCC_def_t));
1259 memset (var_c, 0, sizeof(QCC_def_t));
1261 var_c->name = "temp";
1263 if (opt_overlaptemps) //don't exceed. This lets us allocate a huge block, and still be able to compile smegging big funcs.
1265 for (t = functemps; t; t = t->next)
1267 if (!t->used && t->size == type->size)
1269 #ifdef CRAZYTEMPOPTS
1271 if (t->scope == pr_scope)
1276 #ifdef CRAZYTEMPOPTS
1279 if (t && t->scope && t->scope != pr_scope)
1280 QCC_Error(ERR_INTERNAL, "Internal error temp has scope not equal to current scope");
1284 //allocate a new one
1285 t = qccHunkAlloc(sizeof(temp_t));
1286 t->size = type->size;
1287 t->next = functemps;
1290 t->ofs = QCC_GetFreeOffsetSpace(t->size);
1295 optres_overlaptemps+=t->size;
1296 //use a previous one.
1297 var_c->ofs = t->ofs;
1299 t->lastfunc = pr_scope;
1301 else if (opt_locals_marshalling)
1303 //allocate a new one
1304 t = qccHunkAlloc(sizeof(temp_t));
1305 t->size = type->size;
1307 t->next = functemps;
1310 t->ofs = QCC_GetFreeOffsetSpace(t->size);
1314 var_c->ofs = t->ofs;
1316 t->lastfunc = pr_scope;
1320 // we're not going to reallocate any temps so allocate permanently
1321 var_c->ofs = QCC_GetFreeOffsetSpace(type->size);
1322 numtemps+=type->size;
1325 var_c->s_file = s_file;
1326 var_c->s_line = pr_source_line;
1329 var_c->temp->used = true;
1334 //nothing else references this temp.
1335 static void QCC_FreeTemp(QCC_def_t *t)
1338 t->temp->used = false;
1341 static void QCC_UnFreeTemp(QCC_def_t *t)
1344 t->temp->used = true;
1347 //We've just parsed a statement.
1348 //We can gaurentee that any used temps are now not used.
1350 static void QCC_FreeTemps(void)
1354 if (def_ret.temp && def_ret.temp->used)
1356 QCC_PR_ParseWarning(WARN_DEBUGGING, "Return value still in use in %s", pr_scope->name);
1357 def_ret.temp->used = false;
1363 if (t->used && !pr_error_count) //don't print this after an error jump out.
1365 QCC_PR_ParseWarning(WARN_DEBUGGING, "Temp was used in %s", pr_scope->name);
1372 #define QCC_FreeTemps()
1375 //temps that are still in use over a function call can be considered dodgy.
1376 //we need to remap these to locally defined temps, on return from the function so we know we got them all.
1377 static void QCC_LockActiveTemps(void)
1385 t->scope = pr_scope;
1390 static void QCC_LockTemp(QCC_def_t *d)
1392 if (d->temp && d->temp->used)
1393 d->temp->scope = pr_scope;
1396 static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement)
1404 QCC_dstatement_t *st;
1408 for (i = firststatement, st = &statements[i]; i < laststatement; i++, st++)
1410 if (pr_opcodes[st->op].type_a && st->a == t->ofs)
1414 newofs = QCC_GetFreeOffsetSpace(t->size);
1417 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, false, false);
1418 def->nextlocal = pr.localvars;
1419 def->constant = false;
1421 sprintf(buffer, "locked_%i", t->ofs);
1422 def->name = qccHunkAlloc(strlen(buffer)+1);
1423 strcpy(def->name, buffer);
1429 if (pr_opcodes[st->op].type_b && st->b == t->ofs)
1433 newofs = QCC_GetFreeOffsetSpace(t->size);
1436 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, false, false);
1437 def->nextlocal = pr.localvars;
1438 def->constant = false;
1440 sprintf(buffer, "locked_%i", t->ofs);
1441 def->name = qccHunkAlloc(strlen(buffer)+1);
1442 strcpy(def->name, buffer);
1448 if (pr_opcodes[st->op].type_c && st->c == t->ofs)
1452 newofs = QCC_GetFreeOffsetSpace(t->size);
1455 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, false, false);
1456 def->nextlocal = pr.localvars;
1457 def->constant = false;
1459 sprintf(buffer, "locked_%i", t->ofs);
1460 def->name = qccHunkAlloc(strlen(buffer)+1);
1461 strcpy(def->name, buffer);
1470 static void QCC_RemapLockedTemps(int firststatement, int laststatement)
1477 if (t->scope || opt_locals_marshalling)
1479 QCC_RemapLockedTemp(t, firststatement, laststatement);
1487 static void QCC_fprintfLocals(FILE *f, gofs_t paramstart, gofs_t paramend)
1493 for (var = pr.localvars; var; var = var->nextlocal)
1495 if (var->ofs >= paramstart && var->ofs < paramend)
1497 fprintf(f, "local %s %s;\n", TypeName(var->type), var->name);
1500 for (t = functemps, i = 0; t; t = t->next, i++)
1502 if (t->lastfunc == pr_scope)
1504 fprintf(f, "local %s temp_%i;\n", (t->size == 1)?"float":"vector", i);
1510 void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t firstparm);
1511 static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size)
1513 static char message[1024];
1519 for (t = functemps, i = 0; t; t = t->next, i++)
1521 if (ofs >= t->ofs && ofs < t->ofs + t->size)
1524 sprintf(message, "temp_%i_%c", i, 'x' + (ofs-t->ofs)%3);
1526 sprintf(message, "temp_%i", i);
1531 for (var = pr.localvars; var; var = var->nextlocal)
1533 if (var->scope && var->scope != pr_scope)
1534 continue; //this should be an error
1535 if (ofs >= var->ofs && ofs < var->ofs + var->type->size)
1539 if (!STRCMP(var->name, "IMMEDIATE")) //continue, don't get bogged down by multiple bits of code
1541 if (size < var->type->size)
1542 sprintf(message, "%s_%c", var->name, 'x' + (ofs-var->ofs)%3);
1544 sprintf(message, "%s", var->name);
1550 for (var = pr.def_head.next; var; var = var->next)
1552 if (var->scope && var->scope != pr_scope)
1555 if (ofs >= var->ofs && ofs < var->ofs + var->type->size)
1559 if (!STRCMP(var->name, "IMMEDIATE"))
1561 switch(var->type->type)
1564 sprintf(message, "\"%.1020s\"", &strings[((int *)qcc_pr_globals)[var->ofs]]);
1567 sprintf(message, "%i", ((int *)qcc_pr_globals)[var->ofs]);
1570 sprintf(message, "%f", qcc_pr_globals[var->ofs]);
1573 sprintf(message, "'%f %f %f'", qcc_pr_globals[var->ofs], qcc_pr_globals[var->ofs+1], qcc_pr_globals[var->ofs+2]);
1576 sprintf(message, "IMMEDIATE");
1580 if (size < var->type->size)
1581 sprintf(message, "%s_%c", var->name, 'x' + (ofs-var->ofs)%3);
1583 sprintf(message, "%s", var->name);
1591 if (ofs >= OFS_RETURN && ofs < OFS_PARM0)
1592 sprintf(message, "return");
1593 else if (ofs >= OFS_PARM0 && ofs < RESERVED_OFS)
1594 sprintf(message, "parm%i", (ofs-OFS_PARM0)/3);
1596 sprintf(message, "offset_%i", ofs);
1600 if (ofs >= OFS_RETURN && ofs < OFS_PARM0)
1601 sprintf(message, "return_%c", 'x' + ofs-OFS_RETURN);
1602 else if (ofs >= OFS_PARM0 && ofs < RESERVED_OFS)
1603 sprintf(message, "parm%i_%c", (ofs-OFS_PARM0)/3, 'x' + (ofs-OFS_PARM0)%3);
1605 sprintf(message, "offset_%i", ofs);
1611 QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement)
1613 QCC_dstatement_t *statement;
1614 QCC_def_t *var_c=NULL, *temp=NULL;
1616 if (outstatement == (QCC_dstatement_t **)0xffffffff)
1617 outstatement = NULL;
1618 else if (op->priority != -1)
1620 if (op->associative!=ASSOC_LEFT)
1622 if (op->type_a == &type_pointer)
1623 var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type);
1625 var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type);
1630 var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type);
1632 var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type);
1633 // if (op->type_a == &def_pointer)
1634 // var_a = QCC_SupplyConversion(var_a, (*op->type_b)->type);
1636 // var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type);
1638 // //can't convert the left componant of an assignment operation
1639 // if (var_b && var_b->type && var_b->type != op->type_b->type)
1640 // var_b = QCC_SupplyConversion(var_b, op->type_b->type->type);
1646 var_a->references++;
1647 QCC_FreeTemp(var_a);
1651 var_b->references++;
1652 QCC_FreeTemp(var_b);
1655 if (keyword_class && var_a && var_b)
1657 if (var_a->type->type == ev_entity && var_b->type->type == ev_entity)
1658 if (var_a->type != var_b->type)
1659 if (strcmp(var_a->type->name, var_b->type->name))
1660 QCC_PR_ParseWarning(0, "Implicit cast from '%s' to '%s'", var_a->type->name, var_b->type->name);
1664 if (opt_constantarithmatic)
1666 if (var_a && var_a->constant)
1668 if (var_b && var_b->constant)
1670 //both are constants
1671 switch (op - pr_opcodes) //improve some of the maths.
1674 optres_constantarithmatic++;
1675 return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs)));
1677 optres_constantarithmatic++;
1678 return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
1680 optres_constantarithmatic++;
1681 return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs));
1683 optres_constantarithmatic++;
1684 return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs));
1686 optres_constantarithmatic++;
1687 return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs));
1689 optres_constantarithmatic++;
1690 return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs));
1693 optres_constantarithmatic++;
1694 return QCC_MakeIntDef(G_INT(var_a->ofs) | G_INT(var_b->ofs));
1696 optres_constantarithmatic++;
1697 return QCC_MakeIntDef(G_INT(var_a->ofs) & G_INT(var_b->ofs));
1699 optres_constantarithmatic++;
1700 return QCC_MakeIntDef(G_INT(var_a->ofs) * G_INT(var_b->ofs));
1702 optres_constantarithmatic++;
1703 return QCC_MakeIntDef(G_INT(var_a->ofs) / G_INT(var_b->ofs));
1705 optres_constantarithmatic++;
1706 return QCC_MakeIntDef(G_INT(var_a->ofs) + G_INT(var_b->ofs));
1708 optres_constantarithmatic++;
1709 return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs));
1712 optres_constantarithmatic++;
1713 return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs));
1715 optres_constantarithmatic++;
1716 return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs));
1717 case OP_MUL_V: //mul_f is actually a dot-product
1718 optres_constantarithmatic++;
1719 return QCC_MakeFloatDef( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) +
1720 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1) +
1721 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
1723 optres_constantarithmatic++;
1724 return QCC_MakeVectorDef( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0),
1725 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1),
1726 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
1728 optres_constantarithmatic++;
1729 return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs),
1730 G_FLOAT(var_a->ofs+1) * G_FLOAT(var_b->ofs),
1731 G_FLOAT(var_a->ofs+2) * G_FLOAT(var_b->ofs));
1733 optres_constantarithmatic++;
1734 return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0),
1735 G_FLOAT(var_a->ofs+1) + G_FLOAT(var_b->ofs+1),
1736 G_FLOAT(var_a->ofs+2) + G_FLOAT(var_b->ofs+2));
1738 optres_constantarithmatic++;
1739 return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0),
1740 G_FLOAT(var_a->ofs+1) - G_FLOAT(var_b->ofs+1),
1741 G_FLOAT(var_a->ofs+2) - G_FLOAT(var_b->ofs+2));
1746 //a is const, b is not
1747 switch (op - pr_opcodes)
1752 if (G_FLOAT(var_a->ofs) == 0)
1754 optres_constantarithmatic++;
1755 QCC_UnFreeTemp(var_b);
1760 if (G_FLOAT(var_a->ofs) == 1)
1762 optres_constantarithmatic++;
1763 QCC_UnFreeTemp(var_b);
1769 if (G_FLOAT(var_a->ofs) != 0)
1771 optres_constantarithmatic++;
1772 QCC_UnFreeTemp(var_b);
1780 if (G_INT(var_a->ofs) == 0)
1782 optres_constantarithmatic++;
1783 QCC_UnFreeTemp(var_b);
1788 if (G_INT(var_a->ofs) == 1)
1790 optres_constantarithmatic++;
1791 QCC_UnFreeTemp(var_b);
1797 if (G_INT(var_a->ofs) != 0)
1799 optres_constantarithmatic++;
1800 QCC_UnFreeTemp(var_b);
1807 else if (var_b && var_b->constant)
1809 //b is const, a is not
1810 switch (op - pr_opcodes)
1816 if (G_FLOAT(var_b->ofs) == 0)
1818 optres_constantarithmatic++;
1819 QCC_UnFreeTemp(var_a);
1825 if (G_FLOAT(var_b->ofs) == 1)
1827 optres_constantarithmatic++;
1828 QCC_UnFreeTemp(var_a);
1832 //no bitand_f, I don't trust the casts
1834 if (G_FLOAT(var_b->ofs) != 0)
1836 optres_constantarithmatic++;
1837 QCC_UnFreeTemp(var_a);
1846 if (G_INT(var_b->ofs) == 0)
1848 optres_constantarithmatic++;
1849 QCC_UnFreeTemp(var_a);
1855 if (G_INT(var_b->ofs) == 1)
1857 optres_constantarithmatic++;
1858 QCC_UnFreeTemp(var_a);
1863 if (G_INT(var_b->ofs) == 0xffffffff)
1865 optres_constantarithmatic++;
1866 QCC_UnFreeTemp(var_a);
1870 if (G_INT(var_b->ofs) != 0)
1872 optres_constantarithmatic++;
1873 QCC_UnFreeTemp(var_a);
1881 switch (op - pr_opcodes)
1884 if (var_a->ofs == var_b->ofs)
1885 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same");
1886 if (var_a->constant || var_b->constant)
1887 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
1890 if (var_a->ofs == var_b->ofs)
1891 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameters for || are the same");
1892 if (var_a->constant || var_b->constant)
1893 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
1899 // if (opt_shortenifnots)
1900 // if (var_b->constant && ((int*)qcc_pr_globals)[var_b->ofs]==0) // (a == 0) becomes (!a)
1901 // op = &pr_opcodes[(op - pr_opcodes) - OP_EQ_F + OP_NOT_F];
1914 if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs)
1915 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
1923 // if (var_a->type->type == ev_function && !var_a->temp)
1924 // QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
1925 if (var_a->constant && !var_a->temp)
1926 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
1933 { //optimise based on last statement.
1934 if (op - pr_opcodes == OP_IFNOT)
1936 if (opt_shortenifnots && var_a && (statements[numstatements-1].op == OP_NOT_F || statements[numstatements-1].op == OP_NOT_FNC || statements[numstatements-1].op == OP_NOT_ENT))
1938 if (statements[numstatements-1].c == var_a->ofs)
1940 static QCC_def_t nvara;
1941 if (statements[numstatements-1].op == OP_NOT_F)
1942 op = &pr_opcodes[OP_IF_F];
1944 op = &pr_opcodes[OP_IF];
1946 QCC_FreeTemp(var_a);
1947 memcpy(&nvara, var_a, sizeof(nvara));
1948 nvara.ofs = statements[numstatements].a;
1951 optres_shortenifnots++;
1955 else if (op - pr_opcodes == OP_IFNOT_F)
1957 if (opt_shortenifnots && var_a && statements[numstatements-1].op == OP_NOT_F)
1959 if (statements[numstatements-1].c == var_a->ofs)
1961 static QCC_def_t nvara;
1962 op = &pr_opcodes[OP_IF_F];
1964 QCC_FreeTemp(var_a);
1965 memcpy(&nvara, var_a, sizeof(nvara));
1966 nvara.ofs = statements[numstatements].a;
1969 optres_shortenifnots++;
1973 else if (op - pr_opcodes == OP_IFNOT_S)
1975 if (opt_shortenifnots && var_a && statements[numstatements-1].op == OP_NOT_S)
1977 if (statements[numstatements-1].c == var_a->ofs)
1979 static QCC_def_t nvara;
1980 op = &pr_opcodes[OP_IF_S];
1982 QCC_FreeTemp(var_a);
1983 memcpy(&nvara, var_a, sizeof(nvara));
1984 nvara.ofs = statements[numstatements].a;
1987 optres_shortenifnots++;
1991 else if (((unsigned) ((op - pr_opcodes) - OP_STORE_F) < 6) || (op-pr_opcodes) == OP_STORE_P)
1993 // remove assignments if what should be assigned is the 3rd operand of the previous statement?
1994 // don't if it's a call, callH, switch or case
1995 // && var_a->ofs >RESERVED_OFS)
1996 if (OpAssignsToC(statements[numstatements-1].op) &&
1997 opt_assignments && var_a && var_a->ofs == statements[numstatements-1].c)
1999 if (var_a->type->type == var_b->type->type)
2003 statement = &statements[numstatements-1];
2004 statement->c = var_b->ofs;
2006 if (var_a->type->type != var_b->type->type)
2007 QCC_PR_ParseWarning(0, "store type mismatch");
2008 var_b->references++;
2009 var_a->references--;
2010 QCC_FreeTemp(var_a);
2011 optres_assignments++;
2015 QCC_UnFreeTemp(var_b);
2024 statement = &statements[numstatements];
2027 if (!QCC_OPCodeValid(op))
2029 switch(op - pr_opcodes)
2032 var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false);
2034 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
2035 statement = &statements[numstatements];
2038 QCC_FreeTemp(var_a);
2039 op = &pr_opcodes[OP_IF];
2043 var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false);
2045 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
2046 statement = &statements[numstatements];
2049 QCC_FreeTemp(var_a);
2050 op = &pr_opcodes[OP_IFNOT];
2054 var_c = QCC_MakeFloatDef(0);
2056 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
2057 statement = &statements[numstatements];
2060 QCC_FreeTemp(var_a);
2061 op = &pr_opcodes[OP_IF];
2065 var_c = QCC_MakeFloatDef(0);
2067 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
2068 statement = &statements[numstatements];
2071 QCC_FreeTemp(var_a);
2072 op = &pr_opcodes[OP_IFNOT];
2076 op = &pr_opcodes[OP_ADD_F];
2082 case OP_ADDSTORE_FI:
2083 op = &pr_opcodes[OP_ADD_FI];
2089 case OP_ADDSTORE_IF:
2090 op = &pr_opcodes[OP_ADD_IF];
2098 op = &pr_opcodes[OP_SUB_F];
2104 case OP_SUBSTORE_FI:
2105 op = &pr_opcodes[OP_SUB_FI];
2111 case OP_SUBSTORE_IF:
2112 op = &pr_opcodes[OP_SUB_IF];
2120 op = &pr_opcodes[OP_DIV_F];
2126 case OP_DIVSTORE_FI:
2127 op = &pr_opcodes[OP_DIV_FI];
2133 case OP_DIVSTORE_IF:
2134 op = &pr_opcodes[OP_DIV_IF];
2142 op = &pr_opcodes[OP_MUL_F];
2148 case OP_MULSTORE_IF:
2149 op = &pr_opcodes[OP_MUL_IF];
2155 case OP_MULSTORE_FI:
2156 op = &pr_opcodes[OP_MUL_FI];
2164 op = &pr_opcodes[OP_ADD_V];
2172 op = &pr_opcodes[OP_SUB_V];
2180 op = &pr_opcodes[OP_MUL_VF];
2188 op = &pr_opcodes[OP_BITOR_I];
2195 op = &pr_opcodes[OP_BITOR];
2203 //b = var, a = bit field.
2205 QCC_UnFreeTemp(var_a);
2206 QCC_UnFreeTemp(var_b);
2209 var_c = QCC_PR_Statement(&pr_opcodes[OP_BITAND], var_b, var_a, NULL);
2210 QCC_FreeTemp(var_c);
2211 statement = &statements[numstatements];
2214 QCC_FreeTemp(var_a);
2215 QCC_FreeTemp(var_b);
2217 op = &pr_opcodes[OP_SUB_F];
2223 case OP_SUBSTOREP_FI:
2224 case OP_SUBSTOREP_IF:
2225 case OP_ADDSTOREP_FI:
2226 case OP_ADDSTOREP_IF:
2227 case OP_MULSTOREP_FI:
2228 case OP_MULSTOREP_IF:
2229 case OP_DIVSTOREP_FI:
2230 case OP_DIVSTOREP_IF:
2233 case OP_SUBSTOREP_F:
2234 case OP_ADDSTOREP_F:
2235 case OP_MULSTOREP_F:
2236 case OP_DIVSTOREP_F:
2240 // QCC_PR_ParseWarning(0, "XSTOREP_F emulation is still experimental");
2241 QCC_UnFreeTemp(var_a);
2242 QCC_UnFreeTemp(var_b);
2243 //don't chain these... this expansion is not the same.
2246 int need_lock = false;
2247 for (st = numstatements-2; st>=0; st--)
2249 if (statements[st].op == OP_ADDRESS)
2250 if (statements[st].c == var_b->ofs)
2253 if (statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8 || statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H)
2256 //printf("%s\n", pr_opcodes[statements[st].op].opname);
2258 if (statements[st].c == var_b->ofs)
2259 QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name);
2262 QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_F: pointer was not generated from previous statement");
2263 var_c = QCC_GetTemp(*op->type_c);
2265 QCC_LockTemp(var_c); // this will cause the temp to be remapped by QCC_RemapLockedTemps
2267 statement_linenums[statement-statements] = statement_linenums[st];
2268 statement->op = OP_ADDRESS;
2269 statement->a = statements[st].a;
2270 statement->b = statements[st].b;
2271 statement->c = statements[st].c;
2273 statement_linenums[st] = pr_source_line;
2274 statements[st].op = OP_LOAD_F;
2275 statements[st].a = statements[st].a;
2276 statements[st].b = statements[st].b;
2277 statements[st].c = var_c->ofs;
2280 statement = &statements[numstatements];
2283 statement_linenums[statement-statements] = pr_source_line;
2284 switch(op - pr_opcodes)
2286 case OP_SUBSTOREP_F:
2287 statement->op = OP_SUB_F;
2289 case OP_SUBSTOREP_IF:
2290 statement->op = OP_SUB_IF;
2292 case OP_SUBSTOREP_FI:
2293 statement->op = OP_SUB_FI;
2295 case OP_ADDSTOREP_IF:
2296 statement->op = OP_ADD_IF;
2298 case OP_ADDSTOREP_FI:
2299 statement->op = OP_ADD_FI;
2301 case OP_MULSTOREP_IF:
2302 statement->op = OP_MUL_IF;
2304 case OP_MULSTOREP_FI:
2305 statement->op = OP_MUL_FI;
2307 case OP_DIVSTOREP_IF:
2308 statement->op = OP_DIV_IF;
2310 case OP_DIVSTOREP_FI:
2311 statement->op = OP_DIV_FI;
2313 case OP_ADDSTOREP_F:
2314 statement->op = OP_ADD_F;
2316 case OP_MULSTOREP_F:
2317 statement->op = OP_MUL_F;
2319 case OP_DIVSTOREP_F:
2320 statement->op = OP_DIV_F;
2323 statement->op = OP_BITOR;
2326 statement->op = OP_BITOR_I;
2329 //float pointer float
2330 temp = QCC_GetTemp(type_float);
2331 statement->op = OP_BITAND;
2332 statement->a = var_c ? var_c->ofs : 0;
2333 statement->b = var_a ? var_a->ofs : 0;
2334 statement->c = temp->ofs;
2336 statement = &statements[numstatements];
2339 statement_linenums[statement-statements] = pr_source_line;
2340 statement->op = OP_SUB_F;
2345 default: //no way will this be hit...
2346 QCC_PR_ParseError(ERR_INTERNAL, "opcode invalid 3 times %i", op - pr_opcodes);
2348 if (op - pr_opcodes == OP_BITCLRP)
2350 statement->a = var_c ? var_c->ofs : 0;
2351 statement->b = temp ? temp->ofs : 0;
2352 statement->c = var_c->ofs;
2354 var_b = var_b; //this is the ptr.
2355 QCC_FreeTemp(var_a);
2356 var_a = var_c; //this is the value.
2360 statement->a = var_c ? var_c->ofs : 0;
2361 statement->b = var_a ? var_a->ofs : 0;
2362 statement->c = var_c->ofs;
2363 var_b = var_b; //this is the ptr.
2364 QCC_FreeTemp(var_a);
2365 var_a = var_c; //this is the value.
2368 op = &pr_opcodes[OP_STOREP_F];
2369 QCC_FreeTemp(var_c);
2372 QCC_FreeTemp(var_b);
2374 statement = &statements[numstatements];
2378 case OP_MULSTOREP_V:
2379 case OP_SUBSTOREP_V:
2380 case OP_ADDSTOREP_V:
2381 // QCC_PR_ParseWarning(0, "XSTOREP_V emulation is still experimental");
2382 QCC_UnFreeTemp(var_a);
2383 QCC_UnFreeTemp(var_b);
2384 //don't chain these... this expansion is not the same.
2387 int need_lock = false;
2388 for (st = numstatements-2; st>=0; st--)
2390 if (statements[st].op == OP_ADDRESS)
2391 if (statements[st].c == var_b->ofs)
2394 if (statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8 || statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H)
2397 if (statements[st].c == var_b->ofs)
2398 QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name);
2401 QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_V couldn't find pointer generation");
2402 var_c = QCC_GetTemp(*op->type_c);
2404 QCC_LockTemp(var_c); // this will cause the temp to be remapped by QCC_RemapLockedTemps
2406 statement_linenums[statement-statements] = statement_linenums[st];
2407 statement->op = OP_ADDRESS;
2408 statement->a = statements[st].a;
2409 statement->b = statements[st].b;
2410 statement->c = statements[st].c;
2412 statement_linenums[st] = pr_source_line;
2413 statements[st].op = OP_LOAD_V;
2414 statements[st].a = statements[st].a;
2415 statements[st].b = statements[st].b;
2416 statements[st].c = var_c->ofs;
2419 statement = &statements[numstatements];
2422 statement_linenums[statement-statements] = pr_source_line;
2423 switch(op - pr_opcodes)
2425 case OP_SUBSTOREP_V:
2426 statement->op = OP_SUB_V;
2428 case OP_ADDSTOREP_V:
2429 statement->op = OP_ADD_V;
2431 case OP_MULSTOREP_V:
2432 statement->op = OP_MUL_VF;
2434 default: //no way will this be hit...
2435 QCC_PR_ParseError(ERR_INTERNAL, "opcode invalid 3 times %i", op - pr_opcodes);
2437 statement->a = var_a ? var_a->ofs : 0;
2438 statement->b = var_c ? var_c->ofs : 0;
2439 QCC_FreeTemp(var_c);
2440 var_c = QCC_GetTemp(*op->type_c);
2441 statement->c = var_c ? var_c->ofs : 0;
2443 var_b = var_b; //this is the ptr.
2444 QCC_FreeTemp(var_a);
2445 var_a = var_c; //this is the value.
2446 op = &pr_opcodes[OP_STOREP_V];
2451 QCC_FreeTemp(var_c);
2453 QCC_FreeTemp(var_b);
2455 statement = &statements[numstatements];
2459 QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target", op->name, op->opname);
2465 *outstatement = statement;
2467 statement_linenums[statement-statements] = pr_source_line;
2468 statement->op = op - pr_opcodes;
2469 statement->a = var_a ? var_a->ofs : 0;
2470 statement->b = var_b ? var_b->ofs : 0;
2473 statement->c = var_c->ofs;
2475 else if (op->type_c == &type_void || op->associative==ASSOC_RIGHT || op->type_c == NULL)
2478 statement->c = 0; // ifs, gotos, and assignments
2479 // don't need vars allocated
2482 { // allocate result space
2483 var_c = QCC_GetTemp(*op->type_c);
2484 statement->c = var_c->ofs;
2485 if (op->type_b == &type_field)
2487 var_c->name = var_b->name;
2488 var_c->s_file = var_b->s_file;
2489 var_c->s_line = var_b->s_line;
2493 if ((op - pr_opcodes >= OP_LOAD_F && op - pr_opcodes <= OP_LOAD_FNC) ||
2494 op - pr_opcodes == OP_LOAD_I)
2496 if (var_b->constant == 2)
2497 var_c->constant = true;
2503 QCC_UnFreeTemp(var_a);
2511 QCC_PR_SimpleStatement
2513 Emits a primitive statement, returning the var it places it's value in
2516 QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force)
2518 QCC_dstatement_t *statement;
2520 if (!force && !QCC_OPCodeValid(pr_opcodes+op))
2522 QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target\n", pr_opcodes[op].name, pr_opcodes[op].opname);
2525 statement_linenums[numstatements] = pr_source_line;
2526 statement = &statements[numstatements];
2530 statement->a = var_a;
2531 statement->b = var_b;
2532 statement->c = var_c;
2536 void QCC_PR_Statement3 ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_def_t *var_c, int force)
2538 QCC_dstatement_t *statement;
2540 if (!force && !QCC_OPCodeValid(op))
2542 // outputversion = op->extension;
2543 // if (noextensions)
2544 QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target\n", op->name, op->opname);
2547 statement = &statements[numstatements];
2550 statement_linenums[statement-statements] = pr_source_line;
2551 statement->op = op - pr_opcodes;
2552 statement->a = var_a ? var_a->ofs : 0;
2553 statement->b = var_b ? var_b->ofs : 0;
2554 statement->c = var_c ? var_c->ofs : 0;
2561 Looks for a preexisting constant
2564 QCC_def_t *QCC_PR_ParseImmediate (void)
2568 if (pr_immediate_type == type_float)
2570 cn = QCC_MakeFloatDef(pr_immediate._float);
2574 if (pr_immediate_type == type_integer)
2576 cn = QCC_MakeIntDef(pr_immediate._int);
2581 if (pr_immediate_type == type_string)
2583 cn = QCC_MakeStringDef(pr_immediate_string);
2588 // check for a constant with the same value
2589 for (cn=pr.def_head.next ; cn ; cn=cn->next) //FIXME - hashtable.
2591 if (!cn->initialized)
2595 if (cn->type != pr_immediate_type)
2597 if (pr_immediate_type == type_string)
2599 if (!STRCMP(G_STRING(cn->ofs), pr_immediate_string) )
2605 else if (pr_immediate_type == type_float)
2607 if ( G_FLOAT(cn->ofs) == pr_immediate._float )
2613 else if (pr_immediate_type == type_integer)
2615 if ( G_INT(cn->ofs) == pr_immediate._int )
2621 else if (pr_immediate_type == type_vector)
2623 if ( ( G_FLOAT(cn->ofs) == pr_immediate.vector[0] )
2624 && ( G_FLOAT(cn->ofs+1) == pr_immediate.vector[1] )
2625 && ( G_FLOAT(cn->ofs+2) == pr_immediate.vector[2] ) )
2632 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "weird immediate type");
2635 // allocate a new one
2636 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
2638 pr.def_tail->next = cn;
2641 cn->type = pr_immediate_type;
2642 cn->name = "IMMEDIATE";
2643 cn->constant = true;
2644 cn->initialized = 1;
2645 cn->scope = NULL; // always share immediates
2647 // copy the immediate to the global area
2648 cn->ofs = QCC_GetFreeOffsetSpace(type_size[pr_immediate_type->type]);
2650 if (pr_immediate_type == type_string)
2651 pr_immediate.string = QCC_CopyString (pr_immediate_string);
2653 memcpy (qcc_pr_globals + cn->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
2661 void QCC_PrecacheSound (QCC_def_t *e, int ch)
2666 if (e->type->type != ev_string)
2669 if (!e->ofs || e->temp || !e->constant)
2671 n = G_STRING(e->ofs);
2674 for (i=0 ; i<numsounds ; i++)
2675 if (!STRCMP(n, precache_sounds[i]))
2677 if (numsounds == MAX_SOUNDS)
2679 // QCC_Error ("PrecacheSound: numsounds == MAX_SOUNDS");
2680 strcpy (precache_sounds[i], n);
2681 if (ch >= '1' && ch <= '9')
2682 precache_sounds_block[i] = ch - '0';
2684 precache_sounds_block[i] = 1;
2688 void QCC_PrecacheModel (QCC_def_t *e, int ch)
2693 if (e->type->type != ev_string)
2696 if (!e->ofs || e->temp || !e->constant)
2698 n = G_STRING(e->ofs);
2701 for (i=0 ; i<nummodels ; i++)
2702 if (!STRCMP(n, precache_models[i]))
2704 if (!precache_models_block[i])
2706 if (ch >= '1' && ch <= '9')
2707 precache_models_block[i] = ch - '0';
2709 precache_models_block[i] = 1;
2713 if (nummodels == MAX_MODELS)
2715 // QCC_Error ("PrecacheModels: nummodels == MAX_MODELS");
2716 strcpy (precache_models[i], n);
2717 if (ch >= '1' && ch <= '9')
2718 precache_models_block[i] = ch - '0';
2720 precache_models_block[i] = 1;
2724 void QCC_SetModel (QCC_def_t *e)
2729 if (e->type->type != ev_string)
2732 if (!e->ofs || e->temp || !e->constant)
2734 n = G_STRING(e->ofs);
2737 for (i=0 ; i<nummodels ; i++)
2738 if (!STRCMP(n, precache_models[i]))
2740 precache_models_used[i]++;
2743 if (nummodels == MAX_MODELS)
2745 strcpy (precache_models[i], n);
2746 precache_models_block[i] = 0;
2747 precache_models_used[i]=1;
2751 void QCC_PrecacheTexture (QCC_def_t *e, int ch)
2756 if (e->type->type != ev_string)
2759 if (!e->ofs || e->temp || !e->constant)
2761 n = G_STRING(e->ofs);
2764 for (i=0 ; i<numtextures ; i++)
2765 if (!STRCMP(n, precache_textures[i]))
2767 if (nummodels == MAX_MODELS)
2769 // QCC_Error ("PrecacheTextures: numtextures == MAX_TEXTURES");
2770 strcpy (precache_textures[i], n);
2771 if (ch >= '1' && ch <= '9')
2772 precache_textures_block[i] = ch - '0';
2774 precache_textures_block[i] = 1;
2778 void QCC_PrecacheFile (QCC_def_t *e, int ch)
2783 if (e->type->type != ev_string)
2786 if (!e->ofs || e->temp || !e->constant)
2788 n = G_STRING(e->ofs);
2791 for (i=0 ; i<numfiles ; i++)
2792 if (!STRCMP(n, precache_files[i]))
2794 if (numfiles == MAX_FILES)
2796 // QCC_Error ("PrecacheFile: numfiles == MAX_FILES");
2797 strcpy (precache_files[i], n);
2798 if (ch >= '1' && ch <= '9')
2799 precache_files_block[i] = ch - '0';
2801 precache_files_block[i] = 1;
2805 void QCC_PrecacheFileOptimised (char *n, int ch)
2809 for (i=0 ; i<numfiles ; i++)
2810 if (!STRCMP(n, precache_files[i]))
2812 if (numfiles == MAX_FILES)
2814 // QCC_Error ("PrecacheFile: numfiles == MAX_FILES");
2815 strcpy (precache_files[i], n);
2816 if (ch >= '1' && ch <= '9')
2817 precache_files_block[i] = ch - '0';
2819 precache_files_block[i] = 1;
2823 QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], int argcount) //warning, the func could have no name set if it's a field call.
2825 QCC_def_t *d, *oldret, *oself;
2828 int extraparms=false;
2830 int laststatement = numstatements;
2833 QCC_dstatement_t *st;
2836 func->timescalled++;
2838 if (QCC_OPCodeValid(&pr_opcodes[OP_CALL1H]))
2839 callconvention = OP_CALL1H; //FTE extended
2841 callconvention = OP_CALL1; //standard
2845 if (t->type == ev_variant)
2847 t->aux_type = type_variant;
2850 if (t->type != ev_function && t->type != ev_variant)
2852 QCC_PR_ParseErrorPrintDef (ERR_NOTAFUNCTION, func, "not a function");
2855 // copy the arguments to the global parameter variables
2856 if (t->type == ev_variant)
2861 else if (t->num_parms < 0)
2864 np = (t->num_parms * -1) - 1;
2869 if (strchr(func->name, ':') && laststatement && statements[laststatement-1].op == OP_LOAD_FNC && statements[laststatement-1].c == func->ofs)
2870 { //we're entering OO code with a different self.
2871 //eg: other.touch(self)
2873 //FIXME: problems could occur with hexen2 calling conventions when parm0/1 is 'self'
2874 //thiscall. copy the right ent into 'self' (if it's not the same offset)
2875 d = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
2876 if (statements[laststatement-1].a != d->ofs)
2878 oself = QCC_GetTemp(type_entity);
2880 QCC_PR_SimpleStatement(OP_STORE_ENT, d->ofs, oself->ofs, 0, false);
2882 QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement-1].a, d->ofs, 0, false);
2884 //if the args refered to self, update them to refer to oself instead
2885 //(as self is now set to 'other')
2886 for (i = 0; i < argcount; i++)
2888 if (arglist[i]->ofs == d->ofs)
2896 //it was self.func() anyway
2902 { //regular func call
2907 // write the arguments (except for first two if hexenc)
2908 for (i = 0; i < argcount; i++)
2911 d = extra_parms[i - MAX_PARMS];
2915 if (callconvention == OP_CALL1H)
2918 //first two args are passed in the call opcode, so don't need to be copied
2919 arglist[i]->references++;
2921 QCC_FreeTemp(arglist[i]);
2925 if (arglist[i]->type->size>1 || !opt_nonvec_parms)
2926 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], arglist[i], d, (QCC_dstatement_t **)0xffffffff));
2929 d->type = arglist[i]->type;
2930 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], arglist[i], d, (QCC_dstatement_t **)0xffffffff));
2931 optres_nonvec_parms++;
2935 //if the return value was in use, save it off now, so that it doesn't get clobbered
2936 if (def_ret.temp->used)
2938 oldret = QCC_GetTemp(def_ret.type);
2939 if (def_ret.type->size == 3)
2940 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, NULL));
2942 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, NULL));
2943 QCC_UnFreeTemp(oldret);
2944 QCC_UnFreeTemp(&def_ret);
2945 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
2950 //we dont need to lock the local containing the function index because its thrown away after the call anyway
2951 //(if a function is called in the argument list then it'll be locked as part of that call)
2953 QCC_LockActiveTemps(); //any temps before are likly to be used with the return value.
2954 QCC_UnFreeTemp(func);
2957 if (argcount>MAX_PARMS)
2958 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+MAX_PARMS], func, 0, (QCC_dstatement_t **)&st));
2960 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+argcount], func, 0, (QCC_dstatement_t **)&st));
2962 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CALL0], func, 0, (QCC_dstatement_t **)&st));
2964 if (callconvention == OP_CALL1H)
2968 st->b = arglist[0]->ofs;
2969 // QCC_FreeTemp(param[0]);
2972 st->c = arglist[1]->ofs;
2973 // QCC_FreeTemp(param[1]);
2978 //restore the class owner
2980 QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false);
2982 for(; argcount; argcount--)
2984 QCC_FreeTemp(arglist[argcount-1]);
2989 // Make sure our def_ret backup temp wasn't freed above
2990 QCC_UnFreeTemp(oldret); //this bug fix was brought to you by Blub, the character \ and the number 0.
2993 //if we preserved the ofs_ret global, restore it here
2994 if (t->type == ev_variant)
2996 d = QCC_GetTemp(type_variant);
2997 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
3001 d = QCC_GetTemp(t->aux_type);
3002 if (t->aux_type->size == 3)
3003 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL));
3005 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
3007 if (def_ret.type->size == 3)
3008 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, NULL));
3010 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, NULL));
3011 QCC_FreeTemp(oldret);
3012 QCC_UnFreeTemp(&def_ret);
3018 if (t->type == ev_variant)
3019 def_ret.type = type_variant;
3021 def_ret.type = t->aux_type;
3022 if (def_ret.temp->used)
3023 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3024 def_ret.temp->used = true;
3031 PR_ParseFunctionCall
3034 QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could have no name set if it's a field call.
3036 QCC_def_t *e, *d, *old, *oself, *out;
3039 int extraparms=false;
3041 int laststatement = numstatements;
3045 QCC_def_t *param[MAX_PARMS+MAX_EXTRA_PARMS];
3047 func->timescalled++;
3049 if (QCC_OPCodeValid(&pr_opcodes[OP_CALL1H]))
3050 callconvention = OP_CALL1H; //FTE extended
3052 callconvention = OP_CALL1; //standard
3056 if (t->type == ev_variant)
3058 t->aux_type = type_variant;
3061 if (t->type != ev_function && t->type != ev_variant)
3063 QCC_PR_ParseErrorPrintDef (ERR_NOTAFUNCTION, func, "not a function");
3066 if (!t->num_parms&&t->type != ev_variant) //intrinsics. These base functions have variable arguments. I would check for (...) args too, but that might be used for extended builtin functionality. (this code wouldn't compile otherwise)
3068 if (!strcmp(func->name, "random"))
3072 if (!QCC_PR_CheckToken(")"))
3074 e = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3075 if (e->type->type != ev_float)
3076 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 1);
3077 if (!QCC_PR_CheckToken(")"))
3080 d = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3081 if (d->type->type != ev_float)
3082 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 2);
3094 if (QCC_OPCodeValid(&pr_opcodes[OP_RAND0]))
3096 if(def_ret.temp->used)
3097 out = QCC_GetTemp(type_float);
3104 QCC_PR_SimpleStatement(OP_RAND2, e->ofs, d->ofs, out->ofs, false);
3106 QCC_PR_SimpleStatement(OP_RAND1, e->ofs, 0, out->ofs, false);
3109 QCC_PR_SimpleStatement(OP_RAND0, 0, 0, out->ofs, false);
3113 if (def_ret.temp->used)
3115 old = QCC_GetTemp(def_ret.type);
3116 if (def_ret.type->size == 3)
3117 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL));
3119 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL));
3120 QCC_UnFreeTemp(old);
3121 QCC_UnFreeTemp(&def_ret);
3122 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3131 QCC_dstatement_t *st;
3133 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3135 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3137 t = QCC_PR_Statement(&pr_opcodes[OP_GT], d, e, NULL);
3138 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], t, 0, &st));
3141 t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], d, e, NULL);
3142 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3144 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3146 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_GOTO], 0, 0, &st));
3150 t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], e, d, NULL);
3151 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3153 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs, OFS_RETURN, false);
3157 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3158 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3162 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3178 d = QCC_GetTemp(type_float);
3179 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
3180 if (def_ret.type->size == 3)
3181 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, old, &def_ret, NULL));
3183 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL));
3186 QCC_UnFreeTemp(&def_ret);
3191 if (def_ret.temp->used)
3192 QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
3193 def_ret.temp->used = true;
3194 def_ret.type = type_float;
3198 if (!strcmp(func->name, "randomv"))
3202 if (!QCC_PR_CheckToken(")"))
3204 e = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3205 if (e->type->type != ev_vector)
3206 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 1);
3207 if (!QCC_PR_CheckToken(")"))
3210 d = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3211 if (d->type->type != ev_vector)
3212 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 2);
3224 if (QCC_OPCodeValid(&pr_opcodes[OP_RANDV0]))
3226 if(def_ret.temp->used)
3227 out = QCC_GetTemp(type_vector);
3234 QCC_PR_SimpleStatement(OP_RANDV2, e->ofs, d->ofs, out->ofs, false);
3236 QCC_PR_SimpleStatement(OP_RANDV1, e->ofs, 0, out->ofs, false);
3239 QCC_PR_SimpleStatement(OP_RANDV0, 0, 0, out->ofs, false);
3243 if (def_ret.temp->used)
3245 old = QCC_GetTemp(def_ret.type);
3246 if (def_ret.type->size == 3)
3247 QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL);
3249 QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL);
3250 QCC_UnFreeTemp(old);
3251 QCC_UnFreeTemp(&def_ret);
3252 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3262 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3264 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3266 t = QCC_GetTemp(type_float);
3267 QCC_PR_SimpleStatement(OP_GT, d->ofs+2, e->ofs+2, t->ofs, false);
3268 QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false);
3270 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+2, e->ofs+2, t->ofs, false);
3271 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+2, false);
3273 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs+2, OFS_RETURN+2, false);
3275 QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
3278 t = QCC_GetTemp(type_float);
3279 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+2, e->ofs+2, t->ofs, false);
3280 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+2, false);
3282 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs+2, OFS_RETURN+2, false);
3286 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3288 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3290 t = QCC_GetTemp(type_float);
3291 QCC_PR_SimpleStatement(OP_GT, d->ofs+1, e->ofs+1, t->ofs, false);
3292 QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false);
3294 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+1, e->ofs+1, t->ofs, false);
3295 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+1, false);
3297 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs+1, OFS_RETURN+1, false);
3299 QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
3302 t = QCC_GetTemp(type_float);
3303 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+1, e->ofs+1, t->ofs, false);
3304 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+1, false);
3306 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs+1, OFS_RETURN+1, false);
3309 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3311 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3313 t = QCC_GetTemp(type_float);
3314 QCC_PR_SimpleStatement(OP_GT, d->ofs, e->ofs, t->ofs, false);
3315 QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false);
3317 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs, e->ofs, t->ofs, false);
3318 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3320 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3322 QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
3325 t = QCC_GetTemp(type_float);
3326 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs, e->ofs, t->ofs, false);
3327 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3329 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs, OFS_RETURN, false);
3333 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3334 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN+2, false);
3335 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3336 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN+1, false);
3337 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3338 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3343 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3344 QCC_PR_SimpleStatement(OP_STORE_F, OFS_RETURN, OFS_RETURN+2, 0, false);
3345 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3346 QCC_PR_SimpleStatement(OP_STORE_F, OFS_RETURN, OFS_RETURN+1, 0, false);
3347 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3365 d = QCC_GetTemp(type_vector);
3366 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL));
3367 if (def_ret.type->size == 3)
3369 QCC_PR_Statement(pr_opcodes+OP_STORE_V, old, &def_ret, NULL);
3373 QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL);
3377 QCC_UnFreeTemp(&def_ret);
3382 if (def_ret.temp->used)
3383 QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
3384 def_ret.temp->used = true;
3385 def_ret.type = type_vector;
3388 else if (!strcmp(func->name, "spawn"))
3390 QCC_type_t *rettype;
3391 if (QCC_PR_CheckToken(")"))
3393 rettype = type_entity;
3397 rettype = QCC_TypeForName(QCC_PR_ParseName());
3398 if (!rettype || rettype->type != ev_entity)
3399 QCC_PR_ParseError(ERR_NOTANAME, "Spawn operator with undefined class");
3405 if (def_ret.temp->used)
3407 old = QCC_GetTemp(def_ret.type);
3408 if (def_ret.type->size == 3)
3409 QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL);
3411 QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL);
3412 QCC_UnFreeTemp(old);
3413 QCC_UnFreeTemp(&def_ret);
3414 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3419 if (def_ret.temp->used)
3420 QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
3421 def_ret.temp->used = true;
3424 if (rettype != type_entity)
3427 sprintf(genfunc, "Class*%s", rettype->name);
3428 func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 1, false);
3431 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3435 d = QCC_GetTemp(rettype);
3436 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_ENT, &def_ret, d, NULL));
3437 if (def_ret.type->size == 3)
3438 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, old, &def_ret, NULL));
3440 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL));
3443 QCC_UnFreeTemp(&def_ret);
3448 def_ret.type = rettype;
3451 else if (!strcmp(func->name, "entnum") && !QCC_PR_CheckToken(")"))
3453 //t = (a/%1) / (nextent(world)/%1)
3454 //a/%1 does a (int)entity to float conversion type thing
3455 func->initialized = 1;
3457 e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3459 e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff);
3461 d = QCC_PR_GetDef(NULL, "nextent", NULL, false, 0, false);
3463 QCC_PR_ParseError(0, "the nextent builtin is not defined");
3464 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], e, &def_parms[0], (QCC_dstatement_t **)0xffffffff));
3465 d = QCC_PR_Statement(&pr_opcodes[OP_CALL0], d, NULL, NULL);
3466 d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff);
3468 e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, d, (QCC_dstatement_t **)0xffffffff);
3472 else if (!strcmp(func->name, "_") && !QCC_PR_CheckToken(")"))
3474 // return string as is, but set the dotranslate flag
3476 e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3481 } //so it's not an intrinsic.
3483 if (opt_precache_file) //should we strip out all precache_file calls?
3485 if (!strncmp(func->name,"precache_file", 13))
3487 if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string)
3489 optres_precache_file += strlen(pr_immediate_string);
3492 QCC_PrecacheFileOptimised (pr_immediate_string, func->name[13]);
3493 def_ret.type = type_void;
3499 // copy the arguments to the global parameter variables
3501 if (t->type == ev_variant)
3506 else if (t->num_parms < 0)
3509 np = (t->num_parms * -1) - 1;
3514 //any temps referenced to build the parameters don't need to be locked.
3515 if (!QCC_PR_CheckToken(")"))
3520 if (extraparms && arg >= MAX_PARMS)
3521 QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS);
3522 else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS)
3523 QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS);
3524 if (!extraparms && arg >= t->num_parms)
3526 QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters");
3527 QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func);
3531 //with vectorcalls, we store the vector into the args as individual floats
3532 //this allows better reuse of vector constants.
3533 //copy it into the offset now, because we can.
3534 if (opt_vectorcalls && pr_token_type == tt_immediate && pr_immediate_type == type_vector && arg < MAX_PARMS && !def_parms[arg].temp->used)
3536 e = &def_parms[arg];
3538 e->ofs = OFS_PARM0+0;
3539 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff));
3540 e->ofs = OFS_PARM0+1;
3541 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff));
3542 e->ofs = OFS_PARM0+2;
3543 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff));
3549 e = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3551 if (arg == 0 && func->name)
3553 // save information for model and sound caching
3554 if (!strncmp(func->name,"precache_", 9))
3556 if (!strncmp(func->name+9,"sound", 5))
3557 QCC_PrecacheSound (e, func->name[14]);
3558 else if (!strncmp(func->name+9,"model", 5))
3559 QCC_PrecacheModel (e, func->name[14]);
3560 else if (!strncmp(func->name+9,"texture", 7))
3561 QCC_PrecacheTexture (e, func->name[16]);
3562 else if (!strncmp(func->name+9,"file", 4))
3563 QCC_PrecacheFile (e, func->name[13]);
3569 if (!extra_parms[arg - MAX_PARMS])
3571 d = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t));
3572 d->name = "extra parm";
3573 d->ofs = QCC_GetFreeOffsetSpace (3);
3574 extra_parms[arg - MAX_PARMS] = d;
3576 d = extra_parms[arg - MAX_PARMS];
3579 d = &def_parms[arg];
3581 if (pr_classtype && e->type->type == ev_field && p->type != ev_field)
3583 oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false);
3584 switch(e->type->aux_type->type)
3587 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_S, oself, e, NULL);
3590 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_I, oself, e, NULL);
3593 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_F, oself, e, NULL);
3596 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_FNC, oself, e, NULL);
3599 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_V, oself, e, NULL);
3602 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_ENT, oself, e, NULL);
3605 QCC_Error(ERR_INTERNAL, "Bad member type. Try forced expansion");
3611 if (typecmp(e->type, p))
3612 /*if (e->type->type != ev_integer && p->type != ev_function)
3613 if (e->type->type != ev_function && p->type != ev_integer)
3614 if ( e->type->type != p->type )*/
3616 if (p->type == ev_integer && e->type->type == ev_float) //convert float -> int... is this a constant?
3617 e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL);
3618 else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant?
3619 e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL);
3620 else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
3621 { //you're allowed to use int 0 to pass a null function pointer
3622 //this is basically because __NULL__ is defined as ~0 (int 0)
3624 else if (p->type != ev_variant) //can cast to variant whatever happens
3626 if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function))
3628 QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
3629 QCC_PR_ParsePrintDef(WARN_LAXCAST, func);
3632 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
3640 // a vector copy will copy everything
3642 d->type = type_void;
3644 if (arg == 1 && !STRCMP(func->name, "setmodel"))
3650 /* if (e->type->size>1)
3651 QCC_PR_Statement (&pr_opcodes[OP_STORE_V], e, d, (QCC_dstatement_t **)0xffffffff);
3653 QCC_PR_Statement (&pr_opcodes[OP_STORE_F], e, d, (QCC_dstatement_t **)0xffffffff);
3656 } while (QCC_PR_CheckToken (","));
3658 if (t->num_parms != -1 && arg < np)
3659 QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "too few parameters on call to %s", func->name);
3660 QCC_PR_Expect (")");
3664 QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "%s: Too few parameters", func->name);
3665 QCC_PR_ParsePrintDef (WARN_TOOFEWPARAMS, func);
3668 return QCC_PR_GenerateFunctionCall(func, param, arg);
3674 QCC_def_t *QCC_MakeIntDef(int value)
3678 // check for a constant with the same value
3679 for (cn=pr.def_head.next ; cn ; cn=cn->next)
3682 if (!cn->initialized)
3687 if (cn->type != type_integer)
3691 if ( G_INT(cn->ofs) == value )
3697 // allocate a new one
3698 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3700 pr.def_tail->next = cn;
3703 cn->type = type_integer;
3704 cn->name = "IMMEDIATE";
3705 cn->constant = true;
3706 cn->initialized = 1;
3707 cn->scope = NULL; // always share immediates
3710 // copy the immediate to the global area
3711 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
3713 G_INT(cn->ofs) = value;
3719 QCC_def_t *QCC_MakeVectorDef(float a, float b, float c)
3723 // check for a constant with the same value
3724 for (cn=pr.def_head.next ; cn ; cn=cn->next)
3727 if (!cn->initialized)
3732 if (cn->type != type_vector)
3736 if ( G_FLOAT(cn->ofs+0) == a &&
3737 G_FLOAT(cn->ofs+1) == b &&
3738 G_FLOAT(cn->ofs+2) == c)
3744 // allocate a new one
3745 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3747 pr.def_tail->next = cn;
3750 cn->type = type_vector;
3751 cn->name = "IMMEDIATE";
3752 cn->constant = true;
3753 cn->initialized = 1;
3754 cn->scope = NULL; // always share immediates
3757 // copy the immediate to the global area
3758 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_vector->type]);
3760 G_FLOAT(cn->ofs+0) = a;
3761 G_FLOAT(cn->ofs+1) = b;
3762 G_FLOAT(cn->ofs+2) = c;
3767 hashtable_t floatconstdefstable;
3768 QCC_def_t *QCC_MakeFloatDef(float value)
3779 cn = Hash_GetKey(&floatconstdefstable, fi.i);
3783 // allocate a new one
3784 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3786 pr.def_tail->next = cn;
3789 cn->s_file = s_file;
3790 cn->s_line = pr_source_line;
3791 cn->type = type_float;
3792 cn->name = "IMMEDIATE";
3793 cn->constant = true;
3794 cn->initialized = 1;
3795 cn->scope = NULL; // always share immediates
3798 // copy the immediate to the global area
3799 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
3801 Hash_AddKey(&floatconstdefstable, fi.i, cn, qccHunkAlloc(sizeof(bucket_t)));
3803 G_FLOAT(cn->ofs) = value;
3809 extern hashtable_t stringconstdefstable;
3810 extern hashtable_t stringconstdefstable_dotranslate;
3811 QCC_def_t *QCC_MakeStringDef(char *value)
3815 hashtable_t *tbl = dotranslate ? &stringconstdefstable_dotranslate : &stringconstdefstable;
3818 cn = pHash_Get(tbl, value);
3822 // allocate a new one
3823 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3825 pr.def_tail->next = cn;
3828 cn->type = type_string;
3831 sprintf(buf, "dotranslate_%d", ++dotranslate_count);
3832 cn->name = strdup(buf);
3835 cn->name = "IMMEDIATE";
3836 cn->constant = true;
3837 cn->initialized = 1;
3838 cn->scope = NULL; // always share immediates
3841 // copy the immediate to the global area
3842 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
3844 string = QCC_CopyString (value);
3846 pHash_Add(tbl, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
3848 G_INT(cn->ofs) = string;
3854 QCC_type_t *QCC_PR_NewType (char *name, int basictype);
3855 QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type)
3857 QCC_type_t *newtype;
3858 newtype = QCC_PR_NewType("POINTER TYPE", ev_pointer);
3859 newtype->aux_type = type;
3863 int basictypefield[ev_union+1];
3864 char *basictypenames[] = {
3878 QCC_def_t *QCC_MemberInParentClass(char *name, QCC_type_t *clas)
3879 { //if a member exists, return the member field (rather than mapped-to field)
3883 char membername[2048];
3887 def = QCC_PR_GetDef(NULL, name, NULL, 0, 0, false);
3888 if (def && def->type->type == ev_field) //the member existed as a normal entity field.
3893 np = clas->num_parms;
3894 for (p = 0, mt = clas->param; p < np; p++, mt = mt->next)
3896 if (strcmp(mt->name, name))
3899 //the parent has it.
3901 sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, mt->name);
3902 def = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false);
3906 return QCC_MemberInParentClass(name, clas->parentclass);
3909 //create fields for the types, instanciate the members to the fields.
3910 //we retouch the parents each time to guarentee polymorphism works.
3911 //FIXME: virtual methods will not work properly. Need to trace down to see if a parent already defined it
3912 void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas)
3914 //we created fields for each class when we defined the actual classes.
3915 //we need to go through each member and match it to the offset of it's parent class, if overloaded, or create a new field if not..
3917 //basictypefield is cleared before we do this
3918 //we emit the parent's fields first (every time), thus ensuring that we don't reuse parent fields on a child class.
3920 char membername[2048];
3923 QCC_type_t *mt, *ft;
3925 if (clas->parentclass != type_entity) //parents MUST have all their fields set or inheritance would go crazy.
3926 QCC_PR_EmitFieldsForMembers(clas->parentclass);
3928 np = clas->num_parms;
3930 for (p = 0; p < np; p++, mt = mt->next)
3932 sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, mt->name);
3933 m = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false);
3935 f = QCC_MemberInParentClass(mt->name, clas->parentclass);
3939 QCC_Error(ERR_INTERNAL, "FTEQCC does not support overloaded arrays of members");
3941 for (o = 0; o < m->type->size; o++)
3942 ((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs];
3946 for (a = 0; a < m->arraysize; a++)
3948 //we need the type in here so saved games can still work without saving ints as floats. (would be evil)
3949 ft = QCC_PR_NewType(basictypenames[mt->type], ev_field);
3950 ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type);
3951 ft->aux_type->aux_type = type_void;
3952 ft->size = ft->aux_type->size;
3953 ft = QCC_PR_FindType(ft);
3954 sprintf(membername, "__f_%s_%i", ft->name, ++basictypefield[mt->type]);
3955 f = QCC_PR_GetDef(ft, membername, NULL, true, 1, true);
3957 for (o = 0; o < m->type->size; o++)
3958 ((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs];
3965 void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_def_t *ed, QCC_def_t **constructor)
3966 { //go through clas, do the virtual thing only if the child class does not override.
3968 char membername[2048];
3973 QCC_def_t *point, *member;
3976 if (clas->parentclass)
3977 QCC_PR_EmitClassFunctionTable(clas->parentclass, childclas, ed, constructor);
3980 for (p = 0; p < clas->num_parms; p++, type = type->next)
3982 for (oc = childclas; oc != clas; oc = oc->parentclass)
3984 sprintf(membername, "%s::"MEMBERFIELDNAME, oc->name, type->name);
3985 if (QCC_PR_GetDef(NULL, membername, NULL, false, 0, false))
3986 break; //a child class overrides.
3991 if (type->type == ev_function) //FIXME: inheritance will not install all the member functions.
3993 sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, type->name);
3994 member = QCC_PR_GetDef(NULL, membername, NULL, false, 1, false);
3997 QCC_PR_Warning(0, NULL, 0, "Member function %s was not defined", membername);
4000 if (!strcmp(type->name, clas->name))
4002 *constructor = member;
4004 point = QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], ed, member, NULL);
4005 sprintf(membername, "%s::%s", clas->name, type->name);
4006 virt = QCC_PR_GetDef(type, membername, NULL, false, 1, false);
4007 QCC_PR_Statement(&pr_opcodes[OP_STOREP_FNC], virt, point, NULL);
4012 //take all functions in the type, and parent types, and make sure the links all work properly.
4013 void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname)
4015 QCC_type_t *basetype;
4017 QCC_dfunction_t *df;
4020 QCC_def_t *ed, *oself, *self;
4021 QCC_def_t *constructor = NULL;
4025 basetype = QCC_TypeForName(tname);
4027 QCC_PR_ParseError(ERR_INTERNAL, "Type %s was not defined...", tname);
4031 memset(basictypefield, 0, sizeof(basictypefield));
4032 QCC_PR_EmitFieldsForMembers(basetype);
4039 df = &functions[numfunctions];
4044 df->first_statement = numstatements;
4045 df->parm_size[0] = 1;
4047 df->parm_start = numpr_globals;
4049 G_FUNCTION(scope->ofs) = df - functions;
4052 ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 1, false);
4054 virt = QCC_PR_GetDef(type_function, "spawn", NULL, false, 0, false);
4056 QCC_Error(ERR_INTERNAL, "spawn function was not defined\n");
4057 QCC_PR_SimpleStatement(OP_CALL0, virt->ofs, 0, 0, false); //calling convention doesn't come into it.
4059 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], &def_ret, ed, NULL));
4061 ed->references = 1; //there may be no functions.
4064 QCC_PR_EmitClassFunctionTable(basetype, basetype, ed, &constructor);
4068 self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false);
4069 oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 1, false);
4070 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], self, oself, NULL));
4071 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], ed, self, NULL)); //return to our old self. boom boom.
4072 QCC_PR_SimpleStatement(OP_CALL0, constructor->ofs, 0, 0, false);
4073 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], oself, self, NULL));
4076 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_RETURN], ed, NULL, NULL)); //apparently we do actually have to return something. *sigh*...
4077 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_DONE], NULL, NULL, NULL));
4081 QCC_WriteAsmFunction(scope, df->first_statement, df->parm_start);
4082 pr.localvars = NULL;
4085 locals_end = numpr_globals + basetype->size;
4086 df->locals = locals_end - df->parm_start;
4092 Returns the global ofs for the current token
4095 QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign)
4097 QCC_def_t *ao=NULL; //arrayoffset
4098 QCC_def_t *d, *nd, *od;
4100 QCC_dstatement_t *st;
4102 static QCC_def_t intrinsic = {
4103 NULL, // QCC_type_t *type;
4104 NULL, // char *name;
4105 NULL, // struct QCC_def_s *next;
4106 NULL, // struct QCC_def_s *nextlocal; //provides a chain of local variables for the opt_locals_marshalling optimisation.
4108 NULL, // struct QCC_def_s *scope; // function the var was defined in, or NULL
4109 1, // int initialized; // 1 when a declaration included "= immediate"
4110 1, // int constant; // 1 says we can use the value over and over again
4111 1, // int references;
4112 0, // int timescalled; //part of the opt_stripfunctions optimisation.
4115 0, // int arraysize;
4118 0, // pbool isstatic;
4119 NULL // temp_t *temp;
4122 char membername[2048];
4124 // if the token is an immediate, allocate a constant for it
4125 if (pr_token_type == tt_immediate)
4126 return QCC_PR_ParseImmediate ();
4128 if (QCC_PR_CheckToken("[")) //reacc support
4129 { //looks like a funky vector. :)
4131 pr_immediate_type = type_vector;
4132 v[0] = pr_immediate._float;
4134 v[1] = pr_immediate._float;
4136 v[2] = pr_immediate._float;
4137 pr_immediate.vector[0] = v[0];
4138 pr_immediate.vector[1] = v[1];
4139 pr_immediate.vector[2] = v[2];
4140 pr_immediate_type = type_vector;
4141 d = QCC_PR_ParseImmediate();
4145 name = QCC_PR_ParseName ();
4147 if (assumeclass && assumeclass->parentclass) // 'testvar' becomes 'self::testvar'
4148 { //try getting a member.
4152 while(type != type_entity && type)
4154 sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name);
4155 od = d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false);
4159 type = type->parentclass;
4162 od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
4166 // look through the defs
4167 od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
4171 if ( (!strcmp(name, "random" )) ||
4172 (!strcmp(name, "randomv")) ||
4173 (!strcmp(name, "entnum")) ||
4174 (!strcmp(name, "_")) ) //intrinsics, any old function with no args will do.
4176 intrinsic.name = name;
4177 intrinsic.type = type_function; // can't put that in the static var
4178 od = d = &intrinsic;
4180 else if (keyword_class && !strcmp(name, "this"))
4183 QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n");
4184 od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false);
4185 od = d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 1, od->ofs, true, false);
4187 else if (keyword_class && !strcmp(name, "super"))
4190 QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n");
4191 od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false);
4192 od = d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 1, od->ofs, true, false);
4196 od = d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 1, false);
4198 QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
4201 QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name);
4209 //FIXME: Make this work with double arrays/2nd level structures.
4210 //Should they just jump back to here?
4211 if (QCC_PR_CheckToken("["))
4213 QCC_type_t *newtype;
4216 numstatements--; //remove the last statement
4218 nd = QCC_PR_Expression (TOP_PRIORITY, 0);
4221 if (d->type->size != 1) //we need to multiply it to find the offset.
4223 if (ao->type->type == ev_integer)
4224 nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], nd, QCC_MakeIntDef(d->type->size), NULL); //get add part
4225 else if (ao->type->type == ev_float)
4226 nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], nd, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part
4229 QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
4234 if (nd->type->type == ao->type->type)
4236 if (ao->type->type == ev_integer)
4237 ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
4238 else if (ao->type->type == ev_float)
4239 ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], ao, nd, NULL); //get add part
4242 QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
4248 if (nd->type->type == ev_float)
4249 nd = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], nd, 0, NULL);
4250 ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
4258 ao = QCC_PR_Expression (TOP_PRIORITY, 0);
4261 if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]) && d->type->size != 1) //we need to multiply it to find the offset.
4263 if (ao->type->type == ev_integer)
4264 ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], ao, QCC_MakeIntDef(d->type->size), NULL); //get add part
4265 else if (ao->type->type == ev_float)
4266 ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], ao, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part
4270 QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
4276 if (ao->type->type == ev_integer)
4278 switch(newtype->type)
4281 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL); //get pointer to precise def.
4284 if (d->arraysize <= 1)
4286 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], ao, 0, NULL), NULL); //get pointer to precise def.
4287 newtype = nd->type;//don't be fooled
4291 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL); //get pointer to precise def.
4295 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def.
4298 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
4301 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def.
4304 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL); //get pointer to precise def.
4308 if (ao->constant && !G_INT(ao->ofs))
4310 if (d->arraysize>1) //use the array
4312 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
4313 nd->type = d->type->aux_type;
4316 { //dereference the pointer.
4317 switch(newtype->aux_type->type)
4320 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
4321 nd->type = d->type->aux_type;
4324 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL); //get pointer to precise def.
4325 nd->type = d->type->aux_type;
4328 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL); //get pointer to precise def.
4329 nd->type = d->type->aux_type;
4332 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
4333 nd->type = d->type->aux_type;
4336 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4343 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
4346 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
4350 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4356 else if (ao->type->type == ev_float)
4358 if (qcc_targetformat == QCF_HEXEN2)
4359 { //hexen2 style retrieval, mixed with q1 style assignments...
4360 if (QCC_PR_CheckToken("=")) //(hideous concept)
4362 QCC_def_t *funcretr;
4365 QCC_PR_ParseError(0, "Scoped array without specific engine support");
4367 funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false);
4368 nd = QCC_PR_Expression(TOP_PRIORITY, 0);
4369 if (nd->type->type != d->type->type)
4370 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
4374 return QCC_PR_GenerateFunctionCall(funcretr, args, 2);
4377 switch(newtype->type)
4380 nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, ao, &st); //get pointer to precise def.
4384 nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, ao, &st); //get pointer to precise def.
4388 nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, ao, &st); //get pointer to precise def.
4392 nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, ao, &st); //get pointer to precise def.
4396 nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, ao, &st); //get pointer to precise def.
4400 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4413 if (!QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) //q1 compatible.
4414 { //you didn't see this, okay?
4415 QCC_def_t *funcretr;
4417 QCC_PR_ParseError(0, "Scoped array without specific engine support");
4419 if (allowarrayassign && QCC_PR_CheckToken("="))
4423 funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false);
4425 nd = QCC_PR_Expression(TOP_PRIORITY, 0);
4426 if (nd->type->type != d->type->type)
4427 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
4431 qcc_usefulstatement=true;
4432 nd = QCC_PR_GenerateFunctionCall(funcretr, args, 2);
4433 nd->type = d->type->aux_type;
4439 def_parms[0].type = type_float;
4440 funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false);
4443 nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1);
4444 nd->type = d->type->aux_type;
4449 switch(newtype->type)
4452 if (d->arraysize>1) //use the array
4454 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4455 nd->type = d->type->aux_type;
4458 { //dereference the pointer.
4459 switch(newtype->aux_type->type)
4462 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4463 nd->type = d->type->aux_type;
4466 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4467 nd->type = d->type->aux_type;
4470 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4471 nd->type = d->type->aux_type;
4474 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4475 nd->type = d->type->aux_type;
4478 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4486 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4489 if (d->arraysize <= 1)
4491 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, ao, NULL); //get pointer to precise def.
4492 newtype = nd->type;//don't be fooled
4495 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4498 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4501 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4504 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4507 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4511 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4515 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
4519 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4528 QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
4536 if (i == ev_pointer)
4540 if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
4542 for (i = d->type->num_parms, type = d->type+1; i; i--, type++)
4544 if (QCC_PR_CheckName(type->name))
4549 numstatements--; //remove the last statement
4552 nd = QCC_MakeIntDef(type->ofs);
4553 ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
4555 //so that we may offset it and readd it.
4558 ao = QCC_MakeIntDef(type->ofs);
4562 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL); //get pointer to precise def.
4565 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, ao, NULL); //get pointer to precise def.
4568 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL); //get pointer to precise def.
4571 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, ao, NULL); //get pointer to precise def.
4574 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, ao, NULL); //get pointer to precise def.
4577 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, ao, NULL); //get pointer to precise def.
4581 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
4586 // nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def.
4590 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4598 if (type->num_parms)
4600 for (j = type->num_parms; j;j--)
4605 QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
4610 else if (i == ev_struct || i == ev_union)
4614 if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
4616 for (i = d->type->num_parms, type = d->type+1; i; i--, type++)
4618 if (QCC_PR_CheckName(type->name))
4623 numstatements--; //remove the last statement
4626 nd = QCC_MakeIntDef(type->ofs);
4627 ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
4629 //so that we may offset it and readd it.
4632 ao = QCC_MakeIntDef(type->ofs);
4636 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL); //get pointer to precise def.
4639 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL); //get pointer to precise def.
4642 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def.
4645 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
4648 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def.
4651 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL); //get pointer to precise def.
4655 nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
4660 // nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def.
4664 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4672 if (type->num_parms)
4674 for (j = type->num_parms; j;j--)
4679 QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
4685 /* if (d->type->type == ev_pointer)
4686 { //expand now, not in function call/maths parsing
4687 switch(d->type->aux_type->type)
4690 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, NULL, NULL);
4693 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, NULL, NULL);
4701 if (d->type->parentclass||d->type->type == ev_entity) //class
4703 if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))
4706 if (QCC_PR_CheckToken("("))
4708 field = QCC_PR_Expression(TOP_PRIORITY, 0);
4712 field = QCC_PR_ParseValue(d->type, false);
4713 if (field->type->type == ev_field)
4715 if (!field->type->aux_type)
4717 QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type");
4718 return QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
4722 switch(field->type->aux_type->type)
4725 QCC_PR_ParseError(ERR_INTERNAL, "Bad field type");
4728 return QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL);
4730 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
4731 nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4732 memset (nd, 0, sizeof(QCC_def_t));
4733 nd->type = field->type->aux_type;
4736 nd->constant = false;
4740 return QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL);
4742 return QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL);
4744 return QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL);
4746 { //complicated for a typecast
4747 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL);
4748 nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4749 memset (nd, 0, sizeof(QCC_def_t));
4750 nd->type = field->type->aux_type;
4753 nd->constant = false;
4759 return QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL);
4764 QCC_PR_IncludeChunk(".", false, NULL);
4777 QCC_def_t *QCC_PR_Term (void)
4781 if (pr_token_type == tt_punct) //a little extra speed...
4783 if (QCC_PR_CheckToken("++"))
4785 qcc_usefulstatement=true;
4788 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
4790 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Hey! That's a temp! ++ operators cannot work on temps!");
4791 switch (e->type->type)
4794 QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false);
4797 QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false);
4800 QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "++ operator on unsupported type");
4805 else if (QCC_PR_CheckToken("--"))
4807 qcc_usefulstatement=true;
4810 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
4812 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Hey! That's a temp! -- operators cannot work on temps!");
4813 switch (e->type->type)
4816 QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false);
4819 QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false);
4822 QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "-- operator on unsupported type");
4828 if (QCC_PR_CheckToken ("!"))
4830 e = QCC_PR_Expression (NOT_PRIORITY, EXPR_DISALLOW_COMMA|EXPR_WARN_ABOVE_1);
4833 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_F], e, 0, NULL);
4834 else if (t == ev_string)
4835 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_S], e, 0, NULL);
4836 else if (t == ev_entity)
4837 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_ENT], e, 0, NULL);
4838 else if (t == ev_vector)
4839 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_V], e, 0, NULL);
4840 else if (t == ev_function)
4841 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0, NULL);
4842 else if (t == ev_integer)
4843 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0, NULL); //functions are integer values too.
4844 else if (t == ev_pointer)
4845 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0, NULL); //Pointers are too.
4848 e2 = NULL; // shut up compiler warning;
4849 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for !");
4854 else if (QCC_PR_CheckToken ("&"))
4856 int st = numstatements;
4857 e = QCC_PR_Expression (UNARY_PRIORITY, 0);
4860 if (st != numstatements)
4861 //woo, something like ent.field?
4863 if ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
4865 statements[numstatements-1].op = OP_ADDRESS;
4866 e->type = QCC_PR_PointerType(e->type);
4869 else //this is a restriction that could be lifted, I just want to make sure that I got all the bits first.
4871 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for '&' Must be singular expression or field reference");
4875 // QCC_PR_ParseWarning(0, "debug: &global");
4877 if (!QCC_OPCodeValid(&pr_opcodes[OP_GLOBALADDRESS]))
4878 QCC_PR_ParseError (ERR_BADEXTENSION, "Cannot use addressof operator ('&') on a global. Please use the FTE target.");
4880 e2 = QCC_PR_Statement (&pr_opcodes[OP_GLOBALADDRESS], e, 0, NULL);
4881 e2->type = QCC_PR_PointerType(e->type);
4884 else if (QCC_PR_CheckToken ("*"))
4886 e = QCC_PR_Expression (UNARY_PRIORITY, 0);
4889 if (t != ev_pointer)
4890 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *");
4892 switch(e->type->aux_type->type)
4895 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL);
4898 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL);
4901 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL);
4904 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL);
4907 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
4910 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
4913 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
4916 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
4920 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)");
4925 e2->type = e->type->aux_type;
4928 else if (QCC_PR_CheckToken ("-"))
4930 e = QCC_PR_Expression (UNARY_PRIORITY, 0);
4932 switch(e->type->type)
4935 e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatDef(0), e, NULL);
4938 e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorDef(0, 0, 0), e, NULL);
4941 e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntDef(0), e, NULL);
4944 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for -");
4950 else if (QCC_PR_CheckToken ("+"))
4952 e = QCC_PR_Expression (UNARY_PRIORITY, 0);
4954 switch(e->type->type)
4966 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for +");
4973 if (QCC_PR_CheckToken ("("))
4975 if (QCC_PR_CheckKeyword(keyword_float, "float")) //check for type casts
4977 QCC_PR_Expect (")");
4979 if (e->type->type == ev_float)
4981 else if (e->type->type == ev_integer)
4982 return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL);
4983 else if (e->type->type == ev_function)
4986 // QCC_PR_ParseError ("invalid typecast");
4988 QCC_PR_ParseWarning (0, "Not all vars make sence as floats");
4990 e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4991 memset (e2, 0, sizeof(QCC_def_t));
4992 e2->type = type_float;
4994 e2->constant = true;
4998 else if (QCC_PR_CheckKeyword(keyword_class, "class"))
5000 QCC_type_t *classtype = QCC_TypeForName(QCC_PR_ParseName());
5002 QCC_PR_ParseError(ERR_NOTANAME, "Class not defined for cast");
5004 QCC_PR_Expect (")");
5006 e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
5007 memset (e2, 0, sizeof(QCC_def_t));
5008 e2->type = classtype;
5010 e2->constant = true;
5014 else if (QCC_PR_CheckKeyword(keyword_integer, "integer")) //check for type casts
5016 QCC_PR_Expect (")");
5018 if (e->type->type == ev_integer)
5020 else if (e->type->type == ev_float)
5021 return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL);
5023 QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast");
5025 else if (QCC_PR_CheckKeyword(keyword_int, "int")) //check for type casts
5027 QCC_PR_Expect (")");
5029 if (e->type->type == ev_integer)
5031 else if (e->type->type == ev_float)
5032 return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL);
5034 QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast");
5038 pbool oldcond = conditional;
5039 conditional = conditional?2:0;
5040 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5041 QCC_PR_Expect (")");
5042 conditional = oldcond;
5047 return QCC_PR_ParseValue (pr_classtype, true);
5051 int QCC_canConv(QCC_def_t *from, etype_t to)
5053 if (from->type->type == to)
5056 if (from->type->type == ev_vector && to == ev_float)
5061 if (from->type->type == ev_field)
5063 if (from->type->aux_type->type == to)
5068 /* if (from->type->type == ev_pointer && from->type->aux_type->type == to)
5071 if (QCC_ShouldConvert(from, to)>=0)
5074 if (from->type->type == ev_integer && to == ev_function)
5085 QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
5087 QCC_dstatement32_t *st;
5088 QCC_opcode_t *op, *oldop;
5090 QCC_opcode_t *bestop;
5091 int numconversions, c;
5096 etype_t type_a, type_b, type_c;
5099 return QCC_PR_Term ();
5101 e = QCC_PR_Expression (priority-1, exprflags);
5107 if (QCC_PR_CheckToken ("(") )
5109 qcc_usefulstatement=true;
5110 e = QCC_PR_ParseFunctionCall (e);
5112 if (QCC_PR_CheckToken ("?"))
5114 QCC_dstatement32_t *fromj, *elsej;
5115 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], e, NULL, &fromj));
5116 e = QCC_PR_Expression(TOP_PRIORITY, 0);
5117 e2 = QCC_GetTemp(e->type);
5118 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[(e2->type->size>=3)?OP_STORE_V:OP_STORE_F], e, e2, NULL));
5119 //e2 can be stomped upon until its reused anyway
5123 QCC_PR_Statement(&pr_opcodes[OP_GOTO], NULL, NULL, &elsej);
5124 fromj->b = &statements[numstatements] - fromj;
5125 e = QCC_PR_Expression(TOP_PRIORITY, 0);
5127 if (typecmp(e->type, e2->type) != 0)
5128 QCC_PR_ParseError(0, "Ternary operator with mismatching types\n");
5129 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[(e2->type->size>=3)?OP_STORE_V:OP_STORE_F], e, e2, NULL));
5132 elsej->a = &statements[numstatements] - elsej;
5139 if (pr_token_type == tt_immediate)
5141 if (pr_immediate_type->type == ev_float)
5142 if (pr_immediate._float < 0) //hehehe... was a minus all along...
5144 QCC_PR_IncludeChunk(pr_token, true, NULL);
5145 strcpy(pr_token, "+");//two negatives would make a positive.
5146 pr_token_type = tt_punct;
5150 if (pr_token_type != tt_punct)
5152 QCC_PR_ParseWarning(WARN_UNEXPECTEDPUNCT, "Expected punctuation");
5155 //go straight for the correct priority.
5156 for (op = opcodeprioritized[priority][opnum]; op; op = opcodeprioritized[priority][++opnum])
5157 // for (op=pr_opcodes ; op->name ; op++)
5159 // if (op->priority != priority)
5161 if (!QCC_PR_CheckToken (op->name))
5164 if ( op->associative!=ASSOC_LEFT )
5166 // if last statement is an indirect, change it to an address of
5167 if (!simplestore && ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P) && statements[numstatements-1].c == e->ofs)
5169 qcc_usefulstatement=true;
5170 statements[numstatements-1].op = OP_ADDRESS;
5171 type_pointer->aux_type->type = e->type->type;
5172 e->type = type_pointer;
5174 //if last statement retrieved a value, switch it to retrieve a usable pointer.
5175 if ( !simplestore && (unsigned)(statements[numstatements-1].op - OP_LOADA_F) < 7)// || statements[numstatements-1].op == OP_LOADA_C)
5177 statements[numstatements-1].op = OP_GLOBALADDRESS;
5178 type_pointer->aux_type->type = e->type->type;
5179 e->type = type_pointer;
5181 if ( !simplestore && (unsigned)(statements[numstatements-1].op - OP_LOADP_F) < 7 && statements[numstatements-1].c == e->ofs)
5183 if (!statements[numstatements-1].b)
5185 //if the loadp has no offset, remove the instruction and convert the dest of this instruction directly to the pointer's load address
5186 //this kills the add 0.
5187 e->ofs = statements[numstatements-1].a;
5190 if (e->type->type != ev_pointer)
5192 type_pointer->aux_type->type = e->type->type;
5193 e->type = type_pointer;
5198 statements[numstatements-1].op = OP_ADD_I;
5199 if (e->type->type != ev_pointer)
5201 type_pointer->aux_type->type = e->type->type;
5202 e->type = type_pointer;
5206 if ( !simplestore && statements[numstatements-1].op == OP_LOADP_C && e->ofs == statements[numstatements-1].c)
5208 statements[numstatements-1].op = OP_ADD_SF;
5209 e->type = type_string;
5211 //now we want to make sure that string = float can't work without it being a dereferenced pointer. (we don't want to allow storep_c without dereferece)
5212 e2 = QCC_PR_Expression (priority, exprflags);
5213 if (e2->type->type == ev_float)
5214 op = &pr_opcodes[OP_STOREP_C];
5217 e2 = QCC_PR_Expression (priority, exprflags);
5221 if (op->priority == 7 && opt_logicops)
5224 st = &statements[numstatements];
5225 if (*op->name == '&') //statement 3 because we don't want to optimise this into if from not ifnot
5226 QCC_PR_Statement3(&pr_opcodes[OP_IFNOT], e, NULL, NULL, false);
5228 QCC_PR_Statement3(&pr_opcodes[OP_IF], e, NULL, NULL, false);
5231 e2 = QCC_PR_Expression (priority-1, exprflags);
5235 type_a = e->type->type;
5236 type_b = e2->type->type;
5238 // if (type_a == ev_pointer && type_b == ev_pointer)
5239 // QCC_PR_ParseWarning(0, "Debug: pointer op pointer");
5241 if (op->name[0] == '.')// field access gets type from field
5243 if (e2->type->aux_type)
5244 type_c = e2->type->aux_type->type;
5246 type_c = -1; // not a field
5253 numconversions = 32767;
5256 if (!(type_c != ev_void && type_c != (*op->type_c)->type))
5258 if (!STRCMP (op->name , oldop->name)) //matches
5260 //return values are never converted - what to?
5261 // if (type_c != ev_void && type_c != op->type_c->type->type)
5267 if (op->associative!=ASSOC_LEFT)
5269 if (op->type_a == &type_pointer) //ent var
5271 if (e->type->type != ev_pointer)
5272 c = -200; //don't cast to a pointer.
5273 else if ((*op->type_c)->type == ev_void && op->type_b == &type_pointer && e2->type->type == ev_pointer)
5274 c = 0; //generic pointer... fixme: is this safe? make sure both sides are equivelent
5275 else if (e->type->aux_type->type != (*op->type_b)->type) //if e isn't a pointer to a type_b
5276 c = -200; //don't let the conversion work
5278 c = QCC_canConv(e2, (*op->type_c)->type);
5282 c=QCC_canConv(e2, (*op->type_b)->type);
5283 if (type_a != (*op->type_a)->type) //in this case, a is the final assigned value
5284 c = -300; //don't use this op, as we must not change var b's type
5289 if (op->type_a == &type_pointer) //ent var
5291 if (e2->type->type != ev_pointer || e2->type->aux_type->type != (*op->type_b)->type) //if e isn't a pointer to a type_b
5292 c = -200; //don't let the conversion work
5298 c=QCC_canConv(e, (*op->type_a)->type);
5299 c+=QCC_canConv(e2, (*op->type_b)->type);
5303 if (c>=0 && c < numconversions)
5307 if (c == 0)//can't get less conversions than 0...
5314 op = opcodeprioritized[priority][++opnum];
5318 if (oldop->priority == CONDITION_PRIORITY)
5325 QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch for %s (%s and %s)", oldop->name, e->type->name, e2->type->name);
5328 QCC_PR_ParseError (ERR_TYPEMISMATCH, "type mismatch for %s (%s and %s)", oldop->name, e->type->name, e2->type->name);
5333 if (numconversions>3)
5334 QCC_PR_ParseWarning(WARN_IMPLICITCONVERSION, "Implicit conversion");
5338 // if (type_a == ev_pointer && type_b != e->type->aux_type->type)
5339 // QCC_PR_ParseError ("type mismatch for %s", op->name);
5342 st->b = &statements[numstatements] - st;
5345 if (op->associative!=ASSOC_LEFT)
5347 qcc_usefulstatement = true;
5348 if (e->constant || e->ofs < OFS_PARM0)
5350 if (e->type->type == ev_function)
5352 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANTFUNC, "Assignment to function %s", e->name);
5353 QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANTFUNC, e);
5357 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
5358 QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, e);
5361 editbadfile(strings+s_file, pr_source_line);
5365 QCC_PR_ParseWarning(WARN_ASSIGNMENTINCONDITIONAL, "Assignment in conditional");
5367 e = QCC_PR_Statement (op, e2, e, NULL);
5370 e = QCC_PR_Statement (op, e, e2, NULL);
5372 if (type_c != ev_void/* && type_c != ev_string*/) // field access gets type from field
5373 e->type = e2->type->aux_type;
5375 if (priority > 1 && exprflags & EXPR_WARN_ABOVE_1)
5376 QCC_PR_ParseWarning(0, "You may wish to add brackets after that ! operator");
5383 QCC_PR_ParseError(ERR_INTERNAL, "e == null");
5386 if (!STRCMP(pr_token, "++"))
5388 //if the last statement was an ent.float (or something)
5389 if (((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I) && statements[numstatements-1].c == e->ofs)
5390 { //we have our load.
5392 //the only inefficiency here is with an extra temp (we can't reuse the original)
5393 //this is not a problem, as the optimise temps or locals marshalling can clean these up for us
5394 qcc_usefulstatement=true;
5397 //store temp to offset
5398 //return original loaded (which is not at the same offset as the pointer we store to)
5399 e2 = QCC_GetTemp(type_float);
5400 e3 = QCC_GetTemp(type_pointer);
5401 QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
5402 if (e->type->type == ev_float)
5404 QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e2, false);
5405 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
5407 else if (e->type->type == ev_integer)
5409 QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e2, false);
5410 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
5414 QCC_PR_ParseError(ERR_PARSEERRORS, "-- suffix operator results in nonstandard behaviour. Use -=1 or prefix form instead");
5415 QCC_PR_IncludeChunk("-=1", false, NULL);
5420 else if (e->type->type == ev_float)
5424 //return temp (which == original)
5425 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "++ suffix operator results in inefficient behaviour. Use +=1 or prefix form instead");
5426 qcc_usefulstatement=true;
5428 e2 = QCC_GetTemp(type_float);
5429 QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
5430 QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false);
5434 else if (e->type->type == ev_integer)
5436 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "++ suffix operator results in inefficient behaviour. Use +=1 or prefix form instead");
5437 qcc_usefulstatement=true;
5439 e2 = QCC_GetTemp(type_integer);
5440 QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
5441 QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false);
5447 QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "++ suffix operator results in nonstandard behaviour. Use +=1 or prefix form instead");
5448 QCC_PR_IncludeChunk("+=1", false, NULL);
5452 else if (!STRCMP(pr_token, "--"))
5454 if (((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I) && statements[numstatements-1].c == e->ofs)
5455 { //we have our load.
5459 //store temp to offset
5460 //return original loaded (which is not at the same offset as the pointer we store to)
5461 e2 = QCC_GetTemp(type_float);
5462 e3 = QCC_GetTemp(type_pointer);
5463 QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
5464 if (e->type->type == ev_float)
5466 QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e2, false);
5467 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
5469 else if (e->type->type == ev_integer)
5471 QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e2, false);
5472 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
5476 QCC_PR_ParseError(ERR_PARSEERRORS, "-- suffix operator results in nonstandard behaviour. Use -=1 or prefix form instead");
5477 QCC_PR_IncludeChunk("-=1", false, NULL);
5482 else if (e->type->type == ev_float)
5484 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "-- suffix operator results in inefficient behaviour. Use -=1 or prefix form instead");
5485 qcc_usefulstatement=true;
5487 e2 = QCC_GetTemp(type_float);
5488 QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
5489 QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false);
5493 else if (e->type->type == ev_integer)
5495 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "-- suffix operator results in inefficient behaviour. Use -=1 or prefix form instead");
5496 qcc_usefulstatement=true;
5498 e2 = QCC_GetTemp(type_integer);
5499 QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
5500 QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false);
5506 QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "-- suffix operator results in nonstandard behaviour. Use -=1 or prefix form instead");
5507 QCC_PR_IncludeChunk("-=1", false, NULL);
5511 break; // next token isn't at this priority level
5515 QCC_PR_ParseError(ERR_INTERNAL, "e == null");
5517 if (!(exprflags&EXPR_DISALLOW_COMMA) && priority == TOP_PRIORITY && QCC_PR_CheckToken (","))
5520 return QCC_PR_Expression(TOP_PRIORITY, exprflags);
5526 void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname)
5528 if (num_gotos >= max_gotos)
5531 pr_gotos = realloc(pr_gotos, sizeof(*pr_gotos)*max_gotos);
5534 strncpy(pr_gotos[num_gotos].name, labelname, sizeof(pr_gotos[num_gotos].name) -1);
5535 pr_gotos[num_gotos].lineno = pr_source_line;
5536 pr_gotos[num_gotos].statementno = patch2 - statements;
5541 pbool QCC_PR_StatementBlocksMatch(QCC_dstatement_t *p1, int p1count, QCC_dstatement_t *p2, int p2count)
5543 if (p1count != p2count)
5548 if (p1->op != p2->op)
5570 void QCC_PR_ParseStatement (void)
5577 QCC_dstatement_t *patch1, *patch2, *patch3;
5578 int statementstart = pr_source_line;
5580 if (QCC_PR_CheckToken ("{"))
5583 while (!QCC_PR_CheckToken("}"))
5584 QCC_PR_ParseStatement ();
5586 if (pr_subscopedlocals)
5588 for (e2 = pr.localvars; e2 != e; e2 = e2->nextlocal)
5590 Hash_RemoveData(&localstable, e2->name, e2);
5596 if (QCC_PR_CheckKeyword(keyword_return, "return"))
5600 e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
5601 e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
5602 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL));
5605 if (QCC_PR_CheckToken (";"))
5607 if (pr_scope->type->aux_type->type != ev_void)
5608 QCC_PR_ParseWarning(WARN_MISSINGRETURNVALUE, "\'%s\' should return %s", pr_scope->name, pr_scope->type->aux_type->name);
5609 if (opt_return_only)
5610 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_DONE], 0, 0, NULL));
5612 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], 0, 0, NULL));
5615 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5616 e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type);
5619 QCC_PR_ParseWarning(WARN_CORRECTEDRETURNTYPE, "\'%s\' returned %s, expected %s, conversion supplied", pr_scope->name, e->type->name, pr_scope->type->aux_type->name);
5622 QCC_PR_Expect (";");
5623 if (pr_scope->type->aux_type->type != e->type->type)
5624 QCC_PR_ParseWarning(WARN_WRONGRETURNTYPE, "\'%s\' returned %s, expected %s", pr_scope->name, e->type->name, pr_scope->type->aux_type->name);
5625 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], e, 0, NULL));
5628 if (QCC_PR_CheckKeyword(keyword_exit, "exit"))
5630 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_DONE], 0, 0, NULL));
5631 QCC_PR_Expect (";");
5635 if (QCC_PR_CheckKeyword(keyword_while, "while"))
5637 continues = num_continues;
5638 breaks = num_breaks;
5640 QCC_PR_Expect ("(");
5641 patch2 = &statements[numstatements];
5643 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5645 if (((e->constant && !e->temp) || !STRCMP(e->name, "IMMEDIATE")) && opt_compound_jumps)
5647 optres_compound_jumps++;
5650 QCC_PR_ParseWarning(0, "while(0)?");
5651 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch1));
5660 if (e->constant && !e->temp)
5662 if (!G_FLOAT(e->ofs))
5663 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch1));
5667 else if (!typecmp( e->type, type_string) && flag_ifstring) //special case, as strings are now pointers, not offsets from string table
5669 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "while(string) can result in bizzare behaviour");
5670 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch1));
5672 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) //special case, as negative 0 is also zero
5673 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
5675 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
5677 QCC_PR_Expect (")"); //after the line number is noted..
5678 QCC_PR_ParseStatement ();
5679 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], NULL, 0, &patch3));
5680 patch3->a = patch2 - patch3;
5683 if (patch1->op == OP_GOTO)
5684 patch1->a = &statements[numstatements] - patch1;
5686 patch1->b = &statements[numstatements] - patch1;
5689 if (breaks != num_breaks)
5691 for(i = breaks; i < num_breaks; i++)
5693 patch1 = &statements[pr_breaks[i]];
5694 statements[pr_breaks[i]].a = &statements[numstatements] - patch1; //jump to after the return-to-top goto
5696 num_breaks = breaks;
5698 if (continues != num_continues)
5700 for(i = continues; i < num_continues; i++)
5702 patch1 = &statements[pr_continues[i]];
5703 statements[pr_continues[i]].a = patch2 - patch1; //jump back to top
5705 num_continues = continues;
5709 if (QCC_PR_CheckKeyword(keyword_for, "for"))
5711 int old_numstatements;
5715 QCC_dstatement_t temp[sizeof(linenum)/sizeof(linenum[0])];
5717 continues = num_continues;
5718 breaks = num_breaks;
5721 if (!QCC_PR_CheckToken(";"))
5723 QCC_FreeTemp(QCC_PR_Expression(TOP_PRIORITY, 0));
5727 patch2 = &statements[numstatements];
5728 if (!QCC_PR_CheckToken(";"))
5731 e = QCC_PR_Expression(TOP_PRIORITY, 0);
5738 if (!QCC_PR_CheckToken(")"))
5740 old_numstatements = numstatements;
5741 QCC_FreeTemp(QCC_PR_Expression(TOP_PRIORITY, 0));
5743 numtemp = numstatements - old_numstatements;
5744 if (numtemp > sizeof(linenum)/sizeof(linenum[0]))
5745 QCC_PR_ParseError(ERR_TOOCOMPLEX, "Update expression too large");
5746 numstatements = old_numstatements;
5747 for (i = 0 ; i < numtemp ; i++)
5749 linenum[i] = statement_linenums[numstatements + i];
5750 temp[i] = statements[numstatements + i];
5759 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], e, 0, &patch1));
5762 if (!QCC_PR_CheckToken(";"))
5763 QCC_PR_ParseStatement(); //don't give the hanging ';' warning.
5764 patch3 = &statements[numstatements];
5765 for (i = 0 ; i < numtemp ; i++)
5767 statement_linenums[numstatements] = linenum[i];
5768 statements[numstatements++] = temp[i];
5770 QCC_PR_SimpleStatement(OP_GOTO, patch2 - &statements[numstatements], 0, 0, false);
5772 patch1->b = &statements[numstatements] - patch1;
5774 if (breaks != num_breaks)
5776 for(i = breaks; i < num_breaks; i++)
5778 patch1 = &statements[pr_breaks[i]];
5779 statements[pr_breaks[i]].a = &statements[numstatements] - patch1;
5781 num_breaks = breaks;
5783 if (continues != num_continues)
5785 for(i = continues; i < num_continues; i++)
5787 patch1 = &statements[pr_continues[i]];
5788 statements[pr_continues[i]].a = patch3 - patch1;
5790 num_continues = continues;
5795 if (QCC_PR_CheckKeyword(keyword_do, "do"))
5797 continues = num_continues;
5798 breaks = num_breaks;
5800 patch1 = &statements[numstatements];
5801 QCC_PR_ParseStatement ();
5802 QCC_PR_Expect ("while");
5803 QCC_PR_Expect ("(");
5805 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5808 if (e->constant && !e->temp)
5810 if (G_FLOAT(e->ofs))
5812 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], NULL, 0, &patch2));
5813 patch2->a = patch1 - patch2;
5818 if (!typecmp( e->type, type_string) && flag_ifstring)
5820 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "do {} while(string) can result in bizzare behaviour");
5821 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_S], e, NULL, &patch2));
5823 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
5824 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, NULL, &patch2));
5826 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, NULL, &patch2));
5828 patch2->b = patch1 - patch2;
5831 QCC_PR_Expect (")");
5832 QCC_PR_Expect (";");
5834 if (breaks != num_breaks)
5836 for(i = breaks; i < num_breaks; i++)
5838 patch2 = &statements[pr_breaks[i]];
5839 statements[pr_breaks[i]].a = &statements[numstatements] - patch2;
5841 num_breaks = breaks;
5843 if (continues != num_continues)
5845 for(i = continues; i < num_continues; i++)
5847 patch2 = &statements[pr_continues[i]];
5848 statements[pr_continues[i]].a = patch1 - patch2;
5850 num_continues = continues;
5856 if (QCC_PR_CheckKeyword(keyword_local, "local"))
5858 QCC_type_t *functionsclasstype = pr_classtype;
5859 // if (locals_end != numpr_globals) //is this breaking because of locals?
5860 // QCC_PR_ParseWarning("local vars after temp vars\n");
5861 QCC_PR_ParseDefs (NULL);
5862 pr_classtype = functionsclasstype;
5863 locals_end = numpr_globals;
5867 if (pr_token_type == tt_name)
5868 if ((keyword_var && !STRCMP ("var", pr_token)) ||
5869 (keyword_string && !STRCMP ("string", pr_token)) ||
5870 (keyword_float && !STRCMP ("float", pr_token)) ||
5871 (keyword_entity && !STRCMP ("entity", pr_token)) ||
5872 (keyword_vector && !STRCMP ("vector", pr_token)) ||
5873 (keyword_integer && !STRCMP ("integer", pr_token)) ||
5874 (keyword_int && !STRCMP ("int", pr_token)) ||
5875 (keyword_class && !STRCMP ("class", pr_token)) ||
5876 (keyword_const && !STRCMP ("const", pr_token)))
5878 // if (locals_end != numpr_globals) //is this breaking because of locals?
5879 // QCC_PR_ParseWarning("local vars after temp vars\n");
5880 QCC_PR_ParseDefs (NULL);
5881 locals_end = numpr_globals;
5885 if (QCC_PR_CheckKeyword(keyword_state, "state"))
5888 QCC_PR_ParseState();
5892 if (QCC_PR_CheckToken("#"))
5895 float frame = pr_immediate._float;
5897 name = QCC_PR_ParseName();
5898 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatDef(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL));
5903 if (QCC_PR_CheckKeyword(keyword_if, "if"))
5905 pbool negate = QCC_PR_CheckKeyword(keyword_not, "not");
5907 QCC_PR_Expect ("(");
5909 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5912 // negate = negate != 0;
5916 if (!typecmp( e->type, type_string) && flag_ifstring)
5918 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if not(string) can result in bizzare behaviour");
5919 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_S], e, 0, &patch1));
5921 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
5922 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, 0, &patch1));
5924 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, 0, &patch1));
5928 if (!typecmp( e->type, type_string) && flag_ifstring)
5930 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if (string) can result in bizzare behaviour");
5931 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch1));
5933 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
5934 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
5936 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
5939 QCC_PR_Expect (")"); //close bracket is after we save the statement to mem (so debugger does not show the if statement as being on the line after
5941 QCC_PR_ParseStatement ();
5943 if (QCC_PR_CheckKeyword (keyword_else, "else"))
5946 lastwasreturn = statements[numstatements-1].op == OP_RETURN || statements[numstatements-1].op == OP_DONE ||
5947 statements[numstatements-1].op == OP_GOTO;
5949 //the last statement of the if was a return, so we don't need the goto at the end
5950 if (lastwasreturn && opt_compound_jumps && !QCC_AStatementJumpsTo(numstatements, patch1-statements, numstatements))
5952 // QCC_PR_ParseWarning(0, "optimised the else");
5953 optres_compound_jumps++;
5954 patch1->b = &statements[numstatements] - patch1;
5955 QCC_PR_ParseStatement ();
5959 // QCC_PR_ParseWarning(0, "using the else");
5960 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2));
5961 patch1->b = &statements[numstatements] - patch1;
5962 QCC_PR_ParseStatement ();
5963 patch2->a = &statements[numstatements] - patch2;
5965 if (QCC_PR_StatementBlocksMatch(patch1+1, patch2-patch1, patch2+1, &statements[numstatements] - patch2))
5966 QCC_PR_ParseWarning(0, "Two identical blocks each side of an else");
5970 patch1->b = &statements[numstatements] - patch1;
5974 if (QCC_PR_CheckKeyword(keyword_switch, "switch"))
5978 int defaultcase = -1;
5981 QCC_type_t *switchtype;
5983 breaks = num_breaks;
5987 QCC_PR_Expect ("(");
5990 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5994 { //copy it out, so our hack just below doesn't crash us
5995 /* if (e->type->type == ev_vector)
5996 e = QCC_PR_Statement(pr_opcodes+OP_STORE_V, e, QCC_GetTemp(type_vector), NULL);
5998 e = QCC_PR_Statement(pr_opcodes+OP_STORE_F, e, QCC_GetTemp(type_float), NULL);
6000 if (e == &def_ret) //this shouldn't be happening
6001 QCC_Error(ERR_INTERNAL, "internal error: switch: e == &def_ret");
6008 e->temp = NULL; //so noone frees it until we finish this loop
6013 //switch (CONDITION)
6024 // x = CONDITION, goto start
6032 // if (x == 1) goto l1;
6033 // if (x == 2) goto l2;
6037 //x is emitted in an opcode, stored as a register that we cannot access later.
6038 //it should be possible to nest these.
6040 switchtype = e->type;
6041 switch(switchtype->type)
6046 case ev_entity: //whu???
6064 hcstyle = QCC_OPCodeValid(&pr_opcodes[op]);
6070 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[op], e, 0, &patch1));
6072 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], e, 0, &patch1));
6074 QCC_PR_Expect (")"); //close bracket is after we save the statement to mem (so debugger does not show the if statement as being on the line after
6076 oldst = numstatements;
6077 QCC_PR_ParseStatement ();
6079 //this is so that a missing goto at the end of your switch doesn't end up in the jumptable again
6080 if (oldst == numstatements || !QCC_StatementIsAJump(numstatements-1, numstatements-1))
6082 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2)); //the P1 statement/the theyforgotthebreak statement.
6083 // QCC_PR_ParseWarning(0, "emitted goto");
6088 // QCC_PR_ParseWarning(0, "No goto");
6092 patch1->b = &statements[numstatements] - patch1; //the goto start part
6094 patch1->a = &statements[numstatements] - patch1; //the goto start part
6097 e->type = switchtype; //set it back to the type it was actually meant to be.
6099 for (i = cases; i < num_cases; i++)
6101 if (!pr_casesdef[i])
6103 if (defaultcase >= 0)
6104 QCC_PR_ParseError(ERR_MULTIPLEDEFAULTS, "Duplicated default case");
6109 if (pr_casesdef[i]->type->type != e->type->type)
6111 if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
6112 pr_casesdef[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef[i]->ofs]);
6114 QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch case type mismatch");
6116 if (pr_casesdef2[i])
6118 if (pr_casesdef2[i]->type->type != e->type->type)
6120 if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
6121 pr_casesdef2[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef2[i]->ofs]);
6123 QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch caserange type mismatch");
6128 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CASERANGE], pr_casesdef[i], pr_casesdef2[i], &patch3));
6129 patch3->c = &statements[pr_cases[i]] - patch3;
6135 if (e->type->type == ev_float)
6137 e2 = QCC_PR_Statement (&pr_opcodes[OP_GE], e, pr_casesdef[i], NULL);
6138 e3 = QCC_PR_Statement (&pr_opcodes[OP_LE], e, pr_casesdef2[i], NULL);
6139 e2 = QCC_PR_Statement (&pr_opcodes[OP_AND], e2, e3, NULL);
6140 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3));
6141 patch3->b = &statements[pr_cases[i]] - patch3;
6143 else if (e->type->type == ev_integer)
6145 e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_I], e, pr_casesdef[i], NULL);
6146 e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_I], e, pr_casesdef2[i], NULL);
6147 e2 = QCC_PR_Statement (&pr_opcodes[OP_AND], e2, e3, NULL);
6148 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3));
6149 patch3->b = &statements[pr_cases[i]] - patch3;
6152 QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch caserange MUST be a float or integer");
6159 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CASE], pr_casesdef[i], 0, &patch3));
6160 patch3->b = &statements[pr_cases[i]] - patch3;
6164 if (!pr_casesdef[i]->constant || G_INT(pr_casesdef[i]->ofs))
6166 switch(e->type->type)
6169 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_F], e, pr_casesdef[i], NULL);
6171 case ev_entity: //whu???
6172 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_E], e, pr_casesdef[i], &patch1);
6175 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_V], e, pr_casesdef[i], &patch1);
6178 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_S], e, pr_casesdef[i], &patch1);
6181 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_FNC], e, pr_casesdef[i], &patch1);
6184 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_FNC], e, pr_casesdef[i], &patch1);
6187 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_I], e, pr_casesdef[i], &patch1);
6190 QCC_PR_ParseError(ERR_BADSWITCHTYPE, "Bad switch type");
6194 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3));
6198 if (e->type->type == ev_string)
6199 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch3));
6200 else if (e->type->type == ev_float)
6201 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch3));
6203 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch3));
6205 patch3->b = &statements[pr_cases[i]] - patch3;
6212 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch3));
6213 patch3->a = &statements[pr_cases[defaultcase]] - patch3;
6219 patch3 = &statements[numstatements];
6221 patch2->a = patch3 - patch2; //set P1 jump
6223 if (breaks != num_breaks)
6225 for(i = breaks; i < num_breaks; i++)
6227 patch2 = &statements[pr_breaks[i]];
6228 patch2->a = patch3 - patch2;
6230 num_breaks = breaks;
6241 if (QCC_PR_CheckKeyword(keyword_asm, "asm"))
6243 if (QCC_PR_CheckToken("{"))
6245 while (!QCC_PR_CheckToken("}"))
6253 if (QCC_PR_CheckToken(":"))
6255 if (pr_token_type != tt_name)
6257 QCC_PR_ParseError(ERR_BADLABELNAME, "invalid label name \"%s\"", pr_token);
6261 for (i = 0; i < num_labels; i++)
6262 if (!STRNCMP(pr_labels[i].name, pr_token, sizeof(pr_labels[num_labels].name) -1))
6264 QCC_PR_ParseWarning(WARN_DUPLICATELABEL, "Duplicate label %s", pr_token);
6269 if (num_labels >= max_labels)
6272 pr_labels = realloc(pr_labels, sizeof(*pr_labels)*max_labels);
6275 strncpy(pr_labels[num_labels].name, pr_token, sizeof(pr_labels[num_labels].name) -1);
6276 pr_labels[num_labels].lineno = pr_source_line;
6277 pr_labels[num_labels].statementno = numstatements;
6281 // QCC_PR_ParseWarning("Gotos are evil");
6285 if (QCC_PR_CheckKeyword(keyword_goto, "goto"))
6287 if (pr_token_type != tt_name)
6289 QCC_PR_ParseError(ERR_NOLABEL, "invalid label name \"%s\"", pr_token);
6293 QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2);
6295 QCC_PR_GotoStatement (patch2, pr_token);
6297 // QCC_PR_ParseWarning("Gotos are evil");
6303 if (QCC_PR_CheckKeyword(keyword_break, "break"))
6305 if (!STRCMP ("(", pr_token))
6306 { //make sure it wasn't a call to the break function.
6307 QCC_PR_IncludeChunk("break(", true, NULL);
6308 QCC_PR_Lex(); //so it sees the break.
6312 if (num_breaks >= max_breaks)
6315 pr_breaks = realloc(pr_breaks, sizeof(*pr_breaks)*max_breaks);
6317 pr_breaks[num_breaks] = numstatements;
6318 QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, NULL);
6324 if (QCC_PR_CheckKeyword(keyword_continue, "continue"))
6326 if (num_continues >= max_continues)
6329 pr_continues = realloc(pr_continues, sizeof(*pr_continues)*max_continues);
6331 pr_continues[num_continues] = numstatements;
6332 QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, NULL);
6337 if (QCC_PR_CheckKeyword(keyword_case, "case"))
6339 if (num_cases >= max_cases)
6342 pr_cases = realloc(pr_cases, sizeof(*pr_cases)*max_cases);
6343 pr_casesdef = realloc(pr_casesdef, sizeof(*pr_casesdef)*max_cases);
6344 pr_casesdef2 = realloc(pr_casesdef2, sizeof(*pr_casesdef2)*max_cases);
6346 pr_cases[num_cases] = numstatements;
6347 pr_casesdef[num_cases] = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
6348 if (QCC_PR_CheckToken(".."))
6350 pr_casesdef2[num_cases] = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
6351 if (pr_casesdef[num_cases]->constant && pr_casesdef2[num_cases]->constant &&
6352 !pr_casesdef[num_cases]->temp && !pr_casesdef2[num_cases]->temp)
6353 if (G_FLOAT(pr_casesdef[num_cases]->ofs) >= G_FLOAT(pr_casesdef2[num_cases]->ofs))
6354 QCC_PR_ParseError(ERR_CASENOTIMMEDIATE, "Caserange statement uses backwards range\n");
6357 pr_casesdef2[num_cases] = NULL;
6359 if (numstatements != pr_cases[num_cases])
6360 QCC_PR_ParseError(ERR_CASENOTIMMEDIATE, "Case statements may not use formulas\n");
6365 if (QCC_PR_CheckKeyword(keyword_default, "default"))
6367 if (num_cases >= max_cases)
6370 pr_cases = realloc(pr_cases, sizeof(*pr_cases)*max_cases);
6371 pr_casesdef = realloc(pr_casesdef, sizeof(*pr_casesdef)*max_cases);
6372 pr_casesdef2 = realloc(pr_casesdef2, sizeof(*pr_casesdef2)*max_cases);
6374 pr_cases[num_cases] = numstatements;
6375 pr_casesdef[num_cases] = NULL;
6376 pr_casesdef2[num_cases] = NULL;
6382 if (QCC_PR_CheckKeyword(keyword_thinktime, "thinktime"))
6384 QCC_def_t *nextthink;
6386 e = QCC_PR_Expression (TOP_PRIORITY, 0);
6388 e2 = QCC_PR_Expression (TOP_PRIORITY, 0);
6389 if (e->type->type != ev_entity || e2->type->type != ev_float)
6390 QCC_PR_ParseError(ERR_THINKTIMETYPEMISMATCH, "thinktime type mismatch");
6392 if (QCC_OPCodeValid(&pr_opcodes[OP_THINKTIME]))
6393 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_THINKTIME], e, e2, NULL));
6396 nextthink = QCC_PR_GetDef(NULL, "nextthink", NULL, false, 0, false);
6398 QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", "nextthink");
6399 time = QCC_PR_GetDef(type_float, "time", NULL, false, 0, false);
6401 QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", "time");
6402 nextthink = QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], e, nextthink, NULL);
6403 time = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], time, e2, NULL);
6404 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STOREP_F], time, nextthink, NULL));
6409 if (QCC_PR_CheckToken(";"))
6411 int osl = pr_source_line;
6412 pr_source_line = statementstart;
6413 if (!expandedemptymacro)
6414 QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Hanging ';'");
6415 pr_source_line = osl;
6419 // qcc_functioncalled=0;
6421 qcc_usefulstatement = false;
6422 e = QCC_PR_Expression (TOP_PRIORITY, 0);
6423 expandedemptymacro = false;
6424 QCC_PR_Expect (";");
6426 if (e->type->type != ev_void && !qcc_usefulstatement)
6428 int osl = pr_source_line;
6429 pr_source_line = statementstart;
6430 QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Effectless statement");
6431 pr_source_line = osl;
6436 // qcc_functioncalled=false;
6444 States are special functions made for convenience. They automatically
6445 set frame, nextthink (implicitly), and think (allowing forward definitions).
6447 // void() name = [framenum, nextthink] {code}
6449 // function void name ()
6451 // self.frame=framenum;
6452 // self.nextthink = time + 0.1;
6453 // self.think = nextthink
6458 void QCC_PR_ParseState (void)
6461 QCC_def_t *s1, *def, *sc = pr_scope;
6465 if (QCC_PR_CheckToken("++") || QCC_PR_CheckToken("--"))
6467 s1 = QCC_PR_ParseImmediate ();
6468 QCC_PR_Expect("..");
6469 def = QCC_PR_ParseImmediate ();
6470 QCC_PR_Expect ("]");
6472 if (s1->type->type != ev_float || def->type->type != ev_float)
6473 QCC_PR_ParseError(ERR_STATETYPEMISMATCH, "state type mismatch");
6476 if (QCC_OPCodeValid(&pr_opcodes[OP_CSTATE]))
6477 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CSTATE], s1, def, NULL));
6481 QCC_def_t *framef, *frame;
6483 QCC_def_t *cycle_wrapped;
6486 self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false);
6487 framef = QCC_PR_GetDef(NULL, "frame", NULL, false, 0, false);
6488 cycle_wrapped = QCC_PR_GetDef(type_float, "cycle_wrapped", NULL, false, 0, false);
6490 frame = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], self, framef, NULL);
6492 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(0), cycle_wrapped, NULL));
6493 QCC_UnFreeTemp(frame);
6495 //make sure the frame is within the bounds given.
6496 ftemp = frame->temp;
6498 t1 = QCC_PR_Statement(&pr_opcodes[OP_LT], frame, s1, NULL);
6499 t2 = QCC_PR_Statement(&pr_opcodes[OP_GT], frame, def, NULL);
6500 t1 = QCC_PR_Statement(&pr_opcodes[OP_OR], t1, t2, NULL);
6501 QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 2, 0, false);
6503 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
6504 QCC_PR_SimpleStatement(OP_GOTO, t1->ofs, 13, 0, false);
6506 t1 = QCC_PR_Statement(&pr_opcodes[OP_GE], def, s1, NULL);
6507 QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 7, 0, false);
6508 QCC_FreeTemp(t1); //this block is the 'it's in a forwards direction'
6509 QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
6510 t1 = QCC_PR_Statement(&pr_opcodes[OP_GT], frame, def, NULL);
6511 QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false);
6513 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
6514 QCC_UnFreeTemp(frame);
6516 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL));
6518 QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false);
6519 //reverse animation.
6520 QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
6521 t1 = QCC_PR_Statement(&pr_opcodes[OP_LT], frame, s1, NULL);
6522 QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false);
6524 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL));
6525 QCC_UnFreeTemp(frame);
6527 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL));
6529 //self.frame = frame happens with the normal state opcode.
6530 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], frame, pr_scope, NULL));
6532 frame->temp = ftemp;
6533 QCC_FreeTemp(frame);
6538 if (pr_token_type != tt_immediate || pr_immediate_type != type_float)
6539 QCC_PR_ParseError (ERR_STATETYPEMISMATCH, "state frame must be a number");
6540 s1 = QCC_PR_ParseImmediate ();
6542 QCC_PR_CheckToken (",");
6544 name = QCC_PR_ParseName ();
6546 def = QCC_PR_GetDef (type_function, name, NULL, true, 1, false);
6549 QCC_PR_Expect ("]");
6551 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], s1, def, NULL));
6554 void QCC_PR_ParseAsm(void)
6556 QCC_dstatement_t *patch1;
6558 QCC_def_t *a, *b, *c;
6560 if (QCC_PR_CheckKeyword(keyword_local, "local"))
6562 QCC_PR_ParseDefs (NULL);
6563 locals_end = numpr_globals;
6567 for (op = 0; op < OP_NUMOPS; op++)
6569 if (!STRCMP(pr_token, pr_opcodes[op].opname))
6572 if (pr_opcodes[op].priority==-1 && pr_opcodes[op].associative!=ASSOC_LEFT)
6574 if (pr_opcodes[op].type_a==NULL)
6576 patch1 = &statements[numstatements];
6578 QCC_PR_Statement3(&pr_opcodes[op], NULL, NULL, NULL, true);
6580 if (pr_token_type == tt_name)
6582 QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
6586 p = (int)pr_immediate._float;
6592 else if (pr_opcodes[op].type_b==NULL)
6594 patch1 = &statements[numstatements];
6596 a = QCC_PR_ParseValue(pr_classtype, false);
6597 QCC_PR_Statement3(&pr_opcodes[op], a, NULL, NULL, true);
6599 if (pr_token_type == tt_name)
6601 QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
6605 p = (int)pr_immediate._float;
6613 patch1 = &statements[numstatements];
6615 a = QCC_PR_ParseValue(pr_classtype, false);
6616 b = QCC_PR_ParseValue(pr_classtype, false);
6617 QCC_PR_Statement3(&pr_opcodes[op], a, b, NULL, true);
6619 if (pr_token_type == tt_name)
6621 QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
6625 p = (int)pr_immediate._float;
6634 if (pr_opcodes[op].type_a != &type_void)
6635 a = QCC_PR_ParseValue(pr_classtype, false);
6638 if (pr_opcodes[op].type_b != &type_void)
6639 b = QCC_PR_ParseValue(pr_classtype, false);
6642 if (pr_opcodes[op].associative==ASSOC_LEFT && pr_opcodes[op].type_c != &type_void)
6643 c = QCC_PR_ParseValue(pr_classtype, false);
6647 QCC_PR_Statement3(&pr_opcodes[op], a, b, c, true);
6654 QCC_PR_ParseError(ERR_BADOPCODE, "Bad op code name %s", pr_token);
6657 pbool QCC_FuncJumpsTo(int first, int last, int statement)
6660 for (st = first; st < last; st++)
6662 if (pr_opcodes[statements[st].op].type_a == NULL)
6664 if (st + (signed)statements[st].a == statement)
6668 if (statements[st-1].op == OP_RETURN)
6670 if (statements[st-1].op == OP_DONE)
6676 if (pr_opcodes[statements[st].op].type_b == NULL)
6678 if (st + (signed)statements[st].b == statement)
6682 if (statements[st-1].op == OP_RETURN)
6684 if (statements[st-1].op == OP_DONE)
6690 if (pr_opcodes[statements[st].op].type_c == NULL)
6692 if (st + (signed)statements[st].c == statement)
6696 if (statements[st-1].op == OP_RETURN)
6698 if (statements[st-1].op == OP_DONE)
6708 pbool QCC_FuncJumpsToRange(int first, int last, int firstr, int lastr)
6711 for (st = first; st < last; st++)
6713 if (pr_opcodes[statements[st].op].type_a == NULL)
6715 if (st + (signed)statements[st].a >= firstr && st + (signed)statements[st].a <= lastr)
6719 if (statements[st-1].op == OP_RETURN)
6721 if (statements[st-1].op == OP_DONE)
6727 if (pr_opcodes[statements[st].op].type_b == NULL)
6729 if (st + (signed)statements[st].b >= firstr && st + (signed)statements[st].b <= lastr)
6733 if (statements[st-1].op == OP_RETURN)
6735 if (statements[st-1].op == OP_DONE)
6741 if (pr_opcodes[statements[st].op].type_c == NULL)
6743 if (st + (signed)statements[st].c >= firstr && st + (signed)statements[st].c <= lastr)
6747 if (statements[st-1].op == OP_RETURN)
6749 if (statements[st-1].op == OP_DONE)
6760 void QCC_CompoundJumps(int first, int last)
6762 //jumps to jumps are reordered so they become jumps to the final target.
6765 for (st = first; st < last; st++)
6767 if (pr_opcodes[statements[st].op].type_a == NULL)
6769 statement = st + (signed)statements[st].a;
6770 if (statements[statement].op == OP_RETURN || statements[statement].op == OP_DONE)
6771 { //goto leads to return. Copy the command out to remove the goto.
6772 statements[st].op = statements[statement].op;
6773 statements[st].a = statements[statement].a;
6774 statements[st].b = statements[statement].b;
6775 statements[st].c = statements[statement].c;
6776 optres_compound_jumps++;
6778 while (statements[statement].op == OP_GOTO)
6780 statements[st].a = statement+statements[statement].a - st;
6781 statement = st + (signed)statements[st].a;
6782 optres_compound_jumps++;
6785 if (pr_opcodes[statements[st].op].type_b == NULL)
6787 statement = st + (signed)statements[st].b;
6788 while (statements[statement].op == OP_GOTO)
6790 statements[st].b = statement+statements[statement].a - st;
6791 statement = st + (signed)statements[st].b;
6792 optres_compound_jumps++;
6795 if (pr_opcodes[statements[st].op].type_c == NULL)
6797 statement = st + (signed)statements[st].c;
6798 while (statements[statement].op == OP_GOTO)
6800 statements[st].c = statement+statements[statement].a - st;
6801 statement = st + (signed)statements[st].c;
6802 optres_compound_jumps++;
6808 void QCC_CompoundJumps(int first, int last)
6810 //jumps to jumps are reordered so they become jumps to the final target.
6814 for (st = first; st < last; st++)
6816 if (pr_opcodes[statements[st].op].type_a == NULL)
6818 statement = st + (signed)statements[st].a;
6819 if (statements[statement].op == OP_RETURN || statements[statement].op == OP_DONE)
6820 { //goto leads to return. Copy the command out to remove the goto.
6821 statements[st].op = statements[statement].op;
6822 statements[st].a = statements[statement].a;
6823 statements[st].b = statements[statement].b;
6824 statements[st].c = statements[statement].c;
6825 optres_compound_jumps++;
6828 while (statements[statement].op == OP_GOTO)
6832 QCC_PR_ParseWarning(0, "Infinate loop detected");
6835 statements[st].a = (statement+statements[statement].a - st);
6836 statement = st + (signed)statements[st].a;
6837 optres_compound_jumps++;
6840 if (pr_opcodes[statements[st].op].type_b == NULL)
6842 statement = st + (signed)statements[st].b;
6844 while (statements[statement].op == OP_GOTO)
6848 QCC_PR_ParseWarning(0, "Infinate loop detected");
6851 statements[st].b = (statement+statements[statement].a - st);
6852 statement = st + (signed)statements[st].b;
6853 optres_compound_jumps++;
6856 if (pr_opcodes[statements[st].op].type_c == NULL)
6858 statement = st + (signed)statements[st].c;
6860 while (statements[statement].op == OP_GOTO)
6864 QCC_PR_ParseWarning(0, "Infinate loop detected");
6867 statements[st].c = (statement+statements[statement].a - st);
6868 statement = st + (signed)statements[st].c;
6869 optres_compound_jumps++;
6876 void QCC_CheckForDeadAndMissingReturns(int first, int last, int rettype)
6880 if (statements[last-1].op == OP_DONE)
6881 last--; //don't want the done
6883 if (rettype != ev_void)
6884 if (statements[last-1].op != OP_RETURN)
6886 if (statements[last-1].op != OP_GOTO || (signed)statements[last-1].a > 0)
6888 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
6893 for (st = first; st < last; st++)
6895 if (statements[st].op == OP_RETURN || statements[st].op == OP_GOTO)
6899 continue; //erm... end of function doesn't count as unreachable.
6901 if (!opt_compound_jumps)
6902 { //we can ignore single statements like these without compound jumps (compound jumps correctly removes all).
6903 if (statements[st].op == OP_GOTO) //inefficient compiler, we can ignore this.
6905 if (statements[st].op == OP_DONE) //inefficient compiler, we can ignore this.
6907 if (statements[st].op == OP_RETURN) //inefficient compiler, we can ignore this.
6911 //make sure something goes to just after this return.
6912 for (st2 = first; st2 < last; st2++)
6914 if (pr_opcodes[statements[st2].op].type_a == NULL)
6916 if (st2 + (signed)statements[st2].a == st)
6919 if (pr_opcodes[statements[st2].op].type_b == NULL)
6921 if (st2 + (signed)statements[st2].b == st)
6924 if (pr_opcodes[statements[st2].op].type_c == NULL)
6926 if (st2 + (signed)statements[st2].c == st)
6932 QCC_PR_ParseWarning(WARN_UNREACHABLECODE, "%s: contains unreachable code", pr_scope->name );
6936 if (rettype != ev_void)
6938 if (pr_opcodes[statements[st].op].type_a == NULL)
6940 if (st + (signed)statements[st].a == last)
6942 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
6946 if (pr_opcodes[statements[st].op].type_b == NULL)
6948 if (st + (signed)statements[st].b == last)
6950 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
6954 if (pr_opcodes[statements[st].op].type_c == NULL)
6956 if (st + (signed)statements[st].c == last)
6958 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
6966 pbool QCC_StatementIsAJump(int stnum, int notifdest) //only the unconditionals.
6968 if (statements[stnum].op == OP_RETURN)
6970 if (statements[stnum].op == OP_DONE)
6972 if (statements[stnum].op == OP_GOTO)
6973 if ((int)statements[stnum].a != notifdest)
6978 int QCC_AStatementJumpsTo(int targ, int first, int last)
6981 for (st = first; st < last; st++)
6983 if (pr_opcodes[statements[st].op].type_a == NULL)
6985 if (st + (signed)statements[st].a == targ && statements[st].a)
6990 if (pr_opcodes[statements[st].op].type_b == NULL)
6992 if (st + (signed)statements[st].b == targ)
6997 if (pr_opcodes[statements[st].op].type_c == NULL)
6999 if (st + (signed)statements[st].c == targ)
7006 for (st = 0; st < num_labels; st++) //assume it's used.
7008 if (pr_labels[st].statementno == targ)
7016 //goes through statements, if it sees a matching statement earlier, it'll strim out the current.
7017 void QCC_CommonSubExpressionRemoval(int first, int last)
7019 int cur; //the current
7020 int prev; //the earlier statement
7021 for (cur = last-1; cur >= first; cur--)
7023 if (pr_opcodes[statements[cur].op].priority == -1)
7025 for (prev = cur-1; prev >= first; prev--)
7027 if (statements[prev].op >= OP_CALL0 && statements[prev].op <= OP_CALL8)
7032 if (statements[prev].op >= OP_CALL1H && statements[prev].op <= OP_CALL8H)
7037 if (pr_opcodes[statements[prev].op].right_associative)
7038 { //make sure no changes to var_a occur.
7039 if (statements[prev].b == statements[cur].a)
7044 if (statements[prev].b == statements[cur].b && !pr_opcodes[statements[cur].op].right_associative)
7052 if (statements[prev].c == statements[cur].a)
7057 if (statements[prev].c == statements[cur].b && !pr_opcodes[statements[cur].op].right_associative)
7064 if (statements[prev].op == statements[cur].op)
7065 if (statements[prev].a == statements[cur].a)
7066 if (statements[prev].b == statements[cur].b)
7067 if (statements[prev].c == statements[cur].c)
7069 if (!QCC_FuncJumpsToRange(first, last, prev, cur))
7071 statements[cur].op = OP_STORE_F;
7072 statements[cur].a = 28;
7073 statements[cur].b = 28;
7074 optres_comexprremoval++;
7085 void QCC_RemapOffsets(unsigned int firststatement, unsigned int laststatement, unsigned int min, unsigned int max, unsigned int newmin)
7087 QCC_dstatement_t *st;
7090 for (i = firststatement, st = &statements[i]; i < laststatement; i++, st++)
7092 if (pr_opcodes[st->op].type_a && st->a >= min && st->a < max)
7093 st->a = st->a - min + newmin;
7094 if (pr_opcodes[st->op].type_b && st->b >= min && st->b < max)
7095 st->b = st->b - min + newmin;
7096 if (pr_opcodes[st->op].type_c && st->c >= min && st->c < max)
7097 st->c = st->c - min + newmin;
7101 void QCC_Marshal_Locals(int first, int laststatement)
7104 unsigned int newofs;
7106 // if (!opt_overlaptemps) //clear these after each function. we arn't overlapping them so why do we need to keep track of them?
7109 // for (t = functemps; t; t = t->next)
7110 // QCC_FreeOffset(t->ofs, t->size);
7111 // functemps = NULL;
7114 if (!pr.localvars) //nothing to marshal
7116 locals_start = numpr_globals;
7117 locals_end = numpr_globals;
7121 if (!opt_locals_marshalling)
7123 pr.localvars = NULL;
7127 //initial backwards bounds.
7128 locals_start = MAX_REGS;
7131 newofs = MAX_REGS; //this is a handy place to put it. :)
7133 //the params need to be in the order that they were allocated
7134 //so we allocate in a backwards order.
7135 for (local = pr.localvars; local; local = local->nextlocal)
7137 if (local->constant)
7140 newofs += local->type->size*local->arraysize;
7141 if (local->arraysize>1)
7145 locals_start = MAX_REGS;
7146 locals_end = newofs;
7149 optres_locals_marshalling+=newofs-MAX_REGS;
7151 for (local = pr.localvars; local; local = local->nextlocal)
7153 if (local->constant)
7156 if (((int*)qcc_pr_globals)[local->ofs])
7157 QCC_PR_ParseError(ERR_INTERNAL, "Marshall of a set value");
7159 newofs -= local->type->size*local->arraysize;
7160 if (local->arraysize>1)
7163 QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+local->type->size*local->arraysize, newofs);
7164 QCC_FreeOffset(local->ofs, local->type->size*local->arraysize);
7166 local->ofs = newofs;
7170 pr.localvars = NULL;
7174 void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t firstparm)
7186 fprintf(asmfile, "%s(", TypeName(type->aux_type));
7187 p = type->num_parms;
7188 for (o = firstparm, i = 0, type = type->param; i < p; i++, type = type->next)
7191 fprintf(asmfile, ", ");
7193 for (param = pr.localvars; param; param = param->nextlocal)
7195 if (param->ofs == o)
7199 fprintf(asmfile, "%s %s", TypeName(type), param->name);
7201 fprintf(asmfile, "%s", TypeName(type));
7206 fprintf(asmfile, ") %s = asm\n{\n", sc->name);
7208 QCC_fprintfLocals(asmfile, firstparm, o);
7210 for (i = firststatement; i < (unsigned int)numstatements; i++)
7212 fprintf(asmfile, "\t%s", pr_opcodes[statements[i].op].opname);
7213 if (pr_opcodes[statements[i].op].type_a != &type_void)
7215 if (strlen(pr_opcodes[statements[i].op].opname)<6)
7216 fprintf(asmfile, "\t");
7217 if (pr_opcodes[statements[i].op].type_a)
7218 fprintf(asmfile, "\t%s", QCC_VarAtOffset(statements[i].a, (*pr_opcodes[statements[i].op].type_a)->size));
7220 fprintf(asmfile, "\t%i", statements[i].a);
7221 if (pr_opcodes[statements[i].op].type_b != &type_void)
7223 if (pr_opcodes[statements[i].op].type_b)
7224 fprintf(asmfile, ",\t%s", QCC_VarAtOffset(statements[i].b, (*pr_opcodes[statements[i].op].type_b)->size));
7226 fprintf(asmfile, ",\t%i", statements[i].b);
7227 if (pr_opcodes[statements[i].op].type_c != &type_void && pr_opcodes[statements[i].op].associative==ASSOC_LEFT)
7229 if (pr_opcodes[statements[i].op].type_c)
7230 fprintf(asmfile, ",\t%s", QCC_VarAtOffset(statements[i].c, (*pr_opcodes[statements[i].op].type_c)->size));
7232 fprintf(asmfile, ",\t%i", statements[i].c);
7237 if (pr_opcodes[statements[i].op].type_c != &type_void)
7239 if (pr_opcodes[statements[i].op].type_c)
7240 fprintf(asmfile, ",\t%s", QCC_VarAtOffset(statements[i].c, (*pr_opcodes[statements[i].op].type_c)->size));
7242 fprintf(asmfile, ",\t%i", statements[i].c);
7246 fprintf(asmfile, ";\n");
7249 fprintf(asmfile, "}\n\n");
7255 PR_ParseImmediateStatements
7257 Parse a function body
7260 QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
7264 QCC_def_t *defs[MAX_PARMS+MAX_EXTRA_PARMS], *e2;
7267 pbool needsdone=false;
7268 freeoffset_t *oldfofs;
7272 expandedemptymacro = false;
7275 f = (void *)qccHunkAlloc (sizeof(QCC_function_t));
7278 // check for builtin function definition #1, #2, etc
7280 // hexenC has void name() : 2;
7281 if (QCC_PR_CheckToken ("#") || QCC_PR_CheckToken (":"))
7284 if (pr_token_type == tt_immediate
7285 && pr_immediate_type == type_float
7286 && pr_immediate._float == (int)pr_immediate._float)
7287 binum = (int)pr_immediate._float;
7288 else if (pr_token_type == tt_immediate && pr_immediate_type == type_integer)
7289 binum = pr_immediate._int;
7291 QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
7295 locals_start = locals_end = OFS_PARM0; //hmm...
7298 if (QCC_PR_CheckKeyword(keyword_external, "external"))
7299 { //reacc style builtin
7300 if (pr_token_type != tt_immediate
7301 || pr_immediate_type != type_float
7302 || pr_immediate._float != (int)pr_immediate._float)
7303 QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
7304 f->builtin = (int)-pr_immediate._float;
7308 locals_start = locals_end = OFS_PARM0; //hmm...
7312 if (type->num_parms < 0)
7313 QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
7320 locals_start = locals_end = numpr_globals;
7326 for (i=0 ; i<type->num_parms ; i++)
7328 if (!*pr_parm_names[i])
7329 QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named");
7330 defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 1, false);
7332 defs[i]->references++;
7335 f->parm_ofs[i] = defs[i]->ofs;
7336 if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i-1])
7337 QCC_Error (ERR_BADPARAMORDER, "bad parm order");
7338 if (i > 0 && f->parm_ofs[i] != f->parm_ofs[i-1]+defs[i-1]->type->size)
7339 QCC_Error (ERR_BADPARAMORDER, "parms not packed");
7344 if (type->num_parms)
7345 locals_start = locals_end = defs[0]->ofs;
7349 f->code = numstatements;
7351 if (type->num_parms > MAX_PARMS)
7353 for (i = MAX_PARMS; i < type->num_parms; i++)
7355 if (!extra_parms[i - MAX_PARMS])
7357 e2 = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t));
7358 e2->name = "extra parm";
7359 e2->ofs = QCC_GetFreeOffsetSpace(3);
7360 extra_parms[i - MAX_PARMS] = e2;
7362 extra_parms[i - MAX_PARMS]->type = defs[i]->type;
7363 if (defs[i]->type->type != ev_vector)
7364 QCC_PR_Statement (&pr_opcodes[OP_STORE_F], extra_parms[i - MAX_PARMS], defs[i], NULL);
7366 QCC_PR_Statement (&pr_opcodes[OP_STORE_V], extra_parms[i - MAX_PARMS], defs[i], NULL);
7370 QCC_RemapLockedTemps(-1, -1);
7375 e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 1);
7376 e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 1);
7377 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), e, NULL));
7381 // check for a state opcode
7383 if (QCC_PR_CheckToken ("["))
7384 QCC_PR_ParseState ();
7386 if (QCC_PR_CheckKeyword (keyword_asm, "asm"))
7388 QCC_PR_Expect ("{");
7389 while (!QCC_PR_CheckToken("}"))
7394 if (QCC_PR_CheckKeyword (keyword_var, "var")) //reacc support
7395 { //parse lots of locals
7398 name = QCC_PR_ParseName();
7400 e2 = QCC_PR_GetDef(QCC_PR_ParseType(false), name, pr_scope, true, 1, false);
7402 } while(!QCC_PR_CheckToken("{"));
7405 QCC_PR_Expect ("{");
7407 // parse regular statements
7409 while (!QCC_PR_CheckToken("}"))
7411 QCC_PR_ParseStatement ();
7418 // if (type->aux_type->type)
7419 // if (statements[numstatements - 1].op != OP_RETURN)
7420 // QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
7422 if (f->code == numstatements)
7424 else if (statements[numstatements - 1].op != OP_RETURN && statements[numstatements - 1].op != OP_DONE)
7430 for (i = 0; i < num_gotos; i++)
7432 for (j = 0; j < num_labels; j++)
7434 if (!strcmp(pr_gotos[i].name, pr_labels[j].name))
7436 if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_a)
7437 statements[pr_gotos[i].statementno].a += pr_labels[j].statementno - pr_gotos[i].statementno;
7438 else if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_b)
7439 statements[pr_gotos[i].statementno].b += pr_labels[j].statementno - pr_gotos[i].statementno;
7441 statements[pr_gotos[i].statementno].c += pr_labels[j].statementno - pr_gotos[i].statementno;
7445 if (j == num_labels)
7448 QCC_PR_ParseError(ERR_NOLABEL, "Goto statement with no matching label \"%s\"", pr_gotos[i].name);
7454 if (opt_return_only && !needsdone)
7455 needsdone = QCC_FuncJumpsTo(f->code, numstatements, numstatements);
7457 // emit an end of statements opcode
7458 if (!opt_return_only || needsdone)
7463 e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
7464 e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
7465 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL));
7468 QCC_PR_Statement (pr_opcodes, 0,0, NULL);
7471 optres_return_only++;
7473 QCC_CheckForDeadAndMissingReturns(f->code, numstatements, type->aux_type->type);
7475 if (opt_compound_jumps)
7476 QCC_CompoundJumps(f->code, numstatements);
7477 // if (opt_comexprremoval)
7478 // QCC_CommonSubExpressionRemoval(f->code, numstatements);
7481 QCC_RemapLockedTemps(f->code, numstatements);
7482 locals_end = numpr_globals;
7484 QCC_WriteAsmFunction(pr_scope, f->code, locals_start);
7486 QCC_Marshal_Locals(f->code, numstatements);
7495 QCC_PR_ParseError(ERR_ILLEGALCONTINUES, "%s: function contains illegal continues", pr_scope->name);
7500 QCC_PR_ParseError(ERR_ILLEGALBREAKS, "%s: function contains illegal breaks", pr_scope->name);
7505 QCC_PR_ParseError(ERR_ILLEGALCASES, "%s: function contains illegal cases", pr_scope->name);
7511 void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int min, int max)
7513 QCC_dstatement_t *st;
7515 if (min == max || min+1 == max)
7517 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(min+0.5f), NULL);
7518 QCC_UnFreeTemp(index);
7519 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7521 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7522 st->a = array->ofs + min*array->type->size;
7526 int mid = min + (max-min)/2;
7530 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(mid+0.5f), NULL);
7531 QCC_UnFreeTemp(index);
7532 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7536 QCC_PR_ArrayRecurseDivideRegular(array, index, min, mid);
7538 st->b = numstatements - (st-statements);
7539 QCC_PR_ArrayRecurseDivideRegular(array, index, mid, max);
7543 //the idea here is that we return a vector, the caller then figures out the extra 3rd.
7544 //This is useful when we have a load of indexes.
7545 void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, int min, int max)
7547 QCC_dstatement_t *st;
7549 if (min == max || min+1 == max)
7551 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(min+0.5f), NULL);
7552 QCC_UnFreeTemp(index);
7553 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7555 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7556 st->a = array->ofs + min*3;
7560 int mid = min + (max-min)/2;
7564 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(mid+0.5f), NULL);
7565 QCC_UnFreeTemp(index);
7566 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7570 QCC_PR_ArrayRecurseDivideUsingVectors(array, index, min, mid);
7572 st->b = numstatements - (st-statements);
7573 QCC_PR_ArrayRecurseDivideUsingVectors(array, index, mid, max);
7577 //returns a vector overlapping the result needed.
7578 QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array)
7580 QCC_dfunction_t *df;
7581 QCC_def_t *temp, *index, *func;
7583 func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 1, false);
7587 df = &functions[numfunctions];
7591 df->s_name = QCC_CopyString(func->name);
7592 df->first_statement = numstatements;
7593 df->parm_size[0] = 1;
7595 df->parm_start = numpr_globals;
7596 index = QCC_PR_GetDef(type_float, "index___", func, true, 1, false);
7597 index->references++;
7598 temp = QCC_PR_GetDef(type_float, "div3___", func, true, 1, false);
7599 locals_end = numpr_globals;
7600 df->locals = locals_end - df->parm_start;
7601 QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), temp, false);
7602 QCC_PR_Statement3(pr_opcodes+OP_BITAND, temp, temp, temp, false);//round down to int
7604 QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3); //round up
7606 QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL); //err... we didn't find it, give up.
7607 QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); //err... we didn't find it, give up.
7609 G_FUNCTION(func->ofs) = df - functions;
7610 func->initialized = 1;
7614 void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
7616 QCC_def_t *vectortrick;
7617 QCC_dfunction_t *df;
7618 QCC_def_t *def, *index;
7620 QCC_dstatement_t *st;
7623 QCC_def_t *fasttrackpossible;
7625 if (flag_fasttrackarrays)
7626 fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false);
7628 fasttrackpossible = NULL;
7630 def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
7632 if (def->arraysize >= 15 && def->type->size == 1)
7634 vectortrick = QCC_PR_EmitArrayGetVector(def);
7641 df = &functions[numfunctions];
7645 df->s_name = QCC_CopyString(scope->name);
7646 df->first_statement = numstatements;
7647 df->parm_size[0] = 1;
7649 df->parm_start = numpr_globals;
7650 index = QCC_PR_GetDef(type_float, "indexg___", def, true, 1, false);
7652 G_FUNCTION(scope->ofs) = df - functions;
7654 if (fasttrackpossible)
7656 QCC_PR_Statement(pr_opcodes+OP_IFNOT, fasttrackpossible, NULL, &st);
7657 //fetch_gbl takes: (float size, variant array[]), float index, variant pos
7658 //note that the array size is coded into the globals, one index before the array.
7660 if (def->type->size >= 3)
7661 QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_V], def, index, &def_ret, true);
7663 QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_F], def, index, &def_ret, true);
7665 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_RETURN], &def_ret, NULL, NULL));
7668 st->b = &statements[numstatements] - st;
7673 QCC_def_t *div3, *intdiv3, *ret;
7675 //okay, we've got a function to retrieve the var as part of a vector.
7676 //we need to work out which part, x/y/z that it's stored in.
7677 //0,1,2 = i - ((int)i/3 *) 3;
7679 div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 1, false);
7680 intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 1, false);
7682 eq = QCC_PR_Statement(pr_opcodes+OP_GE, index, QCC_MakeFloatDef((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule!
7683 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7685 QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, &st);
7688 QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false);
7689 QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), div3, false);
7690 QCC_PR_Statement3(pr_opcodes+OP_BITAND, div3, div3, intdiv3, false);
7692 QCC_PR_Statement3(pr_opcodes+OP_STORE_F, index, &def_parms[0], NULL, false);
7693 QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, NULL, false);
7694 vectortrick->references++;
7695 ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 1, false);
7697 QCC_PR_Statement3(pr_opcodes+OP_STORE_V, &def_ret, ret, NULL, false);
7698 QCC_FreeTemp(&def_ret);
7700 div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatDef(3), NULL);
7701 QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false);
7704 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(0+0.5f), NULL);
7705 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7707 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7708 st->a = ret->ofs + 0;
7710 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(1+0.5f), NULL);
7711 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7713 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7714 st->a = ret->ofs + 1;
7716 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(2+0.5), NULL);
7717 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7719 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7720 st->a = ret->ofs + 2;
7722 QCC_FreeTemp(index);
7726 QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false);
7727 QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize);
7730 QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL);
7732 QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
7734 locals_end = numpr_globals;
7735 df->locals = locals_end - df->parm_start;
7738 QCC_WriteAsmFunction(pr_scope, df->first_statement, df->parm_start);
7743 void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t *value, int min, int max)
7745 QCC_dstatement_t *st;
7747 if (min == max || min+1 == max)
7749 eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatDef((float)min), NULL);
7750 QCC_UnFreeTemp(index);
7751 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7753 if (array->type->size == 3)
7754 QCC_PR_Statement(pr_opcodes+OP_STORE_V, value, array, &st);
7756 QCC_PR_Statement(pr_opcodes+OP_STORE_F, value, array, &st);
7757 st->b = array->ofs + min*array->type->size;
7758 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7762 int mid = min + (max-min)/2;
7766 eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef((float)mid), NULL);
7767 QCC_UnFreeTemp(index);
7768 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
7772 QCC_PR_ArraySetRecurseDivide(array, index, value, min, mid);
7774 st->b = numstatements - (st-statements);
7775 QCC_PR_ArraySetRecurseDivide(array, index, value, mid, max);
7779 void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
7781 QCC_dfunction_t *df;
7782 QCC_def_t *def, *index, *value;
7784 QCC_def_t *fasttrackpossible;
7786 if (flag_fasttrackarrays)
7787 fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false);
7789 fasttrackpossible = NULL;
7791 def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
7794 df = &functions[numfunctions];
7798 df->s_name = QCC_CopyString(scope->name);
7799 df->first_statement = numstatements;
7800 df->parm_size[0] = 1;
7801 df->parm_size[1] = def->type->size;
7803 df->parm_start = numpr_globals;
7804 index = QCC_PR_GetDef(type_float, "indexs___", def, true, 1, false);
7805 value = QCC_PR_GetDef(def->type, "value___", def, true, 1, false);
7806 locals_end = numpr_globals;
7807 df->locals = locals_end - df->parm_start;
7809 G_FUNCTION(scope->ofs) = df - functions;
7811 if (fasttrackpossible)
7813 QCC_dstatement_t *st;
7815 QCC_PR_Statement(pr_opcodes+OP_IFNOT, fasttrackpossible, NULL, &st);
7816 //note that the array size is coded into the globals, one index before the array.
7818 QCC_PR_Statement3(&pr_opcodes[OP_CONV_FTOI], index, NULL, index, true); //address stuff is integer based, but standard qc (which this accelerates in supported engines) only supports floats
7819 QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1]+1, 0, true);//annoy the programmer. :p
7820 if (def->type->size != 1)//shift it upwards for larger types
7821 QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntDef(def->type->size), index, true);
7822 QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], def, index, index, true); //comes with built in add
7823 if (def->type->size >= 3)
7824 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_V], value, index, NULL, true); //*b = a
7826 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], value, index, NULL, true);
7827 QCC_PR_Statement(&pr_opcodes[OP_RETURN], value, NULL, NULL);
7830 st->b = &statements[numstatements] - st;
7833 QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false);
7834 QCC_PR_ArraySetRecurseDivide(def, index, value, 0, def->arraysize);
7836 QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
7840 QCC_WriteAsmFunction(pr_scope, df->first_statement, df->parm_start);
7845 //register a def, and all of it's sub parts.
7846 //only the main def is of use to the compiler.
7847 //the subparts are emitted to the compiler and allow correct saving/loading
7848 //be careful with fields, this doesn't allocated space, so will it allocate fields. It only creates defs at specified offsets.
7849 QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable, pbool saved)
7854 QCC_def_t *def, *first=NULL;
7856 #define KEYWORD(x) if (!STRCMP(name, #x) && keyword_##x) {if (keyword_##x)QCC_PR_ParseWarning(WARN_KEYWORDDISABLED, "\""#x"\" keyword used as variable name%s", keywords_coexist?" - coexisting":" - disabling");keyword_##x=keywords_coexist;}
7866 if (type->type != ev_function)
7871 if (qcc_targetformat != QCF_HEXEN2)
7872 KEYWORD(float); //hmm... hexen2 requires this...
7879 for (a = 0; a < arraysize; a++)
7884 sprintf(array, "[%i]", a);
7887 sprintf(newname, "%s%s", name, array);
7891 // allocate a new def
7892 def = (void *)qccHunkAlloc (sizeof(QCC_def_t));
7893 memset (def, 0, sizeof(*def));
7895 def->arraysize = arraysize;
7898 pr.def_tail->next = def;
7905 def->s_line = pr_source_line;
7906 def->s_file = s_file;
7908 def->name = (void *)qccHunkAlloc (strlen(newname)+1);
7909 strcpy (def->name, newname);
7916 def->constant = true;
7918 if (ofs + type->size*a >= MAX_REGS)
7919 QCC_Error(ERR_TOOMANYGLOBALS, "MAX_REGS is too small");
7920 def->ofs = ofs + type->size*a;
7924 // printf("Emited %s\n", newname);
7926 if (type->type == ev_struct)
7929 QCC_type_t *parttype;
7930 parttype = type->param;
7931 for (partnum = 0; partnum < type->num_parms; partnum++)
7933 switch (parttype->type)
7936 sprintf(newname, "%s%s.%s", name, array, parttype->name);
7937 QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved);
7939 sprintf(newname, "%s%s.%s_x", name, array, parttype->name);
7940 QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, false);
7941 sprintf(newname, "%s%s.%s_y", name, array, parttype->name);
7942 QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+1, false, false);
7943 sprintf(newname, "%s%s.%s_z", name, array, parttype->name);
7944 QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+2, false, false);
7955 case ev_variant: //for lack of any better alternative
7956 sprintf(newname, "%s%s.%s", name, array, parttype->name);
7957 QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved);
7961 sprintf(newname, "%s%s.%s", name, array, parttype->name);
7962 QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true;
7967 parttype=parttype->next;
7970 else if (type->type == ev_vector)
7971 { //do the vector thing.
7972 sprintf(newname, "%s%s_x", name, array);
7973 QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+0, referable, false);
7974 sprintf(newname, "%s%s_y", name, array);
7975 QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+1, referable, false);
7976 sprintf(newname, "%s%s_z", name, array);
7977 QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+2, referable, false);
7979 else if (type->type == ev_field)
7981 if (type->aux_type->type == ev_vector)
7983 //do the vector thing.
7984 sprintf(newname, "%s%s_x", name, array);
7985 QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+0, referable, false);
7986 sprintf(newname, "%s%s_y", name, array);
7987 QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+1, referable, false);
7988 sprintf(newname, "%s%s_z", name, array);
7989 QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+2, referable, false);
7996 if (!pHash_Get(&globalstable, "end_sys_fields"))
7997 first->references++; //anything above needs to be left in, and so warning about not using it is just going to pee people off.
7999 first->constant = false;
8001 pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
8003 pHash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
8005 if (!scope && asmfile)
8006 fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name);
8016 If type is NULL, it will match any type
8017 If allocate is true, a new def will be allocated if it can't be found
8021 QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool allocate, int arraysize, pbool saved)
8025 // char element[MAX_NAME];
8027 QCC_def_t *foundstatic = NULL;
8031 def = Hash_Get(&localstable, name);
8035 if ( def->scope && def->scope != scope)
8037 def = Hash_GetNext(&localstable, name, def);
8038 continue; // in a different function
8041 if (type && typecmp(def->type, type))
8042 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8043 if (def->arraysize != arraysize && arraysize)
8044 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
8045 if (allocate && scope)
8047 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8048 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8050 // QCC_PR_ParsePrintDef(def);
8057 def = Hash_Get(&globalstable, name);
8061 if ( def->scope && def->scope != scope)
8063 def = Hash_GetNext(&globalstable, name, def);
8064 continue; // in a different function
8067 if (def->isstatic && def->s_file != s_file)
8068 { //warn? or would that be pointless?
8070 def = Hash_GetNext(&globalstable, name, def);
8071 continue; // in a different function
8074 if (type && typecmp(def->type, type))
8077 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8079 if (def->arraysize != arraysize && arraysize)
8080 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
8081 if (allocate && scope)
8084 { //warn? or would that be pointless?
8085 def = Hash_GetNext(&globalstable, name, def);
8086 continue; // in a different function
8089 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8090 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8092 // QCC_PR_ParsePrintDef(def);
8097 if (pHash_Get != &Hash_Get && !allocate) //do we want to try case insensative too?
8101 def = pHash_Get(&localstable, name);
8105 if ( def->scope && def->scope != scope)
8107 def = pHash_GetNext(&localstable, name, def);
8108 continue; // in a different function
8111 if (type && typecmp(def->type, type))
8112 QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8113 if (def->arraysize != arraysize && arraysize)
8114 QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
8115 if (allocate && scope)
8117 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8118 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8120 // QCC_PR_ParsePrintDef(def);
8127 def = pHash_Get(&globalstable, name);
8131 if ( def->scope && def->scope != scope)
8133 def = pHash_GetNext(&globalstable, name, def);
8134 continue; // in a different function
8137 if (def->isstatic && def->s_file != s_file)
8138 { //warn? or would that be pointless?
8140 def = Hash_GetNext(&globalstable, name, def);
8141 continue; // in a different function
8144 if (type && typecmp(def->type, type))
8147 QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8149 if (def->arraysize != arraysize && arraysize)
8150 QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
8151 if (allocate && scope)
8154 { //warn? or would that be pointless?
8155 def = pHash_GetNext(&globalstable, name, def);
8156 continue; // in a different function
8159 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8160 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8162 // QCC_PR_ParsePrintDef(def);
8168 if (foundstatic && !allocate)
8170 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s defined static", name);
8171 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, foundstatic);
8179 QCC_PR_ParseError (ERR_ARRAYNEEDSSIZE, "First declaration of array %s with no size",name);
8184 if (QCC_PR_GetDef(type, name, NULL, false, arraysize, false))
8185 QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL, "Local \"%s\" defined with name of a global", name);
8188 ofs = numpr_globals;
8190 { //write the array size
8191 ofs = QCC_GetFreeOffsetSpace(1 + (type->size * arraysize));
8193 ((int *)qcc_pr_globals)[ofs] = arraysize-1; //An array needs the size written first. This is a hexen2 opcode thing.
8197 ofs = QCC_GetFreeOffsetSpace(type->size * arraysize);
8199 def = QCC_PR_DummyDef(type, name, scope, arraysize, ofs, true, saved);
8202 if (type->type == ev_field && allocate != 2)
8204 for (i = 0; i < type->size*arraysize; i++) //make arrays of fields work.
8205 *(int *)&qcc_pr_globals[def->ofs+i] = pr.size_fields+i;
8207 pr.size_fields += i;
8212 def->nextlocal = pr.localvars;
8219 QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int *fieldofs, pbool saved)
8224 QCC_def_t *def, *first=NULL;
8225 unsigned int maxfield, startfield;
8228 startfield = *fieldofs;
8229 maxfield = startfield;
8231 for (a = 0; a < arraysize; a++)
8236 sprintf(array, "[%i]", a);
8240 sprintf(newname, "%s%s", name, array);
8242 // allocate a new def
8243 def = (void *)qccHunkAlloc (sizeof(QCC_def_t));
8244 memset (def, 0, sizeof(*def));
8246 def->arraysize = arraysize;
8248 pr.def_tail->next = def;
8251 def->s_line = pr_source_line;
8252 def->s_file = s_file;
8254 def->name = (void *)qccHunkAlloc (strlen(newname)+1);
8255 strcpy (def->name, newname);
8260 def->ofs = QCC_GetFreeOffsetSpace(1);
8261 ((int *)qcc_pr_globals)[def->ofs] = *fieldofs;
8271 // printf("Emited %s\n", newname);
8273 if ((type)->type == ev_struct||(type)->type == ev_union)
8276 QCC_type_t *parttype;
8279 parttype = (type)->param;
8280 isunion = ((type)->type == ev_union);
8281 for (partnum = 0, parms = (type)->num_parms; partnum < parms; partnum++)
8283 switch (parttype->type)
8288 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8290 sprintf(newname, "%s%s", parttype->name, array);
8291 def = QCC_PR_DummyFieldDef(parttype, newname, scope, 1, fieldofs, saved);
8302 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8304 sprintf(newname, "%s%s", parttype->name, array);
8305 ftype = QCC_PR_NewType("FIELD TYPE", ev_field);
8306 ftype->aux_type = parttype;
8307 if (parttype->type == ev_vector)
8308 ftype->size = parttype->size; //vector fields create a _y and _z too, so we need this still.
8309 def = QCC_PR_GetDef(NULL, newname, scope, false, 1, saved);
8312 def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved);
8316 QCC_PR_ParseWarning(WARN_CONFLICTINGUNIONMEMBER, "conflicting offsets for union/struct expansion of %s. Ignoring new def.", newname);
8317 QCC_PR_ParsePrintDef(WARN_CONFLICTINGUNIONMEMBER, def);
8323 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8325 sprintf(newname, "%s%s", parttype->name, array);
8326 ftype = QCC_PR_NewType("FIELD TYPE", ev_field);
8327 ftype->aux_type = parttype;
8328 def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved);
8329 def->initialized = true;
8330 ((int *)qcc_pr_globals)[def->ofs] = *fieldofs;
8331 *fieldofs += parttype->size;
8336 if (*fieldofs > maxfield)
8337 maxfield = *fieldofs;
8339 *fieldofs = startfield;
8342 parttype=parttype->next;
8347 *fieldofs = maxfield; //final size of the union.
8353 void QCC_PR_ExpandUnionToFields(QCC_type_t *type, int *fields)
8355 QCC_type_t *pass = type->aux_type;
8356 QCC_PR_DummyFieldDef(pass, "", pr_scope, 1, fields, true);
8359 int accglobalsblock; //0 = error, 1 = var, 2 = function, 3 = objdata
8364 Called at the outer layer and when a local statement is hit
8367 void QCC_PR_ParseDefs (char *classname)
8370 QCC_type_t *type, *parm;
8373 QCC_dfunction_t *df;
8375 extern pbool defaultstatic;
8377 pbool isstatic=defaultstatic;
8378 pbool externfnc=false;
8379 pbool isconstant = false;
8380 pbool isvar = false;
8381 pbool noref = false;
8382 pbool nosave = false;
8383 pbool allocatenew = true;
8384 pbool inlinefunction = false;
8389 if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
8391 if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int"))
8399 name = QCC_PR_ParseName();
8400 if (QCC_PR_CheckToken("="))
8402 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_integer)
8404 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8408 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name);
8410 iv = G_INT(def->ofs);
8413 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number");
8417 iv = pr_immediate._int;
8421 def = QCC_MakeIntDef(iv);
8422 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8425 if (QCC_PR_CheckToken("}"))
8433 QCC_PR_CheckKeyword(keyword_float, "float");
8439 name = QCC_PR_ParseName();
8440 if (QCC_PR_CheckToken("="))
8442 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float)
8444 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8448 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name);
8450 fv = G_FLOAT(def->ofs);
8453 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number");
8457 fv = pr_immediate._float;
8461 def = QCC_MakeFloatDef(fv);
8462 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8465 if (QCC_PR_CheckToken("}"))
8474 if (QCC_PR_CheckKeyword(keyword_enumflags, "enumflags"))
8478 if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int"))
8486 name = QCC_PR_ParseName();
8487 if (QCC_PR_CheckToken("="))
8489 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_integer)
8491 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8495 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name);
8497 iv = G_INT(def->ofs);
8500 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number");
8504 iv = pr_immediate._int;
8512 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", iv);
8517 if (((i>>1)<<1) != i)
8522 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)iv);
8525 def = QCC_MakeIntDef(iv);
8526 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8530 if (QCC_PR_CheckToken("}"))
8538 QCC_PR_CheckKeyword(keyword_float, "float");
8545 name = QCC_PR_ParseName();
8546 if (QCC_PR_CheckToken("="))
8548 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float)
8550 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8554 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name);
8556 fv = G_FLOAT(def->ofs);
8559 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number");
8563 fv = pr_immediate._float;
8571 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", fv);
8576 if (((i>>1)<<1) != i)
8581 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)fv);
8584 def = QCC_MakeFloatDef(fv);
8585 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8589 if (QCC_PR_CheckToken("}"))
8598 if (QCC_PR_CheckKeyword (keyword_typedef, "typedef"))
8600 type = QCC_PR_ParseType(true);
8603 QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens");
8605 type->name = QCC_CopyString(pr_token)+strings;
8614 if (QCC_PR_CheckKeyword (keyword_codesys, "CodeSys")) //reacc support.
8617 QCC_PR_ParseError(ERR_BADEXTENSION, "progs crc was already specified - only one is allowed");
8618 ForcedCRC = (int)pr_immediate._float;
8625 if (QCC_PR_CheckKeyword (keyword_var, "var")) //reacc support.
8627 if (accglobalsblock == 3)
8629 if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
8630 QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false);
8634 if (QCC_PR_CheckToken(":"))
8635 accglobalsblock = 1;
8640 if (QCC_PR_CheckKeyword (keyword_function, "function")) //reacc support.
8642 accglobalsblock = 2;
8644 if (QCC_PR_CheckKeyword (keyword_objdata, "objdata")) //reacc support.
8646 if (accglobalsblock == 3)
8648 if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
8649 QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false);
8652 if (!QCC_PR_GetDef(type_void, "end_sys_globals", NULL, false, 0, false))
8653 QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 1, false);
8654 accglobalsblock = 3;
8659 switch(accglobalsblock)//reacc support.
8663 char *oldp = pr_file_p;
8664 name = QCC_PR_ParseName();
8665 if (!QCC_PR_CheckToken(":")) //nope, it wasn't!
8667 QCC_PR_IncludeChunk(name, true, NULL);
8673 if (QCC_PR_CheckKeyword(keyword_object, "object"))
8674 QCC_PR_GetDef(type_entity, name, NULL, true, 1, true);
8675 else if (QCC_PR_CheckKeyword(keyword_string, "string"))
8676 QCC_PR_GetDef(type_string, name, NULL, true, 1, true);
8677 else if (QCC_PR_CheckKeyword(keyword_real, "real"))
8679 def = QCC_PR_GetDef(type_float, name, NULL, true, 1, true);
8680 if (QCC_PR_CheckToken("="))
8682 G_FLOAT(def->ofs) = pr_immediate._float;
8686 else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
8688 def = QCC_PR_GetDef(type_vector, name, NULL, true, 1, true);
8689 if (QCC_PR_CheckToken("="))
8692 G_FLOAT(def->ofs+0) = pr_immediate._float;
8694 G_FLOAT(def->ofs+1) = pr_immediate._float;
8696 G_FLOAT(def->ofs+2) = pr_immediate._float;
8701 else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
8702 QCC_PR_GetDef(type_function, name, NULL, true, 1, true);
8704 QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
8705 QCC_PR_Expect (";");
8707 if (QCC_PR_CheckKeyword (keyword_system, "system"))
8708 QCC_PR_Expect (";");
8712 name = QCC_PR_ParseName();
8713 QCC_PR_GetDef(type_function, name, NULL, true, 1, true);
8714 QCC_PR_CheckToken (";");
8718 char *oldp = pr_file_p;
8719 name = QCC_PR_ParseName();
8720 if (!QCC_PR_CheckToken(":")) //nope, it wasn't!
8722 QCC_PR_IncludeChunk(name, true, NULL);
8728 if (QCC_PR_CheckKeyword(keyword_object, "object"))
8729 QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 1, true);
8730 else if (QCC_PR_CheckKeyword(keyword_string, "string"))
8731 QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 1, true);
8732 else if (QCC_PR_CheckKeyword(keyword_real, "real"))
8733 QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 1, true);
8734 else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
8735 QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 1, true);
8736 else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
8737 QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 1, true);
8739 QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
8740 QCC_PR_Expect (";");
8747 if (QCC_PR_CheckKeyword(keyword_extern, "extern"))
8749 else if (QCC_PR_CheckKeyword(keyword_shared, "shared"))
8753 QCC_PR_ParseError (ERR_NOSHAREDLOCALS, "Cannot have shared locals");
8755 else if (QCC_PR_CheckKeyword(keyword_const, "const"))
8757 else if (QCC_PR_CheckKeyword(keyword_var, "var"))
8759 else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "static"))
8761 else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "nonstatic"))
8763 else if (QCC_PR_CheckKeyword(keyword_noref, "noref"))
8765 else if (QCC_PR_CheckKeyword(keyword_nosave, "nosave"))
8771 type = QCC_PR_ParseType (false);
8772 if (type == NULL) //ignore
8775 inlinefunction = type_inlinefunction;
8777 if (externfnc && type->type != ev_function)
8779 printf ("Only functions may be defined as external (yet)\n");
8783 if (!pr_scope && QCC_PR_CheckKeyword(keyword_function, "function")) //reacc support.
8785 name = QCC_PR_ParseName ();
8787 type = QCC_PR_ParseFunctionTypeReacc(false, type);
8789 if (!stricmp(name, "null"))
8791 def = QCC_PR_GetDef (type, name, NULL, true, 1, false);
8794 { //ignore the code and stuff
8796 if (QCC_PR_CheckKeyword(keyword_external, "external"))
8805 while (!QCC_PR_CheckToken("{")) //skip over the locals.
8807 if (pr_token_type == tt_eof)
8809 QCC_PR_ParseError(0, "Unexpected EOF");
8815 //balance out the { and }
8818 if (pr_token_type == tt_eof)
8820 if (QCC_PR_CheckToken("{"))
8822 else if (QCC_PR_CheckToken("}"))
8825 QCC_PR_Lex(); //ignore it.
8834 f = QCC_PR_ParseImmediateStatements (type);
8836 def->initialized = 1;
8837 def->isstatic = isstatic;
8838 G_FUNCTION(def->ofs) = numfunctions;
8841 // PR_PrintFunction (def);
8843 // fill in the dfunction
8844 df = &functions[numfunctions];
8847 df->first_statement = -f->builtin;
8849 df->first_statement = f->code;
8851 if (f->builtin && opt_function_names)
8852 optres_function_names += strlen(f->def->name);
8854 df->s_name = QCC_CopyString (f->def->name);
8855 df->s_file = s_file2;
8856 df->numparms = f->def->type->num_parms;
8857 df->locals = locals_end - locals_start;
8858 df->parm_start = locals_start;
8859 for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
8861 df->parm_size[i] = parm->size;
8867 // if (pr_scope && (type->type == ev_field) )
8868 // QCC_PR_ParseError ("Fields must be global");
8872 if (QCC_PR_CheckToken ("*"))
8875 while(QCC_PR_CheckToken ("*"))
8877 name = QCC_PR_ParseName ();
8879 else if (QCC_PR_CheckToken (";"))
8881 if (type->type == ev_field && (type->aux_type->type == ev_union || type->aux_type->type == ev_struct))
8883 QCC_PR_ExpandUnionToFields(type, &pr.size_fields);
8886 // if (type->type == ev_union)
8890 QCC_PR_ParseError (ERR_TYPEWITHNONAME, "type with no name");
8896 name = QCC_PR_ParseName ();
8900 if (QCC_PR_CheckToken("::") && !classname)
8903 name = QCC_PR_ParseName();
8906 //check for an array
8908 if ( QCC_PR_CheckToken ("[") )
8910 char *oldprfile = pr_file_p;
8912 if (QCC_PR_CheckToken("]"))
8920 if(pr_token_type == tt_eof)
8922 if (QCC_PR_CheckToken(","))
8924 if (QCC_PR_CheckToken("}"))
8928 pr_file_p = oldprfile;
8933 def = QCC_PR_Expression(TOP_PRIORITY, 0);
8935 QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value");
8936 else if (def->type->type == ev_integer)
8937 arraysize = G_INT(def->ofs);
8938 else if (def->type->type == ev_float)
8940 arraysize = (int)G_FLOAT(def->ofs);
8941 if ((float)arraysize != G_FLOAT(def->ofs))
8942 QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value");
8945 QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size must be of int value");
8946 /* if(pr_token_type == tt_name)
8948 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), pr_scope, false, 0);
8949 if (def && def->arraysize==1)
8951 if (def->type->type == ev_integer)
8952 arraysize = G_INT(def->ofs);
8953 else if (def->type->type == ev_float && (float)(int)G_FLOAT(def->ofs) == G_FLOAT(def->ofs))
8954 arraysize = (int)G_FLOAT(def->ofs);
8957 else if (pr_token_type == tt_immediate)
8959 arraysize = atoi (pr_token);
8962 */ QCC_PR_Expect("]");
8967 QCC_PR_ParseError (ERR_BADARRAYSIZE, "Definition of array (%s) size is not of a numerical value", name);
8968 arraysize=0; //grrr...
8974 if (QCC_PR_CheckToken("("))
8977 QCC_PR_ParseWarning(WARN_UNSAFEFUNCTIONRETURNTYPE, "Function returning function. Is this what you meant? (suggestion: use typedefs)");
8978 inlinefunction = false;
8979 type = QCC_PR_ParseFunctionType(false, type);
8984 char *membername = name;
8985 name = qccHunkAlloc(strlen(classname) + strlen(name) + 3);
8986 sprintf(name, "%s::"MEMBERFIELDNAME, classname, membername);
8987 if (!QCC_PR_GetDef(NULL, name, NULL, false, 0, false))
8988 QCC_PR_ParseError(ERR_NOTANAME, "%s %s is not a member of class %s\n", TypeName(type), membername, classname);
8989 sprintf(name, "%s::%s", classname, membername);
8991 pr_classtype = QCC_TypeForName(classname);
8992 if (!pr_classtype || !pr_classtype->parentclass)
8993 QCC_PR_ParseError(ERR_NOTANAME, "%s is not a class\n", classname);
8996 pr_classtype = NULL;
8998 oldglobals = numpr_globals;
9006 parm = QCC_PointerTypeTo(parm);
9009 def = QCC_PR_GetDef (parm, name, pr_scope, allocatenew, arraysize, !nosave);
9012 def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave);
9015 QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of class %s", name, classname);
9020 if (!def->initialized && shared) //shared count as initiialised
9022 def->shared = shared;
9023 def->initialized = true;
9026 def->initialized = 2;
9030 if (def->s_file == s_file)
9031 def->isstatic = isstatic;
9032 else //if (type->type != ev_function && defaultstatic) //functions don't quite consitiute a definition
9033 QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "can't redefine non-static as static");
9036 // check for an initialization
9037 if (type->type == ev_function && (pr_scope))
9039 if ( QCC_PR_CheckToken ("=") )
9041 QCC_PR_ParseError (ERR_INITIALISEDLOCALFUNCTION, "local functions may not be initialised");
9044 arraysize = def->arraysize;
9045 d = def; //apply to ALL elements
9048 d->initialized = 1; //fake function
9049 G_FUNCTION(d->ofs) = 0;
9056 if (type->type == ev_field && QCC_PR_CheckName ("alias"))
9058 QCC_PR_ParseError(ERR_INTERNAL, "FTEQCC does not support this variant of decompiled hexenc\nPlease obtain the original version released by Raven Software instead.");
9059 name = QCC_PR_ParseName();
9061 else if ( QCC_PR_CheckToken ("=") || ((type->type == ev_function) && (pr_token[0] == '{' || pr_token[0] == '[' || pr_token[0] == ':'))) //this is an initialisation (or a function)
9064 QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name);
9065 if (def->initialized == 1)
9067 if (def->type->type == ev_function)
9069 i = G_FUNCTION(def->ofs);
9071 QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
9074 QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
9078 { //ignore the code and stuff
9079 if (QCC_PR_CheckToken("["))
9081 while (!QCC_PR_CheckToken("]"))
9083 if (pr_token_type == tt_eof)
9088 if (QCC_PR_CheckToken("{"))
9091 //balance out the { and }
9094 if (pr_token_type == tt_eof)
9096 if (QCC_PR_CheckToken("{"))
9098 else if (QCC_PR_CheckToken("}"))
9101 QCC_PR_Lex(); //ignore it.
9106 QCC_PR_CheckToken("#");
9112 #pragma message("this is experimental")
9115 d = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
9118 for (i = 0; i < d->type->size; i++)
9119 G_INT(def->ofs+i) = G_INT(d->ofs+i);
9120 def->constant = !isvar;
9121 def->initialized = 1;
9124 else if (def->type->size >= 3)
9126 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], d, def, NULL));
9127 def->constant = false;
9128 def->initialized = false;
9133 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], d, def, NULL));
9134 def->constant = false;
9135 def->initialized = false;
9140 if (pr_token_type == tt_name && strcmp(pr_token, "_"))
9144 if (def->arraysize>1)
9145 QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly braces");
9147 d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false);
9149 QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token);
9150 if (typecmp(def->type, d->type))
9151 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
9154 for (i = 0; i < d->type->size; i++)
9155 G_INT(def->ofs) = G_INT(d->ofs);
9158 if (type->type == ev_function)
9160 def->initialized = 1;
9161 def->constant = !isvar;
9166 else if (type->type == ev_function)
9169 def->constant = false;
9171 def->constant = true;
9172 if (QCC_PR_CheckImmediate("0"))
9175 def->initialized = 1; //fake function
9176 G_FUNCTION(def->ofs) = 0;
9180 if (!def->constant && arraysize==1)
9183 def->initialized = 1; //fake function
9185 name = QCC_PR_ParseName ();
9186 d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
9188 QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not previously defined", name);
9189 G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs);
9196 def->initialized = 1; //fake function
9197 QCC_PR_Expect ("{");
9201 if (pr_token_type == tt_immediate && (
9202 (pr_immediate_type == type_integer && pr_immediate._int == 0) ||
9203 (pr_immediate_type == type_float && pr_immediate._float == 0)))
9206 G_FUNCTION(def->ofs+i) = 0;
9210 name = QCC_PR_ParseName ();
9212 d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
9214 QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined", name);
9217 if (!d->initialized)
9218 QCC_PR_ParseWarning(WARN_NOTDEFINED, "initialisation of function arrays must be placed after the body of all functions used (%s)", name);
9219 G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs);
9224 } while(QCC_PR_CheckToken(","));
9226 arraysize = def->arraysize;
9227 d = def; //apply to ALL elements
9230 d->initialized = 1; //fake function
9235 if (i > def->arraysize)
9236 QCC_PR_ParseError(ERR_TOOMANYINITIALISERS, "Too many initializers");
9240 QCC_PR_ParseError(0, "Initialised functions must be constant");
9244 f = QCC_PR_ParseImmediateStatements (type);
9246 def->initialized = 1;
9247 G_FUNCTION(def->ofs) = numfunctions;
9250 // PR_PrintFunction (def);
9252 // fill in the dfunction
9253 df = &functions[numfunctions];
9256 df->first_statement = -f->builtin;
9258 df->first_statement = f->code;
9260 if (f->builtin && opt_function_names)
9261 optres_function_names += strlen(f->def->name);
9263 df->s_name = QCC_CopyString (f->def->name);
9264 df->s_file = s_file2;
9265 df->numparms = f->def->type->num_parms;
9266 df->locals = locals_end - locals_start;
9267 df->parm_start = locals_start;
9268 for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
9270 df->parm_size[i] = parm->size;
9276 else if (type->type == ev_struct)
9278 int arraypart, partnum;
9279 QCC_type_t *parttype;
9280 def->initialized = 1;
9282 def->constant = true;
9284 def->constant = false;
9286 // QCC_PR_ParseError("const used on a struct isn't useful");
9288 //FIXME: should do this recursivly
9290 for (arraypart = 0; arraypart < arraysize; arraypart++)
9292 parttype = type->param;
9294 for (partnum = 0; partnum < type->num_parms; partnum++)
9296 switch (parttype->type)
9301 if (pr_token_type == tt_punct)
9303 if (QCC_PR_CheckToken("{"))
9308 QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation");
9311 else if (pr_token_type == tt_immediate)
9313 if (pr_immediate_type->type == ev_float && parttype->type == ev_integer)
9314 G_INT(def->ofs + arraypart*type->size + parttype->ofs) = (int)pr_immediate._float;
9315 else if (pr_immediate_type->type != parttype->type)
9316 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name);
9318 memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
9320 else if (pr_token_type == tt_name)
9322 d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false);
9324 QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token);
9325 else if (d->type->type != parttype->type)
9326 QCC_PR_ParseError (ERR_WRONGSUBTYPE, "wrong subtype for %s.%s", def->name, parttype->name);
9327 else if (!d->constant)
9328 QCC_PR_ParseError(ERR_NOTACONSTANT, "%s isn't a constant\n", pr_token);
9330 memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, qcc_pr_globals + d->ofs, 4*d->type->size);
9333 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name);
9338 if (pr_token_type == tt_punct)
9340 if (QCC_PR_CheckToken("{"))
9343 for (i = 0; i < parttype->size; i++)
9345 /* //the executor defines strings as true c strings, but reads in index from string table.
9346 //structures can hide these strings.
9347 d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
9349 pr.def_tail->next = d;
9353 d->name = "STRUCTIMMEDIATE";
9354 d->constant = constant;
9358 d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i;
9360 G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = QCC_CopyString(pr_immediate_string);
9363 if (!QCC_PR_CheckToken(","))
9369 for (; i < parttype->size; i++)
9371 /* //the executor defines strings as true c strings, but reads in index from string table.
9372 //structures can hide these strings.
9373 d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
9375 pr.def_tail->next = d;
9379 d->name = "STRUCTIMMEDIATE";
9380 d->constant = constant;
9384 d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i;
9386 G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = 0;
9391 QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation");
9395 /* //the executor defines strings as true c strings, but reads in index from string table.
9396 //structures can hide these strings.
9397 d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
9399 pr.def_tail->next = d;
9403 d->name = "STRUCTIMMEDIATE";
9404 d->constant = constant;
9408 d->ofs = def->ofs+arraypart*type->size+parttype->ofs;
9410 G_INT(def->ofs+arraypart*type->size+parttype->ofs) = QCC_CopyString(pr_immediate_string);
9415 if (pr_token_type == tt_immediate)
9417 if (pr_immediate._int != 0)
9418 QCC_PR_ParseError(ERR_NOTFUNCTIONTYPE, "Expected function name or NULL");
9419 G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = 0;
9424 name = QCC_PR_ParseName ();
9426 d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
9428 QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", name);
9430 G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = G_FUNCTION(d->ofs);
9434 QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "type %i not valid in a struct", parttype->type);
9438 if (!QCC_PR_CheckToken(","))
9441 parttype=parttype->next;
9444 if (!QCC_PR_CheckToken(","))
9451 else if (type->type == ev_integer) //handle these differently, because they may need conversions
9454 def->constant = false;
9456 def->constant = true;
9458 def->initialized = 1;
9459 memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
9462 if (pr_immediate_type->type == ev_float)
9463 G_INT(def->ofs) = (int)pr_immediate._float;
9464 else if (pr_immediate_type->type != ev_integer)
9465 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
9469 else if (type->type == ev_string)
9471 int dotranslate = 0;
9473 if (!strcmp(pr_token, "_"))
9481 if (arraysize>=1 && QCC_PR_CheckToken("{"))
9484 for (i = 0; i < arraysize; i++)
9488 //the executor defines strings as true c strings, but reads in index from string table.
9489 //structures can hide these strings.
9490 if (i != 0) //not for the first entry - already a string def for that
9492 d = (void *)qccHunkAlloc (sizeof(QCC_def_t));
9494 pr.def_tail->next = d;
9497 d->name = "IMMEDIATE";
9498 d->type = type_string;
9500 d->constant = false;
9506 d->ofs = def->ofs+i;
9507 if (d->ofs >= MAX_REGS)
9508 QCC_Error(ERR_TOOMANYGLOBALS, "MAX_REGS is too small");
9511 if (!strcmp(pr_token, "_"))
9519 if(dotranslate || dotranslate2)
9521 sprintf(buf, "dotranslate_%d", ++dotranslate_count);
9522 d->name = strdup(buf);
9525 (((int *)qcc_pr_globals)[def->ofs+i]) = QCC_CopyString(pr_immediate_string);
9531 if (!QCC_PR_CheckToken(","))
9536 else if (arraysize<=1)
9539 def->constant = false;
9541 def->constant = true;
9542 def->initialized = 1;
9543 (((int *)qcc_pr_globals)[def->ofs]) = QCC_CopyString(pr_immediate_string);
9548 sprintf(buf, "dotranslate_%d", ++dotranslate_count);
9549 def->name = strdup(buf);
9552 if (pr_immediate_type->type == ev_float)
9553 G_INT(def->ofs) = (int)pr_immediate._float;
9554 else if (pr_immediate_type->type != ev_string)
9555 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
9558 QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
9564 else if (type->type == ev_float)
9566 if (arraysize>=1 && QCC_PR_CheckToken("{"))
9569 for (i = 0; i < arraysize; i++)
9571 if (pr_immediate_type->type != ev_float)
9572 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
9573 (((float *)qcc_pr_globals)[def->ofs+i]) = pr_immediate._float;
9576 if (!QCC_PR_CheckToken(","))
9583 else if (arraysize<=1)
9586 def->constant = false;
9588 def->constant = true;
9590 def->initialized = 1;
9592 if (pr_immediate_type->type != ev_float)
9593 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
9595 if (def->constant && opt_dupconstdefs)
9597 if (def->ofs == oldglobals)
9599 if (Hash_GetKey(&floatconstdefstable, *(int*)&pr_immediate._float))
9600 optres_dupconstdefs++;
9601 QCC_FreeOffset(def->ofs, def->type->size);
9602 d = QCC_MakeFloatDef(pr_immediate._float);
9610 (((float *)qcc_pr_globals)[def->ofs]) = pr_immediate._float;
9616 QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
9618 else if (type->type == ev_vector)
9620 if (arraysize>=1 && QCC_PR_CheckToken("{"))
9623 for (i = 0; i < arraysize; i++)
9625 if (pr_immediate_type->type != ev_vector)
9626 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
9627 (((float *)qcc_pr_globals)[def->ofs+i*3+0]) = pr_immediate.vector[0];
9628 (((float *)qcc_pr_globals)[def->ofs+i*3+1]) = pr_immediate.vector[1];
9629 (((float *)qcc_pr_globals)[def->ofs+i*3+2]) = pr_immediate.vector[2];
9632 if (!QCC_PR_CheckToken(","))
9639 else if (arraysize<=1)
9642 def->constant = false;
9644 def->constant = true;
9645 def->initialized = 1;
9647 if (pr_immediate_type->type != ev_vector)
9648 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
9649 (((float *)qcc_pr_globals)[def->ofs+0]) = pr_immediate.vector[0];
9650 (((float *)qcc_pr_globals)[def->ofs+1]) = pr_immediate.vector[1];
9651 (((float *)qcc_pr_globals)[def->ofs+2]) = pr_immediate.vector[2];
9657 QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces");
9659 else if (pr_token_type == tt_name)
9661 // if (pr_scope)//create a new instance, emit a copy op
9663 // QCC_PR_ParseError ("name defined for local : %s", name);
9667 d = QCC_PR_GetDef (NULL, pr_token, pr_scope, false, 0, false);
9669 QCC_PR_ParseError (ERR_NOTDEFINED, "initialisation name not defined : %s", pr_token);
9672 QCC_PR_ParseWarning (WARN_NOTCONSTANT, "initialisation name not a constant : %s", pr_token);
9673 QCC_PR_ParsePrintDef(WARN_NOTCONSTANT, d);
9675 memcpy (def, d, sizeof(*d));
9677 def->initialized = true;
9680 else if (pr_token_type != tt_immediate)
9681 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "not an immediate for %s - %s", name, pr_token);
9682 else if (pr_immediate_type->type != type->type)
9683 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s - %s", name, pr_token);
9685 memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
9688 def->constant = false;
9690 def->constant = true;
9691 def->initialized = true;
9696 if (type->type == ev_function && isvar)
9698 isconstant = !isvar;
9699 def->initialized = 1;
9702 if (isconstant && type->type == ev_field)
9703 def->constant = 2; //special flag on fields, 2, makes the pointer obtained from them also constant.
9705 def->constant = isconstant;
9709 } while (QCC_PR_CheckToken (","));
9711 if (type->type == ev_function)
9712 QCC_PR_CheckToken (";");
9715 if (!QCC_PR_CheckToken (";"))
9716 QCC_PR_ParseWarning(WARN_UNDESIRABLECONVENTION, "Missing semicolon at end of definition");
9724 compiles the 0 terminated text, adding defintions to the pr structure
9727 pbool QCC_PR_CompileFile (char *string, char *filename)
9731 QCC_Error (ERR_INTERNAL, "PR_CompileFile: Didn't clear");
9733 QCC_PR_ClearGrabMacros (); // clear the frame macros
9735 compilingfile = filename;
9739 optres_filenames += strlen(filename);
9740 pr_file_p = qccHunkAlloc(strlen(filename)+1);
9741 strcpy(pr_file_p, filename);
9742 s_file = pr_file_p - strings;
9747 s_file = s_file2 = QCC_CopyString (filename);
9753 memcpy(&oldjb, &pr_parse_abort, sizeof(oldjb));
9755 if( setjmp( pr_parse_abort ) ) {
9756 // dont count it as error
9758 //clock up the first line
9759 QCC_PR_NewLine (false);
9761 QCC_PR_Lex (); // read first token
9764 while (pr_token_type != tt_eof)
9766 if (setjmp(pr_parse_abort))
9768 if (++pr_error_count > MAX_ERRORS)
9770 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
9776 QCC_PR_SkipToSemicolon ();
9777 if (pr_token_type == tt_eof)
9779 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
9784 pr_scope = NULL; // outside all functions
9786 QCC_PR_ParseDefs (NULL);
9788 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
9790 return (pr_error_count == 0);
9793 pbool QCC_Include(char *filename)
9798 QCC_string_t os_file, os_file2;
9799 int opr_source_line;
9800 char *ocompilingfile;
9801 struct qcc_includechunk_s *oldcurrentchunk;
9802 extern struct qcc_includechunk_s *currentchunk;
9804 ocompilingfile = compilingfile;
9807 opr_source_line = pr_source_line;
9808 opr_file_p = pr_file_p;
9809 oldcurrentchunk = currentchunk;
9811 strcpy(fname, filename);
9812 QCC_LoadFile(fname, (void*)&newfile);
9813 currentchunk = NULL;
9814 pr_file_p = newfile;
9815 QCC_PR_CompileFile(newfile, fname);
9816 currentchunk = oldcurrentchunk;
9818 compilingfile = ocompilingfile;
9821 pr_source_line = opr_source_line;
9822 pr_file_p = opr_file_p;
9824 // QCC_PR_IncludeChunk(newfile, false, fname);