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 //standard qcc keywords
17 #define keyword_return 1
19 #define keyword_else 1
20 #define keyword_local 1
21 #define keyword_while 1
28 pbool keyword_optional;
29 pbool keyword_const; //fixme
30 pbool keyword_continue;
31 pbool keyword_default;
32 pbool keyword_entity; //for skipping the local
33 pbool keyword_float; //for skipping the local
36 pbool keyword_int; //for skipping the local
37 pbool keyword_integer; //for skipping the local
39 pbool keyword_string; //for skipping the local
42 pbool keyword_thinktime;
43 pbool keyword_var; //allow it to be initialised and set around the place.
44 pbool keyword_vector; //for skipping the local
47 pbool keyword_enum; //kinda like in c, but typedef not supported.
48 pbool keyword_enumflags; //like enum, but doubles instead of adds 1.
49 pbool keyword_typedef; //fixme
50 #define keyword_codesys flag_acc //reacc needs this (forces the resultant crc)
51 #define keyword_function flag_acc //reacc needs this (reacc has this on all functions, wierd eh?)
52 #define keyword_objdata flag_acc //reacc needs this (following defs are fields rather than globals, use var to disable)
53 #define keyword_object flag_acc //reacc needs this (an entity)
54 #define keyword_pfunc flag_acc //reacc needs this (pointer to function)
55 #define keyword_system flag_acc //reacc needs this (potatos)
56 #define keyword_real flag_acc //reacc needs this (a float)
57 #define keyword_exit flag_acc //emits an OP_DONE opcode.
58 #define keyword_external flag_acc //reacc needs this (a builtin)
59 pbool keyword_extern; //function is external, don't error or warn if the body was not found
60 pbool keyword_shared; //mark global to be copied over when progs changes (part of FTE_MULTIPROGS)
61 pbool keyword_noref; //nowhere else references this, don't strip it.
62 pbool keyword_nosave; //don't write the def to the output.
63 pbool keyword_union; //you surly know what a union is!
65 #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
67 pbool keywords_coexist; //don't disable a keyword simply because a var was made with the same name.
68 pbool output_parms; //emit some PARMX fields. confuses decompilers.
69 pbool autoprototype; //take two passes over the source code. First time round doesn't enter and functions or initialise variables.
70 pbool pr_subscopedlocals; //causes locals to be valid ONLY within their statement block. (they simply can't be referenced by name outside of it)
71 pbool flag_ifstring; //makes if (blah) equivelent to if (blah != "") which resolves some issues in multiprogs situations.
72 pbool flag_iffloat; //use an op_if_f instruction instead of op_if so if(-0) evaluates to false.
73 pbool flag_acc; //reacc like behaviour of src files (finds *.qc in start dir and compiles all in alphabetical order)
74 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
75 pbool flag_laxcasts; //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code.
76 pbool flag_hashonly; //Allows use of only #constant for precompiler constants, allows certain preqcc using mods to compile
77 pbool flag_fasttrackarrays; //Faster arrays, dynamically detected, activated only in supporting engines.
78 pbool flag_msvcstyle; //MSVC style warnings, so msvc's ide works properly
79 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?
81 pbool flag_typeexplicit; //no implicit type conversions, you must do the casts yourself.
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, const char *name);
132 void *(*pHash_GetNext)(hashtable_t *table, const char *name, void *old);
133 void *(*pHash_Add)(hashtable_t *table, const 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_FindType (QCC_type_t *type);
137 QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto);
138 QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto);
140 void QCC_PR_ParseState (void);
142 pbool expandedemptymacro;
145 //QCC_def_t **pr_global_defs/*[MAX_REGS]*/; // to find def for a global variable
147 //keeps track of how many funcs are called while parsing a statement
148 //int qcc_functioncalled;
150 //========================================
152 QCC_def_t *pr_scope; // the function being parsed, or NULL
153 QCC_type_t *pr_classtype;
155 QCC_string_t s_file, s_file2; // filename for function definition
157 unsigned int locals_start; // for tracking local variables vs temps
158 unsigned int locals_end; // for tracking local variables vs temps
160 jmp_buf pr_parse_abort; // longjump with this on parse error
162 void QCC_PR_ParseDefs (char *classname);
164 pbool qcc_usefulstatement;
175 QCC_def_t **pr_casesdef;
176 QCC_def_t **pr_casesdef2;
186 gotooperator_t *pr_labels;
187 gotooperator_t *pr_gotos;
191 QCC_def_t *extra_parms[MAX_EXTRA_PARMS];
193 //#define ASSOC_RIGHT_RESULT ASSOC_RIGHT
195 //========================================
197 //FIXME: modifiy list so most common GROUPS are first
198 //use look up table for value of first char and sort by first char and most common...?
200 //if true, effectivly {b=a; return a;}
201 QCC_opcode_t pr_opcodes[] =
203 {6, "<DONE>", "DONE", -1, ASSOC_LEFT, &type_void, &type_void, &type_void},
205 {6, "*", "MUL_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
206 {6, "*", "MUL_V", 3, ASSOC_LEFT, &type_vector, &type_vector, &type_float},
207 {6, "*", "MUL_FV", 3, ASSOC_LEFT, &type_float, &type_vector, &type_vector},
208 {6, "*", "MUL_VF", 3, ASSOC_LEFT, &type_vector, &type_float, &type_vector},
210 {6, "/", "DIV_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
212 {6, "+", "ADD_F", 4, ASSOC_LEFT, &type_float, &type_float, &type_float},
213 {6, "+", "ADD_V", 4, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
215 {6, "-", "SUB_F", 4, ASSOC_LEFT, &type_float, &type_float, &type_float},
216 {6, "-", "SUB_V", 4, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
218 {6, "==", "EQ_F", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
219 {6, "==", "EQ_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_float},
220 {6, "==", "EQ_S", 5, ASSOC_LEFT, &type_string, &type_string, &type_float},
221 {6, "==", "EQ_E", 5, ASSOC_LEFT, &type_entity, &type_entity, &type_float},
222 {6, "==", "EQ_FNC", 5, ASSOC_LEFT, &type_function, &type_function, &type_float},
224 {6, "!=", "NE_F", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
225 {6, "!=", "NE_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_float},
226 {6, "!=", "NE_S", 5, ASSOC_LEFT, &type_string, &type_string, &type_float},
227 {6, "!=", "NE_E", 5, ASSOC_LEFT, &type_entity, &type_entity, &type_float},
228 {6, "!=", "NE_FNC", 5, ASSOC_LEFT, &type_function, &type_function, &type_float},
230 {6, "<=", "LE", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
231 {6, ">=", "GE", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
232 {6, "<", "LT", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
233 {6, ">", "GT", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
235 {6, ".", "INDIRECT_F", 1, ASSOC_LEFT, &type_entity, &type_field, &type_float},
236 {6, ".", "INDIRECT_V", 1, ASSOC_LEFT, &type_entity, &type_field, &type_vector},
237 {6, ".", "INDIRECT_S", 1, ASSOC_LEFT, &type_entity, &type_field, &type_string},
238 {6, ".", "INDIRECT_E", 1, ASSOC_LEFT, &type_entity, &type_field, &type_entity},
239 {6, ".", "INDIRECT_FI", 1, ASSOC_LEFT, &type_entity, &type_field, &type_field},
240 {6, ".", "INDIRECT_FU", 1, ASSOC_LEFT, &type_entity, &type_field, &type_function},
242 {6, ".", "ADDRESS", 1, ASSOC_LEFT, &type_entity, &type_field, &type_pointer},
244 {6, "=", "STORE_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float},
245 {6, "=", "STORE_V", 6, ASSOC_RIGHT, &type_vector, &type_vector, &type_vector},
246 {6, "=", "STORE_S", 6, ASSOC_RIGHT, &type_string, &type_string, &type_string},
247 {6, "=", "STORE_ENT", 6, ASSOC_RIGHT, &type_entity, &type_entity, &type_entity},
248 {6, "=", "STORE_FLD", 6, ASSOC_RIGHT, &type_field, &type_field, &type_field},
249 {6, "=", "STORE_FNC", 6, ASSOC_RIGHT, &type_function, &type_function, &type_function},
251 {6, "=", "STOREP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float},
252 {6, "=", "STOREP_V", 6, ASSOC_RIGHT, &type_pointer, &type_vector, &type_vector},
253 {6, "=", "STOREP_S", 6, ASSOC_RIGHT, &type_pointer, &type_string, &type_string},
254 {6, "=", "STOREP_ENT", 6, ASSOC_RIGHT, &type_pointer, &type_entity, &type_entity},
255 {6, "=", "STOREP_FLD", 6, ASSOC_RIGHT, &type_pointer, &type_field, &type_field},
256 {6, "=", "STOREP_FNC", 6, ASSOC_RIGHT, &type_pointer, &type_function, &type_function},
258 {6, "<RETURN>", "RETURN", -1, ASSOC_LEFT, &type_float, &type_void, &type_void},
260 {6, "!", "NOT_F", -1, ASSOC_LEFT, &type_float, &type_void, &type_float},
261 {6, "!", "NOT_V", -1, ASSOC_LEFT, &type_vector, &type_void, &type_float},
262 {6, "!", "NOT_S", -1, ASSOC_LEFT, &type_vector, &type_void, &type_float},
263 {6, "!", "NOT_ENT", -1, ASSOC_LEFT, &type_entity, &type_void, &type_float},
264 {6, "!", "NOT_FNC", -1, ASSOC_LEFT, &type_function, &type_void, &type_float},
266 {6, "<IF>", "IF", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
267 {6, "<IFNOT>", "IFNOT", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
269 // calls returns REG_RETURN
270 {6, "<CALL0>", "CALL0", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
271 {6, "<CALL1>", "CALL1", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
272 {6, "<CALL2>", "CALL2", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
273 {6, "<CALL3>", "CALL3", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
274 {6, "<CALL4>", "CALL4", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
275 {6, "<CALL5>", "CALL5", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
276 {6, "<CALL6>", "CALL6", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
277 {6, "<CALL7>", "CALL7", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
278 {6, "<CALL8>", "CALL8", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
280 {6, "<STATE>", "STATE", -1, ASSOC_LEFT, &type_float, &type_float, &type_void},
282 {6, "<GOTO>", "GOTO", -1, ASSOC_RIGHT, NULL, &type_void, &type_void},
284 {6, "&&", "AND", 7, ASSOC_LEFT, &type_float, &type_float, &type_float},
285 {6, "||", "OR", 7, ASSOC_LEFT, &type_float, &type_float, &type_float},
287 {6, "&", "BITAND", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
288 {6, "|", "BITOR", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
290 //version 6 are in normal progs.
295 {7, "*=", "MULSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
296 {7, "*=", "MULSTORE_VF", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector},
297 {7, "*=", "MULSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
298 {7, "*=", "MULSTOREP_VF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector},
300 {7, "/=", "DIVSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
301 {7, "/=", "DIVSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
303 {7, "+=", "ADDSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
304 {7, "+=", "ADDSTORE_V", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector},
305 {7, "+=", "ADDSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
306 {7, "+=", "ADDSTOREP_V", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector},
308 {7, "-=", "SUBSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float},
309 {7, "-=", "SUBSTORE_V", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector},
310 {7, "-=", "SUBSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float},
311 {7, "-=", "SUBSTOREP_V", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector},
313 {7, "<FETCH_GBL_F>", "FETCH_GBL_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
314 {7, "<FETCH_GBL_V>", "FETCH_GBL_V", -1, ASSOC_LEFT, &type_vector, &type_float, &type_vector},
315 {7, "<FETCH_GBL_S>", "FETCH_GBL_S", -1, ASSOC_LEFT, &type_string, &type_float, &type_string},
316 {7, "<FETCH_GBL_E>", "FETCH_GBL_E", -1, ASSOC_LEFT, &type_entity, &type_float, &type_entity},
317 {7, "<FETCH_GBL_FNC>", "FETCH_GBL_FNC", -1, ASSOC_LEFT, &type_function, &type_float, &type_function},
319 {7, "<CSTATE>", "CSTATE", -1, ASSOC_LEFT, &type_float, &type_float, &type_void},
321 {7, "<CWSTATE>", "CWSTATE", -1, ASSOC_LEFT, &type_float, &type_float, &type_void},
323 {7, "<THINKTIME>", "THINKTIME", -1, ASSOC_LEFT, &type_entity, &type_float, &type_void},
325 {7, "|=", "BITSET_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float},
326 {7, "|=", "BITSETP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float},
327 {7, "&~=", "BITCLR_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float},
328 {7, "&~=", "BITCLRP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float},
330 {7, "<RAND0>", "RAND0", -1, ASSOC_LEFT, &type_void, &type_void, &type_float},
331 {7, "<RAND1>", "RAND1", -1, ASSOC_LEFT, &type_float, &type_void, &type_float},
332 {7, "<RAND2>", "RAND2", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
333 {7, "<RANDV0>", "RANDV0", -1, ASSOC_LEFT, &type_void, &type_void, &type_vector},
334 {7, "<RANDV1>", "RANDV1", -1, ASSOC_LEFT, &type_vector, &type_void, &type_vector},
335 {7, "<RANDV2>", "RANDV2", -1, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
337 {7, "<SWITCH_F>", "SWITCH_F", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
338 {7, "<SWITCH_V>", "SWITCH_V", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
339 {7, "<SWITCH_S>", "SWITCH_S", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
340 {7, "<SWITCH_E>", "SWITCH_E", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
341 {7, "<SWITCH_FNC>", "SWITCH_FNC", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
343 {7, "<CASE>", "CASE", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
344 {7, "<CASERANGE>", "CASERANGE", -1, ASSOC_LEFT, &type_void, &type_void, NULL},
347 //Later are additions by DMW.
349 {7, "<CALL1H>", "CALL1H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_void},
350 {7, "<CALL2H>", "CALL2H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
351 {7, "<CALL3H>", "CALL3H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
352 {7, "<CALL4H>", "CALL4H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
353 {7, "<CALL5H>", "CALL5H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
354 {7, "<CALL6H>", "CALL6H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
355 {7, "<CALL7H>", "CALL7H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
356 {7, "<CALL8H>", "CALL8H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
358 {7, "=", "STORE_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer},
359 {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_integer},
360 {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_float},
362 {7, "+", "ADD_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
363 {7, "+", "ADD_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float},
364 {7, "+", "ADD_IF", 4, ASSOC_LEFT, &type_integer, &type_float, &type_float},
366 {7, "-", "SUB_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
367 {7, "-", "SUB_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float},
368 {7, "-", "SUB_IF", 4, ASSOC_LEFT, &type_integer, &type_float, &type_float},
370 {7, "<CIF>", "C_ITOF", -1, ASSOC_LEFT, &type_integer, &type_void, &type_float},
371 {7, "<CFI>", "C_FTOI", -1, ASSOC_LEFT, &type_float, &type_void, &type_integer},
372 {7, "<CPIF>", "CP_ITOF", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_float},
373 {7, "<CPFI>", "CP_FTOI", -1, ASSOC_LEFT, &type_pointer, &type_float, &type_integer},
375 {7, ".", "INDIRECT", 1, ASSOC_LEFT, &type_entity, &type_field, &type_integer},
376 {7, "=", "STOREP_I", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer},
377 {7, "=", "STOREP_IF", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_integer},
378 {7, "=", "STOREP_FI", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_float},
380 {7, "&", "BITAND_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
381 {7, "|", "BITOR_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
383 {7, "*", "MUL_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
384 {7, "/", "DIV_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
385 {7, "==", "EQ_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
386 {7, "!=", "NE_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
388 {7, "<IFNOTS>", "IFNOTS", -1, ASSOC_RIGHT, &type_string, NULL, &type_void},
389 {7, "<IFS>", "IFS", -1, ASSOC_RIGHT, &type_string, NULL, &type_void},
391 {7, "!", "NOT_I", -1, ASSOC_LEFT, &type_integer, &type_void, &type_integer},
393 {7, "/", "DIV_VF", 3, ASSOC_LEFT, &type_vector, &type_float, &type_float},
395 {7, "^", "XOR_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
396 {7, ">>", "RSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
397 {7, "<<", "LSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
400 {7, "<ARRAY>", "GET_POINTER", -1, ASSOC_LEFT, &type_float, &type_integer, &type_pointer},
401 {7, "<ARRAY>", "MUL4ADD_I", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer},
403 {7, "=", "LOADA_F", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float},
404 {7, "=", "LOADA_V", 6, ASSOC_LEFT, &type_vector, &type_integer, &type_vector},
405 {7, "=", "LOADA_S", 6, ASSOC_LEFT, &type_string, &type_integer, &type_string},
406 {7, "=", "LOADA_ENT", 6, ASSOC_LEFT, &type_entity, &type_integer, &type_entity},
407 {7, "=", "LOADA_FLD", 6, ASSOC_LEFT, &type_field, &type_integer, &type_field},
408 {7, "=", "LOADA_FNC", 6, ASSOC_LEFT, &type_function, &type_integer, &type_function},
409 {7, "=", "LOADA_I", 6, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
411 {7, "=", "STORE_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void},
412 {7, ".", "INDIRECT_P", 1, ASSOC_LEFT, &type_entity, &type_field, &type_pointer},
414 {7, "=", "LOADP_F", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_float},
415 {7, "=", "LOADP_V", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_vector},
416 {7, "=", "LOADP_S", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_string},
417 {7, "=", "LOADP_ENT", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_entity},
418 {7, "=", "LOADP_FLD", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_field},
419 {7, "=", "LOADP_FNC", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_function},
420 {7, "=", "LOADP_I", 6, ASSOC_LEFT, &type_pointer, &type_integer, &type_integer},
423 {7, "<=", "LE_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
424 {7, ">=", "GE_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
425 {7, "<", "LT_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
426 {7, ">", "GT_I", 5, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
428 {7, "<=", "LE_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
429 {7, ">=", "GE_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
430 {7, "<", "LT_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
431 {7, ">", "GT_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
433 {7, "<=", "LE_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
434 {7, ">=", "GE_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
435 {7, "<", "LT_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
436 {7, ">", "GT_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
438 {7, "==", "EQ_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
439 {7, "==", "EQ_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
441 //-------------------------------------
442 //string manipulation.
443 {7, "+", "ADD_SF", 4, ASSOC_LEFT, &type_string, &type_float, &type_string},
444 {7, "-", "SUB_S", 4, ASSOC_LEFT, &type_string, &type_string, &type_float},
445 {7, "<STOREP_C>", "STOREP_C", 1, ASSOC_RIGHT, &type_string, &type_float, &type_float},
446 {7, "<LOADP_C>", "LOADP_C", 1, ASSOC_LEFT, &type_string, &type_void, &type_float},
447 //-------------------------------------
451 {7, "*", "MUL_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
452 {7, "*", "MUL_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
453 {7, "*", "MUL_VI", 5, ASSOC_LEFT, &type_vector, &type_integer, &type_vector},
454 {7, "*", "MUL_IV", 5, ASSOC_LEFT, &type_integer, &type_vector, &type_vector},
456 {7, "/", "DIV_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
457 {7, "/", "DIV_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
459 {7, "&", "BITAND_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
460 {7, "|", "BITOR_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
461 {7, "&", "BITAND_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
462 {7, "|", "BITOR_FI", 5, ASSOC_LEFT, &type_float, &type_integer, &type_float},
464 {7, "&&", "AND_I", 7, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
465 {7, "||", "OR_I", 7, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
466 {7, "&&", "AND_IF", 7, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
467 {7, "||", "OR_IF", 7, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
468 {7, "&&", "AND_FI", 7, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
469 {7, "||", "OR_FI", 7, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
470 {7, "!=", "NE_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
471 {7, "!=", "NE_FI", 5, ASSOC_LEFT, &type_float, &type_float, &type_integer},
478 {7, "<>", "GSTOREP_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
479 {7, "<>", "GSTOREP_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
480 {7, "<>", "GSTOREP_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
481 {7, "<>", "GSTOREP_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
482 {7, "<>", "GSTOREP_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
483 {7, "<>", "GSTOREP_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
484 {7, "<>", "GSTOREP_V", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
486 {7, "<>", "GADDRESS", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
488 {7, "<>", "GLOAD_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
489 {7, "<>", "GLOAD_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
490 {7, "<>", "GLOAD_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
491 {7, "<>", "GLOAD_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
492 {7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
493 {7, "<>", "GLOAD_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
495 {7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_integer, NULL, NULL},
497 {7, "<UNUSED>", "UNUSED", 6, ASSOC_RIGHT, &type_void, &type_void, &type_void},
498 {7, "<PUSH>", "PUSH", -1, ASSOC_RIGHT, &type_float, &type_void, &type_pointer},
499 {7, "<POP>", "POP", -1, ASSOC_RIGHT, &type_float, &type_void, &type_void},
501 {7, "<SWITCH_I>", "SWITCH_I", -1, ASSOC_LEFT, &type_void, NULL, &type_void},
502 {7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
504 {6, "<IF_F>", "IF_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
505 {6, "<IFNOT_F>","IFNOT_F", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
507 /* emulated ops begin here */
508 {7, "<>", "OP_EMULATED", -1, ASSOC_LEFT, &type_float, &type_float, &type_float},
511 {7, "|=", "BITSET_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer},
512 {7, "|=", "BITSETP_I", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer},
515 {7, "*=", "MULSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
516 {7, "/=", "DIVSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
517 {7, "+=", "ADDSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
518 {7, "-=", "SUBSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer},
520 {7, "*=", "MULSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
521 {7, "/=", "DIVSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
522 {7, "+=", "ADDSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
523 {7, "-=", "SUBSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer},
525 {7, "*=", "MULSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
526 {7, "*=", "MULSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
527 {7, "/=", "DIVSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
528 {7, "/=", "DIVSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
529 {7, "+=", "ADDSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
530 {7, "+=", "ADDSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
531 {7, "-=", "SUBSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float},
532 {7, "-=", "SUBSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float},
534 {7, "*=", "MULSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
535 {7, "*=", "MULSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
536 {7, "/=", "DIVSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
537 {7, "/=", "DIVSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
538 {7, "+=", "ADDSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
539 {7, "+=", "ADDSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
540 {7, "-=", "SUBSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float},
541 {7, "-=", "SUBSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float},
543 {7, "*=", "MULSTORE_VI", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_integer, &type_vector},
544 {7, "*=", "MULSTOREP_VI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector},
546 {7, "=", "LOADA_STRUCT", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float},
548 {7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_pointer},
554 pbool OpAssignsToC(unsigned int op)
556 // calls, switches and cases DON'T
557 if(pr_opcodes[op].type_c == &type_void)
559 if(op >= OP_SWITCH_F && op <= OP_CALL8H)
561 if(op >= OP_RAND0 && op <= OP_RANDV2)
563 // they use a and b, but have 3 types
565 if(op >= OP_BITSET && op <= OP_BITCLRP)
567 /*if(op >= OP_STORE_I && op <= OP_STORE_FI)
568 return false; <- add STOREP_*?*/
569 if(op == OP_STOREP_C || op == OP_LOADP_C)
571 if(op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V)
575 pbool OpAssignsToB(unsigned int op)
577 if(op >= OP_BITSET && op <= OP_BITCLRP)
579 if(op >= OP_STORE_I && op <= OP_STORE_FI)
581 if(op == OP_STOREP_C || op == OP_LOADP_C)
583 if(op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V)
585 if(op >= OP_STORE_F && op <= OP_STOREP_FNC)
589 /*pbool OpAssignedTo(QCC_def_t *v, unsigned int op)
594 else if(OpAssignsToB(op))
600 #undef ASSOC_RIGHT_RESULT
602 #define TOP_PRIORITY 7
603 #define FUNC_PRIORITY 1
604 #define UNARY_PRIORITY 1
605 #define NOT_PRIORITY 5
607 #define CONDITION_PRIORITY 7
610 //this system cuts out 10/120
611 //these evaluate as top first.
612 QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
615 /* &pr_opcodes[OP_DONE],
616 &pr_opcodes[OP_RETURN],
618 &pr_opcodes[OP_NOT_F],
619 &pr_opcodes[OP_NOT_V],
620 &pr_opcodes[OP_NOT_S],
621 &pr_opcodes[OP_NOT_ENT],
622 &pr_opcodes[OP_NOT_FNC],
625 &pr_opcodes[OP_IFNOT],
626 &pr_opcodes[OP_CALL0],
627 &pr_opcodes[OP_CALL1],
628 &pr_opcodes[OP_CALL2],
629 &pr_opcodes[OP_CALL3],
630 &pr_opcodes[OP_CALL4],
631 &pr_opcodes[OP_CALL5],
632 &pr_opcodes[OP_CALL6],
633 &pr_opcodes[OP_CALL7],
634 &pr_opcodes[OP_CALL8],
635 &pr_opcodes[OP_STATE],
636 &pr_opcodes[OP_GOTO],
638 &pr_opcodes[OP_IFNOTS],
641 &pr_opcodes[OP_NOT_I],
645 &pr_opcodes[OP_LOAD_F],
646 &pr_opcodes[OP_LOAD_V],
647 &pr_opcodes[OP_LOAD_S],
648 &pr_opcodes[OP_LOAD_ENT],
649 &pr_opcodes[OP_LOAD_FLD],
650 &pr_opcodes[OP_LOAD_FNC],
651 &pr_opcodes[OP_LOAD_I],
652 &pr_opcodes[OP_LOAD_P],
653 &pr_opcodes[OP_ADDRESS],
656 /* //conversion. don't use
657 &pr_opcodes[OP_C_ITOF],
658 &pr_opcodes[OP_C_FTOI],
659 &pr_opcodes[OP_CP_ITOF],
660 &pr_opcodes[OP_CP_FTOI],
663 &pr_opcodes[OP_MUL_F],
664 &pr_opcodes[OP_MUL_V],
665 &pr_opcodes[OP_MUL_FV],
666 &pr_opcodes[OP_MUL_IV],
667 &pr_opcodes[OP_MUL_VF],
668 &pr_opcodes[OP_MUL_VI],
669 &pr_opcodes[OP_MUL_I],
670 &pr_opcodes[OP_MUL_FI],
671 &pr_opcodes[OP_MUL_IF],
673 &pr_opcodes[OP_DIV_F],
674 &pr_opcodes[OP_DIV_I],
675 &pr_opcodes[OP_DIV_FI],
676 &pr_opcodes[OP_DIV_IF],
677 &pr_opcodes[OP_DIV_VF],
679 &pr_opcodes[OP_BITAND_F],
680 &pr_opcodes[OP_BITAND_I],
681 &pr_opcodes[OP_BITAND_IF],
682 &pr_opcodes[OP_BITAND_FI],
684 &pr_opcodes[OP_BITOR_F],
685 &pr_opcodes[OP_BITOR_I],
686 &pr_opcodes[OP_BITOR_IF],
687 &pr_opcodes[OP_BITOR_FI],
689 &pr_opcodes[OP_XOR_I],
690 &pr_opcodes[OP_RSHIFT_I],
691 &pr_opcodes[OP_LSHIFT_I],
696 &pr_opcodes[OP_ADD_F],
697 &pr_opcodes[OP_ADD_V],
698 &pr_opcodes[OP_ADD_I],
699 &pr_opcodes[OP_ADD_FI],
700 &pr_opcodes[OP_ADD_IF],
701 &pr_opcodes[OP_ADD_SF],
703 &pr_opcodes[OP_SUB_F],
704 &pr_opcodes[OP_SUB_V],
705 &pr_opcodes[OP_SUB_I],
706 &pr_opcodes[OP_SUB_FI],
707 &pr_opcodes[OP_SUB_IF],
708 &pr_opcodes[OP_SUB_S],
712 &pr_opcodes[OP_EQ_F],
713 &pr_opcodes[OP_EQ_V],
714 &pr_opcodes[OP_EQ_S],
715 &pr_opcodes[OP_EQ_E],
716 &pr_opcodes[OP_EQ_FNC],
717 &pr_opcodes[OP_EQ_I],
718 &pr_opcodes[OP_EQ_IF],
719 &pr_opcodes[OP_EQ_FI],
721 &pr_opcodes[OP_NE_F],
722 &pr_opcodes[OP_NE_V],
723 &pr_opcodes[OP_NE_S],
724 &pr_opcodes[OP_NE_E],
725 &pr_opcodes[OP_NE_FNC],
726 &pr_opcodes[OP_NE_I],
727 &pr_opcodes[OP_NE_IF],
728 &pr_opcodes[OP_NE_FI],
730 &pr_opcodes[OP_LE_F],
731 &pr_opcodes[OP_LE_I],
732 &pr_opcodes[OP_LE_IF],
733 &pr_opcodes[OP_LE_FI],
734 &pr_opcodes[OP_GE_F],
735 &pr_opcodes[OP_GE_I],
736 &pr_opcodes[OP_GE_IF],
737 &pr_opcodes[OP_GE_FI],
738 &pr_opcodes[OP_LT_F],
739 &pr_opcodes[OP_LT_I],
740 &pr_opcodes[OP_LT_IF],
741 &pr_opcodes[OP_LT_FI],
742 &pr_opcodes[OP_GT_F],
743 &pr_opcodes[OP_GT_I],
744 &pr_opcodes[OP_GT_IF],
745 &pr_opcodes[OP_GT_FI],
749 &pr_opcodes[OP_STOREP_P],
751 &pr_opcodes[OP_STORE_F],
752 &pr_opcodes[OP_STORE_V],
753 &pr_opcodes[OP_STORE_S],
754 &pr_opcodes[OP_STORE_ENT],
755 &pr_opcodes[OP_STORE_FLD],
756 &pr_opcodes[OP_STORE_FNC],
757 &pr_opcodes[OP_STORE_I],
758 &pr_opcodes[OP_STORE_IF],
759 &pr_opcodes[OP_STORE_FI],
760 &pr_opcodes[OP_STORE_P],
762 &pr_opcodes[OP_STOREP_F],
763 &pr_opcodes[OP_STOREP_V],
764 &pr_opcodes[OP_STOREP_S],
765 &pr_opcodes[OP_STOREP_ENT],
766 &pr_opcodes[OP_STOREP_FLD],
767 &pr_opcodes[OP_STOREP_FNC],
768 &pr_opcodes[OP_STOREP_I],
769 &pr_opcodes[OP_STOREP_IF],
770 &pr_opcodes[OP_STOREP_FI],
772 &pr_opcodes[OP_DIVSTORE_F],
773 &pr_opcodes[OP_DIVSTORE_I],
774 &pr_opcodes[OP_DIVSTORE_FI],
775 &pr_opcodes[OP_DIVSTORE_IF],
776 &pr_opcodes[OP_DIVSTOREP_F],
777 &pr_opcodes[OP_DIVSTOREP_I],
778 &pr_opcodes[OP_DIVSTOREP_IF],
779 &pr_opcodes[OP_DIVSTOREP_FI],
780 &pr_opcodes[OP_MULSTORE_F],
781 &pr_opcodes[OP_MULSTORE_VF],
782 &pr_opcodes[OP_MULSTORE_VI],
783 &pr_opcodes[OP_MULSTORE_I],
784 &pr_opcodes[OP_MULSTORE_IF],
785 &pr_opcodes[OP_MULSTORE_FI],
786 &pr_opcodes[OP_MULSTOREP_F],
787 &pr_opcodes[OP_MULSTOREP_VF],
788 &pr_opcodes[OP_MULSTOREP_VI],
789 &pr_opcodes[OP_MULSTOREP_I],
790 &pr_opcodes[OP_MULSTOREP_IF],
791 &pr_opcodes[OP_MULSTOREP_FI],
792 &pr_opcodes[OP_ADDSTORE_F],
793 &pr_opcodes[OP_ADDSTORE_V],
794 &pr_opcodes[OP_ADDSTORE_I],
795 &pr_opcodes[OP_ADDSTORE_IF],
796 &pr_opcodes[OP_ADDSTORE_FI],
797 &pr_opcodes[OP_ADDSTOREP_F],
798 &pr_opcodes[OP_ADDSTOREP_V],
799 &pr_opcodes[OP_ADDSTOREP_I],
800 &pr_opcodes[OP_ADDSTOREP_IF],
801 &pr_opcodes[OP_ADDSTOREP_FI],
802 &pr_opcodes[OP_SUBSTORE_F],
803 &pr_opcodes[OP_SUBSTORE_V],
804 &pr_opcodes[OP_SUBSTORE_I],
805 &pr_opcodes[OP_SUBSTORE_IF],
806 &pr_opcodes[OP_SUBSTORE_FI],
807 &pr_opcodes[OP_SUBSTOREP_F],
808 &pr_opcodes[OP_SUBSTOREP_V],
809 &pr_opcodes[OP_SUBSTOREP_I],
810 &pr_opcodes[OP_SUBSTOREP_IF],
811 &pr_opcodes[OP_SUBSTOREP_FI],
813 &pr_opcodes[OP_BITSET],
814 &pr_opcodes[OP_BITSET_I],
815 // &pr_opcodes[OP_BITSET_IF],
816 // &pr_opcodes[OP_BITSET_FI],
817 &pr_opcodes[OP_BITSETP],
818 &pr_opcodes[OP_BITSETP_I],
819 // &pr_opcodes[OP_BITSETP_IF],
820 // &pr_opcodes[OP_BITSETP_FI],
821 &pr_opcodes[OP_BITCLR],
822 &pr_opcodes[OP_BITCLRP],
826 &pr_opcodes[OP_AND_F],
827 &pr_opcodes[OP_AND_I],
828 &pr_opcodes[OP_AND_IF],
829 &pr_opcodes[OP_AND_FI],
830 &pr_opcodes[OP_OR_F],
831 &pr_opcodes[OP_OR_I],
832 &pr_opcodes[OP_OR_IF],
833 &pr_opcodes[OP_OR_FI],
838 pbool QCC_OPCodeValid(QCC_opcode_t *op)
841 num = op - pr_opcodes;
843 switch(qcc_targetformat)
848 if (num < OP_MULSTORE_F)
852 if (num >= OP_SWITCH_V && num <= OP_SWITCH_FNC) //these were assigned numbers but were never actually implemtented in standard h2.
854 // if (num >= OP_MULSTORE_F && num <= OP_SUBSTOREP_V)
856 if (num <= OP_CALL8H) //CALLXH are fixed up. This is to provide more dynamic switching...??
861 //no emulated opcodes
862 if (num >= OP_NUMREALOPS)
867 if (num < OP_MULSTORE_F)
870 //no emulated opcodes
871 if (num >= OP_NUMREALOPS)
875 //DPFIXME: this is a list of the extended opcodes. I was conservative regarding supported ones.
876 // at the time of writing, these are the ones that look like they'll work just fine in Blub\0's patch.
877 // the ones that looked too permissive with bounds checks, or would give false positives are disabled.
878 // if the DP guys want I can change them as desired.
881 //maths and conditionals (simple opcodes that read from specific globals and write to a global)
929 //stores into a pointer (generated from 'ent.field=XXX')
930 case OP_STOREP_I: //no worse than the other OP_STOREP_X functions
931 //reads from an entity field
932 case OP_LOAD_I: //no worse than the other OP_LOAD_X functions.
936 //stores into the globals array.
937 //they can change any global dynamically, but thats no security risk.
938 //fteqcc will not automatically generate these.
939 //fteqw does not support them either.
949 //this opcode looks weird
950 case OP_GADDRESS://floatc = globals[inta + floatb] (fte does not support)
953 //fteqcc will not automatically generate these
954 //fteqw does not support them either, for that matter.
955 case OP_GLOAD_I://c = globals[inta]
956 case OP_GLOAD_F://note: fte does not support these
963 return false; //DPFIXME: this is commented out in the patch I was given a link to... because the opcode wasn't defined.
965 //these are reportedly functional.
984 case OP_BITSET: // b |= a
985 case OP_BITCLR: // b &= ~a
986 case OP_BITSETP: // *b |= a
987 case OP_BITCLRP: // *b &= ~a
988 return false; //FIXME: I do not fully follow the controversy over these.
999 //assuming the pointers here are fine, the return values are a little strange.
1003 case OP_ADDSTOREP_F: // e.f += f
1004 case OP_ADDSTOREP_V: // e.v += v
1007 case OP_SUBSTOREP_F: // e.f += f
1008 case OP_SUBSTOREP_V: // e.v += v
1018 return false; //DPFIXME: DP does not bounds check these properly. I won't generate them.
1022 return true; //these look fine.
1024 case OP_STOREP_C: // store a char in a string
1025 return false; //DPFIXME: dp's bounds check may give false positives with expected uses.
1028 case OP_MULSTORE_VF:
1029 case OP_MULSTOREP_F:
1030 case OP_MULSTOREP_VF: // e.v *= f
1032 case OP_DIVSTOREP_F:
1036 case OP_STOREP_IF: // store a value to a pointer
1042 case OP_IFNOT_F: //added, but not in dp yet
1048 return false; //DPFIXME: These are not bounds checked at all.
1049 case OP_GLOBALADDRESS:
1050 return true; //DPFIXME: DP will reject these pointers if they are ever used.
1051 case OP_POINTER_ADD:
1052 return true; //just maths.
1054 case OP_ADD_SF: //(char*)c = (char*)a + (float)b
1055 case OP_SUB_S: //(float)c = (char*)a - (char*)b
1057 case OP_LOADP_C: //load character from a string
1058 return false; //DPFIXME: DP looks like it'll reject these or wrongly allow.
1074 case OP_FETCH_GBL_F:
1075 case OP_FETCH_GBL_S:
1076 case OP_FETCH_GBL_E:
1077 case OP_FETCH_GBL_FNC:
1078 case OP_FETCH_GBL_V:
1079 return false; //DPFIXME: DP will not bounds check this properly, it is too permissive.
1082 return false; //DP does not support this hexenc opcode.
1084 return true; //but it does support this one.
1086 default: //anything I forgot to mention is new.
1093 #define EXPR_WARN_ABOVE_1 2
1094 #define EXPR_DISALLOW_COMMA 4
1095 QCC_def_t *QCC_PR_Expression (int priority, int exprflags);
1096 int QCC_AStatementJumpsTo(int targ, int first, int last);
1097 pbool QCC_StatementIsAJump(int stnum, int notifdest);
1099 temp_t *functemps; //floats/strings/funcs/ents...
1101 //===========================================================================
1108 Emits a primitive statement, returning the var it places it's value in
1111 QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement);
1112 static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted)
1114 /*no conversion needed*/
1115 if (var->type->type == wanted)
1117 if (var->type->type == ev_integer && wanted == ev_function)
1119 if (var->type->type == ev_integer && wanted == ev_pointer)
1121 /*stuff needs converting*/
1122 if (var->type->type == ev_pointer && var->type->aux_type)
1124 if (var->type->aux_type->type == ev_float && wanted == ev_integer)
1127 if (var->type->aux_type->type == ev_integer && wanted == ev_float)
1132 if (var->type->type == ev_float && wanted == ev_integer)
1133 return OP_CONV_FTOI;
1135 if (var->type->type == ev_integer && wanted == ev_float)
1136 return OP_CONV_ITOF;
1142 QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted, pbool fatal)
1144 extern char *basictypenames[];
1147 if (pr_classtype && var->type->type == ev_field && wanted != ev_field)
1150 { //load self.var into a temp
1152 self = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
1156 return QCC_PR_Statement(pr_opcodes+OP_LOAD_F, self, var, NULL);
1158 return QCC_PR_Statement(pr_opcodes+OP_LOAD_S, self, var, NULL);
1160 return QCC_PR_Statement(pr_opcodes+OP_LOAD_FNC, self, var, NULL);
1162 return QCC_PR_Statement(pr_opcodes+OP_LOAD_V, self, var, NULL);
1164 return QCC_PR_Statement(pr_opcodes+OP_LOAD_ENT, self, var, NULL);
1166 QCC_Error(ERR_INTERNAL, "Inexplicit field load failed, try explicit");
1171 o = QCC_ShouldConvert(var, wanted);
1173 if (o == 0) //type already matches
1175 if (flag_typeexplicit)
1176 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name);
1180 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name);
1185 return QCC_PR_Statement(&pr_opcodes[o], var, NULL, NULL); //conversion return value
1187 QCC_def_t *QCC_MakeTranslateStringConst(char *value);
1188 QCC_def_t *QCC_MakeStringConst(char *value);
1189 QCC_def_t *QCC_MakeFloatConst(float value);
1190 QCC_def_t *QCC_MakeIntConst(int value);
1191 QCC_def_t *QCC_MakeVectorConst(float a, float b, float c);
1193 typedef struct freeoffset_s {
1194 struct freeoffset_s *next;
1199 freeoffset_t *freeofs;
1201 //assistant functions. This can safly be bipassed with the old method for more complex things.
1202 gofs_t QCC_GetFreeOffsetSpace(unsigned int size)
1205 if (opt_locals_marshalling)
1207 freeoffset_t *fofs, *prev;
1208 for (fofs = freeofs, prev = NULL; fofs; fofs=fofs->next)
1210 if (fofs->size == size)
1213 prev->next = fofs->next;
1215 freeofs = fofs->next;
1221 for (fofs = freeofs, prev = NULL; fofs; fofs=fofs->next)
1223 if (fofs->size > size)
1228 return fofs->ofs-size;
1234 ofs = numpr_globals;
1235 numpr_globals+=size;
1237 if (numpr_globals >= MAX_REGS)
1239 if (!opt_overlaptemps || !opt_locals_marshalling)
1240 QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS - you'll need to use more optimisations");
1242 QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS");
1248 void QCC_FreeOffset(gofs_t ofs, unsigned int size)
1251 if (ofs+size == numpr_globals)
1252 { //fixme: is this a bug?
1253 numpr_globals -= size;
1257 for (fofs = freeofs; fofs; fofs=fofs->next)
1259 //fixme: if this means the last block becomes free, free them all.
1260 if (fofs->ofs == ofs + size)
1266 if (fofs->ofs+fofs->size == ofs)
1273 fofs = qccHunkAlloc(sizeof(freeoffset_t));
1274 fofs->next = freeofs;
1282 static QCC_def_t *QCC_GetTemp(QCC_type_t *type)
1284 //#define CRAZYTEMPOPTS //not worth it. saves 2 temps with hexen2 (without even touching numpr_globals)
1287 #ifdef CRAZYTEMPOPTS
1288 temp_t *best = NULL;
1291 var_c = (void *)qccHunkAlloc (sizeof(QCC_def_t));
1292 memset (var_c, 0, sizeof(QCC_def_t));
1294 var_c->name = "temp";
1296 if (opt_overlaptemps) //don't exceed. This lets us allocate a huge block, and still be able to compile smegging big funcs.
1298 for (t = functemps; t; t = t->next)
1300 if (!t->used && t->size == type->size)
1302 #ifdef CRAZYTEMPOPTS
1304 if (t->scope == pr_scope)
1309 #ifdef CRAZYTEMPOPTS
1312 if (t && t->scope && t->scope != pr_scope)
1313 QCC_Error(ERR_INTERNAL, "Internal error temp has scope not equal to current scope");
1317 //allocate a new one
1318 t = qccHunkAlloc(sizeof(temp_t));
1319 t->size = type->size;
1320 t->next = functemps;
1323 t->ofs = QCC_GetFreeOffsetSpace(t->size);
1328 optres_overlaptemps+=t->size;
1329 //use a previous one.
1330 var_c->ofs = t->ofs;
1332 t->lastfunc = pr_scope;
1334 else if (opt_locals_marshalling)
1336 //allocate a new one
1337 t = qccHunkAlloc(sizeof(temp_t));
1338 t->size = type->size;
1340 t->next = functemps;
1343 t->ofs = QCC_GetFreeOffsetSpace(t->size);
1347 var_c->ofs = t->ofs;
1349 t->lastfunc = pr_scope;
1353 // we're not going to reallocate any temps so allocate permanently
1354 var_c->ofs = QCC_GetFreeOffsetSpace(type->size);
1355 numtemps+=type->size;
1358 var_c->s_file = s_file;
1359 var_c->s_line = pr_source_line;
1362 var_c->temp->used = true;
1367 //nothing else references this temp.
1368 static void QCC_FreeTemp(QCC_def_t *t)
1371 t->temp->used = false;
1374 static void QCC_UnFreeTemp(QCC_def_t *t)
1377 t->temp->used = true;
1380 //We've just parsed a statement.
1381 //We can gaurentee that any used temps are now not used.
1383 static void QCC_FreeTemps(void)
1387 if (def_ret.temp && def_ret.temp->used)
1389 QCC_PR_ParseWarning(WARN_DEBUGGING, "Return value still in use in %s", pr_scope->name);
1390 def_ret.temp->used = false;
1396 if (t->used && !pr_error_count) //don't print this after an error jump out.
1397 QCC_PR_ParseWarning(WARN_DEBUGGING, "Internal: temp(ofs %i) was not released in %s. This implies miscompilation.", t->ofs, pr_scope->name);
1403 #define QCC_FreeTemps()
1405 void QCC_PurgeTemps(void)
1410 //temps that are still in use over a function call can be considered dodgy.
1411 //we need to remap these to locally defined temps, on return from the function so we know we got them all.
1412 static void QCC_LockActiveTemps(void)
1420 t->scope = pr_scope;
1426 static void QCC_LockTemp(QCC_def_t *d)
1428 if (d->temp && d->temp->used)
1429 d->temp->scope = pr_scope;
1431 static void QCC_ForceLockTempForOffset(int ofs)
1434 for (t = functemps; t; t = t->next)
1435 if(t->ofs == ofs /* && t->used */)
1436 t->scope = pr_scope;
1439 static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement)
1447 QCC_dstatement_t *st;
1451 for (i = firststatement, st = &statements[i]; i < laststatement; i++, st++)
1453 if (pr_opcodes[st->op].type_a && st->a == t->ofs)
1457 newofs = QCC_GetFreeOffsetSpace(t->size);
1460 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, false, false);
1461 def->nextlocal = pr.localvars;
1462 def->constant = false;
1464 sprintf(buffer, "locked_%i", t->ofs);
1465 def->name = qccHunkAlloc(strlen(buffer)+1);
1466 strcpy(def->name, buffer);
1472 if (pr_opcodes[st->op].type_b && st->b == t->ofs)
1476 newofs = QCC_GetFreeOffsetSpace(t->size);
1479 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, false, false);
1480 def->nextlocal = pr.localvars;
1481 def->constant = false;
1483 sprintf(buffer, "locked_%i", t->ofs);
1484 def->name = qccHunkAlloc(strlen(buffer)+1);
1485 strcpy(def->name, buffer);
1491 if (pr_opcodes[st->op].type_c && st->c == t->ofs)
1495 newofs = QCC_GetFreeOffsetSpace(t->size);
1498 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, false, false);
1499 def->nextlocal = pr.localvars;
1500 def->constant = false;
1502 sprintf(buffer, "locked_%i", t->ofs);
1503 def->name = qccHunkAlloc(strlen(buffer)+1);
1504 strcpy(def->name, buffer);
1513 static void QCC_RemapLockedTemps(int firststatement, int laststatement)
1520 if (t->scope || opt_locals_marshalling)
1522 QCC_RemapLockedTemp(t, firststatement, laststatement);
1530 static void QCC_fprintfLocals(FILE *f, gofs_t paramstart, gofs_t paramend)
1536 for (var = pr.localvars; var; var = var->nextlocal)
1538 if (var->ofs >= paramstart && var->ofs < paramend)
1541 fprintf(f, "local %s %s[%i];\n", TypeName(var->type), var->name, var->arraysize);
1543 fprintf(f, "local %s %s;\n", TypeName(var->type), var->name);
1546 for (t = functemps, i = 0; t; t = t->next, i++)
1548 if (t->lastfunc == pr_scope)
1550 fprintf(f, "local %s temp_%i;\n", (t->size == 1)?"float":"vector", i);
1556 void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t firstparm);
1557 static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size)
1559 static char message[1024];
1565 for (t = functemps, i = 0; t; t = t->next, i++)
1567 if (ofs >= t->ofs && ofs < t->ofs + t->size)
1570 sprintf(message, "temp_%i_%c", t->ofs, 'x' + (ofs-t->ofs)%3);
1572 sprintf(message, "temp_%i", t->ofs);
1577 for (var = pr.localvars; var; var = var->nextlocal)
1579 if (var->scope && var->scope != pr_scope)
1580 continue; //this should be an error
1581 if (ofs >= var->ofs && ofs < var->ofs + var->type->size)
1585 if (!STRCMP(var->name, "IMMEDIATE")) //continue, don't get bogged down by multiple bits of code
1587 if (size < var->type->size)
1588 sprintf(message, "%s_%c", var->name, 'x' + (ofs-var->ofs)%3);
1590 sprintf(message, "%s", var->name);
1596 for (var = pr.def_head.next; var; var = var->next)
1598 if (var->scope && var->scope != pr_scope)
1601 if (ofs >= var->ofs && ofs < var->ofs + var->type->size)
1605 if (!STRCMP(var->name, "IMMEDIATE"))
1607 switch(var->type->type)
1610 sprintf(message, "\"%.1020s\"", &strings[((int *)qcc_pr_globals)[var->ofs]]);
1613 sprintf(message, "%i", ((int *)qcc_pr_globals)[var->ofs]);
1616 sprintf(message, "%f", qcc_pr_globals[var->ofs]);
1619 sprintf(message, "'%f %f %f'", qcc_pr_globals[var->ofs], qcc_pr_globals[var->ofs+1], qcc_pr_globals[var->ofs+2]);
1622 sprintf(message, "IMMEDIATE");
1626 if (size < var->type->size)
1627 sprintf(message, "%s_%c", var->name, 'x' + (ofs-var->ofs)%3);
1629 sprintf(message, "%s", var->name);
1637 if (ofs >= OFS_RETURN && ofs < OFS_PARM0)
1638 sprintf(message, "return");
1639 else if (ofs >= OFS_PARM0 && ofs < RESERVED_OFS)
1640 sprintf(message, "parm%i", (ofs-OFS_PARM0)/3);
1642 sprintf(message, "offset_%i", ofs);
1646 if (ofs >= OFS_RETURN && ofs < OFS_PARM0)
1647 sprintf(message, "return_%c", 'x' + ofs-OFS_RETURN);
1648 else if (ofs >= OFS_PARM0 && ofs < RESERVED_OFS)
1649 sprintf(message, "parm%i_%c", (ofs-OFS_PARM0)/3, 'x' + (ofs-OFS_PARM0)%3);
1651 sprintf(message, "offset_%i", ofs);
1657 QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force);
1659 QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement)
1661 QCC_dstatement_t *statement;
1662 QCC_def_t *var_c=NULL, *temp=NULL;
1664 if (outstatement == (QCC_dstatement_t **)0xffffffff)
1665 outstatement = NULL;
1666 else if (op->priority != -1 && op->priority != CONDITION_PRIORITY)
1668 if (op->associative!=ASSOC_LEFT)
1670 if (op->type_a != &type_pointer)
1671 var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type, false);
1676 var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type, false);
1678 var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type, false);
1684 var_a->references++;
1685 QCC_FreeTemp(var_a);
1689 var_b->references++;
1690 QCC_FreeTemp(var_b);
1693 if (keyword_class && var_a && var_b)
1695 if (var_a->type->type == ev_entity && var_b->type->type == ev_entity)
1696 if (var_a->type != var_b->type)
1697 if (strcmp(var_a->type->name, var_b->type->name))
1698 QCC_PR_ParseWarning(0, "Implicit cast from '%s' to '%s'", var_a->type->name, var_b->type->name);
1702 if (opt_constantarithmatic)
1704 if (var_a && var_a->constant)
1706 if (var_b && var_b->constant)
1708 //both are constants
1709 switch (op - pr_opcodes) //improve some of the maths.
1720 nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
1721 memset (nd, 0, sizeof(QCC_def_t));
1722 nd->type = var_a->type;
1723 nd->ofs = var_a->ofs + G_INT(var_b->ofs);
1724 nd->temp = var_a->temp;
1725 nd->constant = true;
1726 nd->name = var_a->name;
1731 optres_constantarithmatic++;
1732 return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs)));
1734 optres_constantarithmatic++;
1735 return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
1737 optres_constantarithmatic++;
1738 return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs));
1740 optres_constantarithmatic++;
1741 return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs));
1743 optres_constantarithmatic++;
1744 return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs));
1746 optres_constantarithmatic++;
1747 return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs));
1750 optres_constantarithmatic++;
1751 return QCC_MakeIntConst(G_INT(var_a->ofs) | G_INT(var_b->ofs));
1753 optres_constantarithmatic++;
1754 return QCC_MakeIntConst(G_INT(var_a->ofs) & G_INT(var_b->ofs));
1756 optres_constantarithmatic++;
1757 return QCC_MakeIntConst(G_INT(var_a->ofs) * G_INT(var_b->ofs));
1759 optres_constantarithmatic++;
1760 return QCC_MakeIntConst(G_INT(var_a->ofs) / G_INT(var_b->ofs));
1762 optres_constantarithmatic++;
1763 return QCC_MakeIntConst(G_INT(var_a->ofs) + G_INT(var_b->ofs));
1765 optres_constantarithmatic++;
1766 return QCC_MakeIntConst(G_INT(var_a->ofs) - G_INT(var_b->ofs));
1769 optres_constantarithmatic++;
1770 return QCC_MakeIntConst(G_INT(var_a->ofs) && G_INT(var_b->ofs));
1772 optres_constantarithmatic++;
1773 return QCC_MakeIntConst(G_INT(var_a->ofs) || G_INT(var_b->ofs));
1774 case OP_MUL_V: //mul_f is actually a dot-product
1775 optres_constantarithmatic++;
1776 return QCC_MakeFloatConst( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) +
1777 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1) +
1778 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
1780 optres_constantarithmatic++;
1781 return QCC_MakeVectorConst( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0),
1782 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1),
1783 G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2));
1785 optres_constantarithmatic++;
1786 return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs),
1787 G_FLOAT(var_a->ofs+1) * G_FLOAT(var_b->ofs),
1788 G_FLOAT(var_a->ofs+2) * G_FLOAT(var_b->ofs));
1790 optres_constantarithmatic++;
1791 return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0),
1792 G_FLOAT(var_a->ofs+1) + G_FLOAT(var_b->ofs+1),
1793 G_FLOAT(var_a->ofs+2) + G_FLOAT(var_b->ofs+2));
1795 optres_constantarithmatic++;
1796 return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0),
1797 G_FLOAT(var_a->ofs+1) - G_FLOAT(var_b->ofs+1),
1798 G_FLOAT(var_a->ofs+2) - G_FLOAT(var_b->ofs+2));
1803 //a is const, b is not
1804 switch (op - pr_opcodes)
1807 optres_constantarithmatic++;
1808 return QCC_MakeIntConst(G_FLOAT(var_a->ofs));
1810 optres_constantarithmatic++;
1811 return QCC_MakeFloatConst(G_INT(var_a->ofs));
1815 if (G_FLOAT(var_a->ofs) == 0)
1817 optres_constantarithmatic++;
1818 QCC_UnFreeTemp(var_b);
1823 if (G_FLOAT(var_a->ofs) == 1)
1825 optres_constantarithmatic++;
1826 QCC_UnFreeTemp(var_b);
1832 if (G_FLOAT(var_a->ofs) != 0)
1834 optres_constantarithmatic++;
1835 QCC_UnFreeTemp(var_b);
1843 if (G_INT(var_a->ofs) == 0)
1845 optres_constantarithmatic++;
1846 QCC_UnFreeTemp(var_b);
1851 if (G_INT(var_a->ofs) == 1)
1853 optres_constantarithmatic++;
1854 QCC_UnFreeTemp(var_b);
1860 if (G_INT(var_a->ofs) != 0)
1862 optres_constantarithmatic++;
1863 QCC_UnFreeTemp(var_b);
1870 else if (var_b && var_b->constant)
1872 //b is const, a is not
1873 switch (op - pr_opcodes)
1884 nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
1885 memset (nd, 0, sizeof(QCC_def_t));
1886 nd->type = var_a->type;
1887 nd->ofs = var_a->ofs + G_INT(var_b->ofs);
1888 nd->temp = var_a->temp;
1889 nd->constant = false;
1890 nd->name = var_a->name;
1898 if (G_FLOAT(var_b->ofs) == 0)
1900 optres_constantarithmatic++;
1901 QCC_UnFreeTemp(var_a);
1907 if (G_FLOAT(var_b->ofs) == 1)
1909 optres_constantarithmatic++;
1910 QCC_UnFreeTemp(var_a);
1914 //no bitand_f, I don't trust the casts
1916 if (G_FLOAT(var_b->ofs) != 0)
1918 optres_constantarithmatic++;
1919 QCC_UnFreeTemp(var_a);
1928 if (G_INT(var_b->ofs) == 0)
1930 optres_constantarithmatic++;
1931 QCC_UnFreeTemp(var_a);
1937 if (G_INT(var_b->ofs) == 1)
1939 optres_constantarithmatic++;
1940 QCC_UnFreeTemp(var_a);
1945 if (G_INT(var_b->ofs) == 0xffffffff)
1947 optres_constantarithmatic++;
1948 QCC_UnFreeTemp(var_a);
1952 if (G_INT(var_b->ofs) == 0)
1954 optres_constantarithmatic++;
1955 QCC_UnFreeTemp(var_a);
1963 switch (op - pr_opcodes)
1974 if (var_a->ofs == var_b->ofs)
1975 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same");
1976 if (var_a->constant || var_b->constant)
1977 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
1980 if (var_a->ofs == var_b->ofs)
1981 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameters for || are the same");
1982 if (var_a->constant || var_b->constant)
1983 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
1989 // if (opt_shortenifnots)
1990 // if (var_b->constant && ((int*)qcc_pr_globals)[var_b->ofs]==0) // (a == 0) becomes (!a)
1991 // op = &pr_opcodes[(op - pr_opcodes) - OP_EQ_F + OP_NOT_F];
2004 if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs)
2005 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
2013 // if (var_a->type->type == ev_function && !var_a->temp)
2014 // QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
2015 if (var_a->constant && !var_a->temp)
2016 QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
2023 { //optimise based on last statement.
2024 if (op - pr_opcodes == OP_IFNOT_I)
2026 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))
2028 if (statements[numstatements-1].c == var_a->ofs)
2030 static QCC_def_t nvara;
2031 if (statements[numstatements-1].op == OP_NOT_F)
2032 op = &pr_opcodes[OP_IF_F];
2034 op = &pr_opcodes[OP_IF_I];
2036 QCC_FreeTemp(var_a);
2037 memcpy(&nvara, var_a, sizeof(nvara));
2038 nvara.ofs = statements[numstatements].a;
2041 optres_shortenifnots++;
2045 else if (op - pr_opcodes == OP_IFNOT_F)
2047 if (opt_shortenifnots && var_a && statements[numstatements-1].op == OP_NOT_F)
2049 if (statements[numstatements-1].c == var_a->ofs)
2051 static QCC_def_t nvara;
2052 op = &pr_opcodes[OP_IF_F];
2054 QCC_FreeTemp(var_a);
2055 memcpy(&nvara, var_a, sizeof(nvara));
2056 nvara.ofs = statements[numstatements].a;
2059 optres_shortenifnots++;
2063 else if (op - pr_opcodes == OP_IFNOT_S)
2065 if (opt_shortenifnots && var_a && statements[numstatements-1].op == OP_NOT_S)
2067 if (statements[numstatements-1].c == var_a->ofs)
2069 static QCC_def_t nvara;
2070 op = &pr_opcodes[OP_IF_S];
2072 QCC_FreeTemp(var_a);
2073 memcpy(&nvara, var_a, sizeof(nvara));
2074 nvara.ofs = statements[numstatements].a;
2077 optres_shortenifnots++;
2081 else if (((unsigned) ((op - pr_opcodes) - OP_STORE_F) < 6) || (op-pr_opcodes) == OP_STORE_P)
2083 // remove assignments if what should be assigned is the 3rd operand of the previous statement?
2084 // don't if it's a call, callH, switch or case
2085 // && var_a->ofs >RESERVED_OFS)
2086 if (OpAssignsToC(statements[numstatements-1].op) &&
2087 opt_assignments && var_a && var_a->ofs == statements[numstatements-1].c)
2089 if (var_a->type->type == var_b->type->type)
2093 statement = &statements[numstatements-1];
2094 statement->c = var_b->ofs;
2096 if (var_a->type->type != var_b->type->type)
2097 QCC_PR_ParseWarning(0, "store type mismatch");
2098 var_b->references++;
2099 var_a->references--;
2100 QCC_FreeTemp(var_a);
2101 optres_assignments++;
2105 QCC_UnFreeTemp(var_b);
2114 statement = &statements[numstatements];
2117 if (!QCC_OPCodeValid(op))
2119 switch(op - pr_opcodes)
2121 case OP_LOADA_STRUCT:
2122 /*emit this anyway. if it reaches runtime then you messed up.
2123 this is valid only if you do &foo[0]*/
2128 var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false);
2130 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
2131 statement = &statements[numstatements];
2134 QCC_FreeTemp(var_a);
2135 op = &pr_opcodes[OP_IF_I];
2139 var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false);
2141 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL);
2142 statement = &statements[numstatements];
2145 QCC_FreeTemp(var_a);
2146 op = &pr_opcodes[OP_IFNOT_I];
2150 var_c = QCC_MakeFloatConst(0);
2152 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
2153 statement = &statements[numstatements];
2156 QCC_FreeTemp(var_a);
2157 op = &pr_opcodes[OP_IF_I];
2161 var_c = QCC_MakeFloatConst(0);
2163 var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL);
2164 statement = &statements[numstatements];
2167 QCC_FreeTemp(var_a);
2168 op = &pr_opcodes[OP_IFNOT_I];
2172 op = &pr_opcodes[OP_ADD_F];
2179 op = &pr_opcodes[OP_ADD_I];
2185 case OP_ADDSTORE_FI:
2186 op = &pr_opcodes[OP_ADD_FI];
2192 case OP_ADDSTORE_IF:
2193 op = &pr_opcodes[OP_ADD_IF];
2201 op = &pr_opcodes[OP_SUB_F];
2207 case OP_SUBSTORE_FI:
2208 op = &pr_opcodes[OP_SUB_FI];
2214 case OP_SUBSTORE_IF:
2215 op = &pr_opcodes[OP_SUB_IF];
2223 op = &pr_opcodes[OP_DIV_F];
2229 case OP_DIVSTORE_FI:
2230 op = &pr_opcodes[OP_DIV_FI];
2236 case OP_DIVSTORE_IF:
2237 op = &pr_opcodes[OP_DIV_IF];
2245 op = &pr_opcodes[OP_MUL_F];
2251 case OP_MULSTORE_IF:
2252 op = &pr_opcodes[OP_MUL_IF];
2258 case OP_MULSTORE_FI:
2259 op = &pr_opcodes[OP_MUL_FI];
2267 op = &pr_opcodes[OP_ADD_V];
2275 op = &pr_opcodes[OP_SUB_V];
2282 case OP_MULSTORE_VF:
2283 op = &pr_opcodes[OP_MUL_VF];
2289 case OP_MULSTORE_VI:
2290 op = &pr_opcodes[OP_MUL_VI];
2298 op = &pr_opcodes[OP_BITOR_I];
2305 op = &pr_opcodes[OP_BITOR_F];
2313 op = &pr_opcodes[OP_STOREP_I];
2317 //b = var, a = bit field.
2319 QCC_UnFreeTemp(var_a);
2320 QCC_UnFreeTemp(var_b);
2323 var_c = QCC_PR_Statement(&pr_opcodes[OP_BITAND_F], var_b, var_a, NULL);
2324 QCC_FreeTemp(var_c);
2325 statement = &statements[numstatements];
2328 QCC_FreeTemp(var_a);
2329 QCC_FreeTemp(var_b);
2331 op = &pr_opcodes[OP_SUB_F];
2337 case OP_SUBSTOREP_FI:
2338 case OP_SUBSTOREP_IF:
2339 case OP_ADDSTOREP_FI:
2340 case OP_ADDSTOREP_IF:
2341 case OP_MULSTOREP_FI:
2342 case OP_MULSTOREP_IF:
2343 case OP_DIVSTOREP_FI:
2344 case OP_DIVSTOREP_IF:
2346 case OP_MULSTOREP_VF:
2347 case OP_MULSTOREP_VI:
2348 case OP_SUBSTOREP_V:
2349 case OP_ADDSTOREP_V:
2351 case OP_SUBSTOREP_F:
2352 case OP_SUBSTOREP_I:
2353 case OP_ADDSTOREP_I:
2354 case OP_ADDSTOREP_F:
2355 case OP_MULSTOREP_F:
2356 case OP_DIVSTOREP_F:
2360 // QCC_PR_ParseWarning(0, "XSTOREP_F emulation is still experimental");
2361 QCC_UnFreeTemp(var_a);
2362 QCC_UnFreeTemp(var_b);
2363 //don't chain these... this expansion is not the same.
2366 int need_lock = false;
2369 for (st = numstatements-2; st>=0; st--)
2371 if (statements[st].op == OP_ADDRESS)
2372 if (statements[st].c == var_b->ofs)
2375 if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
2378 if (statements[st].c == var_b->ofs)
2388 var_c = QCC_GetTemp(*op->type_c);
2391 /*generate new OP_LOADP instruction*/
2392 statement->op = ((*op->type_c)->type==ev_vector)?OP_LOADP_V:OP_LOADP_F;
2393 statement->a = var_b->ofs;
2394 statement->b = var_c->ofs;
2399 /*it came from an OP_ADDRESS - st says the instruction*/
2402 QCC_ForceLockTempForOffset(statements[st].a);
2403 QCC_ForceLockTempForOffset(statements[st].b);
2404 QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
2407 /*generate new OP_ADDRESS instruction - FIXME: the arguments may have changed since the original instruction*/
2408 statement_linenums[statement-statements] = statement_linenums[st];
2409 statement->op = OP_ADDRESS;
2410 statement->a = statements[st].a;
2411 statement->b = statements[st].b;
2412 statement->c = statements[st].c;
2414 /*convert old one to an OP_LOAD*/
2415 statement_linenums[st] = pr_source_line;
2416 statements[st].op = ((*op->type_c)->type==ev_vector)?OP_LOAD_V:OP_LOAD_F;
2417 statements[st].a = statements[st].a;
2418 statements[st].b = statements[st].b;
2419 statements[st].c = var_c->ofs;
2423 statement = &statements[numstatements];
2426 statement_linenums[statement-statements] = pr_source_line;
2427 switch(op - pr_opcodes)
2429 case OP_SUBSTOREP_V:
2430 statement->op = OP_SUB_V;
2432 case OP_ADDSTOREP_V:
2433 statement->op = OP_ADD_V;
2435 case OP_MULSTOREP_VF:
2436 statement->op = OP_MUL_VF;
2438 case OP_MULSTOREP_VI:
2439 statement->op = OP_MUL_VI;
2441 case OP_SUBSTOREP_F:
2442 statement->op = OP_SUB_F;
2444 case OP_SUBSTOREP_I:
2445 statement->op = OP_SUB_I;
2447 case OP_SUBSTOREP_IF:
2448 statement->op = OP_SUB_IF;
2450 case OP_SUBSTOREP_FI:
2451 statement->op = OP_SUB_FI;
2453 case OP_ADDSTOREP_IF:
2454 statement->op = OP_ADD_IF;
2456 case OP_ADDSTOREP_FI:
2457 statement->op = OP_ADD_FI;
2459 case OP_MULSTOREP_IF:
2460 statement->op = OP_MUL_IF;
2462 case OP_MULSTOREP_FI:
2463 statement->op = OP_MUL_FI;
2465 case OP_DIVSTOREP_IF:
2466 statement->op = OP_DIV_IF;
2468 case OP_DIVSTOREP_FI:
2469 statement->op = OP_DIV_FI;
2471 case OP_ADDSTOREP_F:
2472 statement->op = OP_ADD_F;
2474 case OP_ADDSTOREP_I:
2475 statement->op = OP_ADD_I;
2477 case OP_MULSTOREP_F:
2478 statement->op = OP_MUL_F;
2480 case OP_DIVSTOREP_F:
2481 statement->op = OP_DIV_F;
2484 statement->op = OP_BITOR_F;
2487 statement->op = OP_BITOR_I;
2490 //float pointer float
2491 temp = QCC_GetTemp(type_float);
2492 statement->op = OP_BITAND_F;
2493 statement->a = var_c ? var_c->ofs : 0;
2494 statement->b = var_a ? var_a->ofs : 0;
2495 statement->c = temp->ofs;
2497 statement = &statements[numstatements];
2500 statement_linenums[statement-statements] = pr_source_line;
2501 statement->op = OP_SUB_F;
2506 default: //no way will this be hit...
2507 QCC_PR_ParseError(ERR_INTERNAL, "opcode invalid 3 times %i", op - pr_opcodes);
2509 if (op - pr_opcodes == OP_BITCLRP)
2511 statement->a = var_c ? var_c->ofs : 0;
2512 statement->b = temp ? temp->ofs : 0;
2513 statement->c = var_c->ofs;
2515 var_b = var_b; //this is the ptr.
2516 QCC_FreeTemp(var_a);
2517 var_a = var_c; //this is the value.
2521 statement->a = var_c ? var_c->ofs : 0;
2522 statement->b = var_a ? var_a->ofs : 0;
2523 statement->c = var_c->ofs;
2524 var_b = var_b; //this is the ptr.
2525 QCC_FreeTemp(var_a);
2526 var_a = var_c; //this is the value.
2529 op = &pr_opcodes[((*op->type_c)->type==ev_vector)?OP_STOREP_V:OP_STOREP_F];
2530 QCC_FreeTemp(var_c);
2532 QCC_FreeTemp(var_b);
2534 statement = &statements[numstatements];
2539 QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target", op->name, op->opname);
2545 *outstatement = statement;
2547 statement_linenums[statement-statements] = pr_source_line;
2548 statement->op = op - pr_opcodes;
2549 statement->a = var_a ? var_a->ofs : 0;
2550 statement->b = var_b ? var_b->ofs : 0;
2553 statement->c = var_c->ofs;
2555 else if (op->type_c == &type_void || op->associative==ASSOC_RIGHT || op->type_c == NULL)
2558 statement->c = 0; // ifs, gotos, and assignments
2559 // don't need vars allocated
2562 { // allocate result space
2563 var_c = QCC_GetTemp(*op->type_c);
2564 statement->c = var_c->ofs;
2565 if (op->type_b == &type_field)
2567 var_c->name = var_b->name;
2568 var_c->s_file = var_b->s_file;
2569 var_c->s_line = var_b->s_line;
2573 if ((op - pr_opcodes >= OP_LOAD_F && op - pr_opcodes <= OP_LOAD_FNC) ||
2574 op - pr_opcodes == OP_LOAD_I)
2576 if (var_b->constant == 2)
2577 var_c->constant = true;
2583 QCC_UnFreeTemp(var_a);
2591 QCC_PR_SimpleStatement
2593 Emits a primitive statement, returning the var it places it's value in
2596 QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force)
2598 QCC_dstatement_t *statement;
2600 if (!force && !QCC_OPCodeValid(pr_opcodes+op))
2602 QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target\n", pr_opcodes[op].name, pr_opcodes[op].opname);
2605 statement_linenums[numstatements] = pr_source_line;
2606 statement = &statements[numstatements];
2610 statement->a = var_a;
2611 statement->b = var_b;
2612 statement->c = var_c;
2616 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)
2618 QCC_dstatement_t *statement;
2620 if (!force && !QCC_OPCodeValid(op))
2622 // outputversion = op->extension;
2623 // if (noextensions)
2624 QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target\n", op->name, op->opname);
2627 statement = &statements[numstatements];
2630 statement_linenums[statement-statements] = pr_source_line;
2631 statement->op = op - pr_opcodes;
2632 statement->a = var_a ? var_a->ofs : 0;
2633 statement->b = var_b ? var_b->ofs : 0;
2634 statement->c = var_c ? var_c->ofs : 0;
2641 Looks for a preexisting constant
2644 QCC_def_t *QCC_PR_ParseImmediate (void)
2648 if (pr_immediate_type == type_float)
2650 cn = QCC_MakeFloatConst(pr_immediate._float);
2654 if (pr_immediate_type == type_integer)
2656 cn = QCC_MakeIntConst(pr_immediate._int);
2661 if (pr_immediate_type == type_string)
2664 strcpy(tmp, pr_immediate_string);
2669 if (pr_token_type == tt_immediate && pr_token_type == tt_immediate)
2670 strcat(tmp, pr_immediate_string);
2675 cn = QCC_MakeStringConst(tmp);
2679 // check for a constant with the same value
2680 for (cn=pr.def_head.next ; cn ; cn=cn->next) //FIXME - hashtable.
2682 if (!cn->initialized)
2686 if (cn->type != pr_immediate_type)
2688 if (pr_immediate_type == type_string)
2690 if (!STRCMP(G_STRING(cn->ofs), pr_immediate_string) )
2696 else if (pr_immediate_type == type_float)
2698 if ( G_FLOAT(cn->ofs) == pr_immediate._float )
2704 else if (pr_immediate_type == type_integer)
2706 if ( G_INT(cn->ofs) == pr_immediate._int )
2712 else if (pr_immediate_type == type_vector)
2714 if ( ( G_FLOAT(cn->ofs) == pr_immediate.vector[0] )
2715 && ( G_FLOAT(cn->ofs+1) == pr_immediate.vector[1] )
2716 && ( G_FLOAT(cn->ofs+2) == pr_immediate.vector[2] ) )
2723 QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "weird immediate type");
2726 // allocate a new one
2727 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
2729 pr.def_tail->next = cn;
2732 cn->type = pr_immediate_type;
2733 cn->name = "IMMEDIATE";
2734 cn->constant = true;
2735 cn->initialized = 1;
2736 cn->scope = NULL; // always share immediates
2738 // copy the immediate to the global area
2739 cn->ofs = QCC_GetFreeOffsetSpace(type_size[pr_immediate_type->type]);
2741 if (pr_immediate_type == type_string)
2742 pr_immediate.string = QCC_CopyString (pr_immediate_string);
2744 memcpy (qcc_pr_globals + cn->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
2752 void QCC_PrecacheSound (QCC_def_t *e, int ch)
2757 if (e->type->type != ev_string)
2760 if (!e->ofs || e->temp || !e->constant)
2762 n = G_STRING(e->ofs);
2765 for (i=0 ; i<numsounds ; i++)
2766 if (!STRCMP(n, precache_sounds[i]))
2768 if (numsounds == MAX_SOUNDS)
2770 // QCC_Error ("PrecacheSound: numsounds == MAX_SOUNDS");
2771 strcpy (precache_sounds[i], n);
2772 if (ch >= '1' && ch <= '9')
2773 precache_sounds_block[i] = ch - '0';
2775 precache_sounds_block[i] = 1;
2779 void QCC_PrecacheModel (QCC_def_t *e, int ch)
2784 if (e->type->type != ev_string)
2787 if (!e->ofs || e->temp || !e->constant)
2789 n = G_STRING(e->ofs);
2792 for (i=0 ; i<nummodels ; i++)
2793 if (!STRCMP(n, precache_models[i]))
2795 if (!precache_models_block[i])
2797 if (ch >= '1' && ch <= '9')
2798 precache_models_block[i] = ch - '0';
2800 precache_models_block[i] = 1;
2804 if (nummodels == MAX_MODELS)
2806 // QCC_Error ("PrecacheModels: nummodels == MAX_MODELS");
2807 strcpy (precache_models[i], n);
2808 if (ch >= '1' && ch <= '9')
2809 precache_models_block[i] = ch - '0';
2811 precache_models_block[i] = 1;
2815 void QCC_SetModel (QCC_def_t *e)
2820 if (e->type->type != ev_string)
2823 if (!e->ofs || e->temp || !e->constant)
2825 n = G_STRING(e->ofs);
2828 for (i=0 ; i<nummodels ; i++)
2829 if (!STRCMP(n, precache_models[i]))
2831 precache_models_used[i]++;
2834 if (nummodels == MAX_MODELS)
2836 strcpy (precache_models[i], n);
2837 precache_models_block[i] = 0;
2838 precache_models_used[i]=1;
2842 void QCC_PrecacheTexture (QCC_def_t *e, int ch)
2847 if (e->type->type != ev_string)
2850 if (!e->ofs || e->temp || !e->constant)
2852 n = G_STRING(e->ofs);
2855 for (i=0 ; i<numtextures ; i++)
2856 if (!STRCMP(n, precache_textures[i]))
2858 if (nummodels == MAX_MODELS)
2860 // QCC_Error ("PrecacheTextures: numtextures == MAX_TEXTURES");
2861 strcpy (precache_textures[i], n);
2862 if (ch >= '1' && ch <= '9')
2863 precache_textures_block[i] = ch - '0';
2865 precache_textures_block[i] = 1;
2869 void QCC_PrecacheFile (QCC_def_t *e, int ch)
2874 if (e->type->type != ev_string)
2877 if (!e->ofs || e->temp || !e->constant)
2879 n = G_STRING(e->ofs);
2882 for (i=0 ; i<numfiles ; i++)
2883 if (!STRCMP(n, precache_files[i]))
2885 if (numfiles == MAX_FILES)
2887 // QCC_Error ("PrecacheFile: numfiles == MAX_FILES");
2888 strcpy (precache_files[i], n);
2889 if (ch >= '1' && ch <= '9')
2890 precache_files_block[i] = ch - '0';
2892 precache_files_block[i] = 1;
2896 void QCC_PrecacheFileOptimised (char *n, int ch)
2900 for (i=0 ; i<numfiles ; i++)
2901 if (!STRCMP(n, precache_files[i]))
2903 if (numfiles == MAX_FILES)
2905 // QCC_Error ("PrecacheFile: numfiles == MAX_FILES");
2906 strcpy (precache_files[i], n);
2907 if (ch >= '1' && ch <= '9')
2908 precache_files_block[i] = ch - '0';
2910 precache_files_block[i] = 1;
2914 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.
2916 QCC_def_t *d, *oldret, *oself;
2919 int extraparms=false;
2921 int laststatement = numstatements;
2924 QCC_dstatement_t *st;
2927 func->timescalled++;
2929 if (QCC_OPCodeValid(&pr_opcodes[OP_CALL1H]))
2930 callconvention = OP_CALL1H; //FTE extended
2932 callconvention = OP_CALL1; //standard
2936 if (t->type == ev_variant)
2938 t->aux_type = type_variant;
2941 if (t->type != ev_function && t->type != ev_variant)
2943 QCC_PR_ParseErrorPrintDef (ERR_NOTAFUNCTION, func, "not a function");
2946 // copy the arguments to the global parameter variables
2947 if (t->type == ev_variant)
2952 else if (t->num_parms < 0)
2955 np = (t->num_parms * -1) - 1;
2960 if (strchr(func->name, ':') && laststatement && statements[laststatement-1].op == OP_LOAD_FNC && statements[laststatement-1].c == func->ofs)
2961 { //we're entering OO code with a different self.
2962 //eg: other.touch(self)
2964 //FIXME: problems could occur with hexen2 calling conventions when parm0/1 is 'self'
2965 //thiscall. copy the right ent into 'self' (if it's not the same offset)
2966 d = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
2967 if (statements[laststatement-1].a != d->ofs)
2969 oself = QCC_GetTemp(type_entity);
2971 QCC_PR_SimpleStatement(OP_STORE_ENT, d->ofs, oself->ofs, 0, false);
2973 QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement-1].a, d->ofs, 0, false);
2975 //if the args refered to self, update them to refer to oself instead
2976 //(as self is now set to 'other')
2977 for (i = 0; i < argcount; i++)
2979 if (arglist[i]->ofs == d->ofs)
2987 //it was self.func() anyway
2993 { //regular func call
2998 // write the arguments (except for first two if hexenc)
2999 for (i = 0; i < argcount; i++)
3002 d = extra_parms[i - MAX_PARMS];
3006 if (callconvention == OP_CALL1H)
3009 //first two args are passed in the call opcode, so don't need to be copied
3010 arglist[i]->references++;
3012 /*don't free these temps yet, free them after the return check*/
3016 if (arglist[i]->type->size == 3 || !opt_nonvec_parms)
3017 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], arglist[i], d, (QCC_dstatement_t **)0xffffffff));
3020 d->type = arglist[i]->type;
3021 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], arglist[i], d, (QCC_dstatement_t **)0xffffffff));
3022 optres_nonvec_parms++;
3026 //if the return value was in use, save it off now, so that it doesn't get clobbered
3027 if (def_ret.temp->used)
3028 oldret = QCC_GetTemp(def_ret.type);
3032 /*can free temps used for arguments now*/
3033 if (callconvention == OP_CALL1H)
3035 for (i = 0; i < argcount && i < 2; i++)
3036 QCC_FreeTemp(arglist[i]);
3039 if (oldret && !def_ret.temp->used)
3041 QCC_FreeTemp(oldret);
3044 else if (def_ret.temp->used)
3046 if (def_ret.type->size == 3)
3047 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, (void*)0xffffffff));
3049 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, (void*)0xffffffff));
3050 QCC_UnFreeTemp(oldret);
3051 QCC_UnFreeTemp(&def_ret);
3052 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3057 //we dont need to lock the local containing the function index because its thrown away after the call anyway
3058 //(if a function is called in the argument list then it'll be locked as part of that call)
3060 QCC_LockActiveTemps(); //any temps before are likly to be used with the return value.
3061 QCC_UnFreeTemp(func);
3064 if (argcount>MAX_PARMS)
3065 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+MAX_PARMS], func, 0, (QCC_dstatement_t **)&st));
3067 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[callconvention-1+argcount], func, 0, (QCC_dstatement_t **)&st));
3069 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CALL0], func, 0, (QCC_dstatement_t **)&st));
3071 if (callconvention == OP_CALL1H)
3075 st->b = arglist[0]->ofs;
3076 // QCC_FreeTemp(param[0]);
3079 st->c = arglist[1]->ofs;
3080 // QCC_FreeTemp(param[1]);
3085 //restore the class owner
3087 QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false);
3091 if (oldret->temp && !oldret->temp->used)
3092 QCC_PR_ParseWarning(0, "Ret was freed\n");
3094 //if we preserved the ofs_ret global, restore it here
3095 if (t->type == ev_variant)
3097 d = QCC_GetTemp(type_variant);
3098 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff));
3102 d = QCC_GetTemp(t->aux_type);
3103 if (t->aux_type->size == 3)
3104 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, (void*)0xffffffff));
3106 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff));
3108 if (def_ret.type->size == 3)
3109 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, (void*)0xffffffff));
3111 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, (void*)0xffffffff));
3112 QCC_FreeTemp(oldret);
3113 QCC_UnFreeTemp(&def_ret);
3119 if (t->type == ev_variant)
3120 def_ret.type = type_variant;
3122 def_ret.type = t->aux_type;
3123 if (def_ret.temp->used)
3124 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3125 def_ret.temp->used = true;
3132 PR_ParseFunctionCall
3135 QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could have no name set if it's a field call.
3137 QCC_def_t *e, *d, *old = {0}, *oself, *out; // warning:
\91old
\92 may be used uninitialized in this function
3140 int extraparms=false;
3145 QCC_def_t *param[MAX_PARMS+MAX_EXTRA_PARMS];
3147 func->timescalled++;
3149 if (QCC_OPCodeValid(&pr_opcodes[OP_CALL1H]))
3150 callconvention = OP_CALL1H; //FTE extended
3152 callconvention = OP_CALL1; //standard
3156 if (t->type == ev_variant)
3158 t->aux_type = type_variant;
3161 if (t->type != ev_function && t->type != ev_variant)
3163 QCC_PR_ParseErrorPrintDef (ERR_NOTAFUNCTION, func, "not a function");
3166 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)
3168 if (!strcmp(func->name, "sizeof"))
3171 if (!func->initialized)
3172 func->initialized = 3;
3174 t = QCC_PR_ParseType(false, false);
3176 return QCC_MakeIntConst(t->size * 4);
3178 if (!strcmp(func->name, "_"))
3180 if (!func->initialized)
3181 func->initialized = 3;
3183 if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string)
3185 d = QCC_MakeTranslateStringConst(pr_immediate_string);
3189 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "_() intrinsic accepts only a string immediate", 1);
3193 if (!strcmp(func->name, "random"))
3196 if (!func->initialized)
3197 func->initialized = 3;
3199 if (!QCC_PR_CheckToken(")"))
3201 e = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3202 if (e->type->type != ev_float)
3203 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 1);
3204 if (!QCC_PR_CheckToken(")"))
3207 d = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3208 if (d->type->type != ev_float)
3209 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 2);
3222 if (QCC_OPCodeValid(&pr_opcodes[OP_RAND0]))
3224 if(qcc_targetformat != QCF_HEXEN2)
3225 out = QCC_GetTemp(type_float);
3226 else if (out->temp->used)
3228 old = QCC_GetTemp(out->type);
3229 if (def_ret.type->size == 3)
3230 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL));
3232 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL));
3233 QCC_UnFreeTemp(old);
3234 QCC_UnFreeTemp(out);
3235 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3243 QCC_PR_SimpleStatement(OP_RAND2, e->ofs, d->ofs, out->ofs, false);
3245 QCC_PR_SimpleStatement(OP_RAND1, e->ofs, 0, out->ofs, false);
3248 QCC_PR_SimpleStatement(OP_RAND0, 0, 0, out->ofs, false);
3252 if (out->temp->used)
3254 old = QCC_GetTemp(out->type);
3255 if (def_ret.type->size == 3)
3256 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL));
3258 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL));
3259 QCC_UnFreeTemp(old);
3260 QCC_UnFreeTemp(out);
3261 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3270 QCC_dstatement_t *st;
3272 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3274 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3276 t = QCC_PR_Statement(&pr_opcodes[OP_GT_F], d, e, NULL);
3277 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], t, 0, &st));
3280 t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], d, e, NULL);
3281 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3283 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3285 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_GOTO], 0, 0, &st));
3289 t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], e, d, NULL);
3290 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3292 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs, OFS_RETURN, false);
3296 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3297 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3301 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3317 d = QCC_GetTemp(type_float);
3318 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL));
3319 if (def_ret.type->size == 3)
3320 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, old, &def_ret, NULL));
3322 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL));
3325 QCC_UnFreeTemp(&def_ret);
3330 if (out == &def_ret)
3332 if (out->temp->used)
3333 QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
3334 out->temp->used = true;
3335 out->type = type_float;
3340 if (!strcmp(func->name, "randomv"))
3343 if (!func->initialized)
3344 func->initialized = 3;
3346 if (!QCC_PR_CheckToken(")"))
3348 e = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3349 if (e->type->type != ev_vector)
3350 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 1);
3351 if (!QCC_PR_CheckToken(")"))
3354 d = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3355 if (d->type->type != ev_vector)
3356 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i", 2);
3368 if (QCC_OPCodeValid(&pr_opcodes[OP_RANDV0]))
3370 if(def_ret.temp->used)
3371 out = QCC_GetTemp(type_vector);
3378 QCC_PR_SimpleStatement(OP_RANDV2, e->ofs, d->ofs, out->ofs, false);
3380 QCC_PR_SimpleStatement(OP_RANDV1, e->ofs, 0, out->ofs, false);
3383 QCC_PR_SimpleStatement(OP_RANDV0, 0, 0, out->ofs, false);
3387 if (def_ret.temp->used)
3389 old = QCC_GetTemp(def_ret.type);
3390 if (def_ret.type->size == 3)
3391 QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL);
3393 QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL);
3394 QCC_UnFreeTemp(old);
3395 QCC_UnFreeTemp(&def_ret);
3396 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3406 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3408 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3410 t = QCC_GetTemp(type_float);
3411 QCC_PR_SimpleStatement(OP_GT_F, d->ofs+2, e->ofs+2, t->ofs, false);
3412 QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false);
3414 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+2, e->ofs+2, t->ofs, false);
3415 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+2, false);
3417 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs+2, OFS_RETURN+2, false);
3419 QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
3422 t = QCC_GetTemp(type_float);
3423 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+2, e->ofs+2, t->ofs, false);
3424 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+2, false);
3426 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs+2, OFS_RETURN+2, false);
3430 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3432 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3434 t = QCC_GetTemp(type_float);
3435 QCC_PR_SimpleStatement(OP_GT_F, d->ofs+1, e->ofs+1, t->ofs, false);
3436 QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false);
3438 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+1, e->ofs+1, t->ofs, false);
3439 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+1, false);
3441 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs+1, OFS_RETURN+1, false);
3443 QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
3446 t = QCC_GetTemp(type_float);
3447 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+1, e->ofs+1, t->ofs, false);
3448 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+1, false);
3450 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs+1, OFS_RETURN+1, false);
3453 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3455 if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
3457 t = QCC_GetTemp(type_float);
3458 QCC_PR_SimpleStatement(OP_GT_F, d->ofs, e->ofs, t->ofs, false);
3459 QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false);
3461 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs, e->ofs, t->ofs, false);
3462 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3464 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3466 QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
3469 t = QCC_GetTemp(type_float);
3470 QCC_PR_SimpleStatement(OP_SUB_F, d->ofs, e->ofs, t->ofs, false);
3471 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
3473 QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs, OFS_RETURN, false);
3477 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3478 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN+2, false);
3479 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3480 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN+1, false);
3481 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3482 QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, e->ofs, OFS_RETURN, false);
3487 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3488 QCC_PR_SimpleStatement(OP_STORE_F, OFS_RETURN, OFS_RETURN+2, 0, false);
3489 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3490 QCC_PR_SimpleStatement(OP_STORE_F, OFS_RETURN, OFS_RETURN+1, 0, false);
3491 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3509 d = QCC_GetTemp(type_vector);
3510 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL));
3511 if (def_ret.type->size == 3)
3513 QCC_PR_Statement(pr_opcodes+OP_STORE_V, old, &def_ret, NULL);
3517 QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL);
3521 QCC_UnFreeTemp(&def_ret);
3526 if (def_ret.temp->used)
3527 QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
3528 def_ret.temp->used = true;
3529 def_ret.type = type_vector;
3532 else if (!strcmp(func->name, "spawn"))
3534 QCC_type_t *rettype;
3535 if (QCC_PR_CheckToken(")"))
3537 rettype = type_entity;
3541 rettype = QCC_TypeForName(QCC_PR_ParseName());
3542 if (!rettype || rettype->type != ev_entity)
3543 QCC_PR_ParseError(ERR_NOTANAME, "Spawn operator with undefined class");
3549 if (def_ret.temp->used)
3551 old = QCC_GetTemp(def_ret.type);
3552 if (def_ret.type->size == 3)
3553 QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL);
3555 QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL);
3556 QCC_UnFreeTemp(old);
3557 QCC_UnFreeTemp(&def_ret);
3558 QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
3563 if (def_ret.temp->used)
3564 QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid");
3565 def_ret.temp->used = true;
3568 if (rettype != type_entity)
3571 sprintf(genfunc, "Class*%s", rettype->name);
3572 func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 0, false);
3575 QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
3579 d = QCC_GetTemp(rettype);
3580 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_ENT, &def_ret, d, NULL));
3581 if (def_ret.type->size == 3)
3582 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, old, &def_ret, NULL));
3584 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL));
3587 QCC_UnFreeTemp(&def_ret);
3592 def_ret.type = rettype;
3595 else if (!strcmp(func->name, "entnum") && !QCC_PR_CheckToken(")"))
3597 //t = (a/%1) / (nextent(world)/%1)
3598 //a/%1 does a (int)entity to float conversion type thing
3599 if (!func->initialized)
3600 func->initialized = 3;
3603 e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3605 e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff);
3607 d = QCC_PR_GetDef(NULL, "nextent", NULL, false, 0, false);
3609 QCC_PR_ParseError(0, "the nextent builtin is not defined");
3610 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], e, &def_parms[0], (QCC_dstatement_t **)0xffffffff));
3611 d = QCC_PR_Statement(&pr_opcodes[OP_CALL0], d, NULL, NULL);
3612 d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff);
3614 e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, d, (QCC_dstatement_t **)0xffffffff);
3618 } //so it's not an intrinsic.
3620 if (opt_precache_file) //should we strip out all precache_file calls?
3622 if (!strncmp(func->name,"precache_file", 13))
3624 if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string && pr_scope && !strcmp(pr_scope->name, "main"))
3626 optres_precache_file += strlen(pr_immediate_string);
3629 QCC_PrecacheFileOptimised (pr_immediate_string, func->name[13]);
3630 def_ret.type = type_void;
3636 // copy the arguments to the global parameter variables
3638 if (t->type == ev_variant)
3643 else if (t->num_parms < 0)
3646 np = (t->num_parms * -1) - 1;
3651 //any temps referenced to build the parameters don't need to be locked.
3652 if (!QCC_PR_CheckToken(")"))
3657 if (extraparms && arg >= MAX_PARMS)
3658 QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS);
3659 else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS)
3660 QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS);
3661 if (!extraparms && arg >= t->num_parms && !p)
3663 QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters");
3664 QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func);
3668 //with vectorcalls, we store the vector into the args as individual floats
3669 //this allows better reuse of vector constants.
3670 //copy it into the offset now, because we can.
3671 if (opt_vectorcalls && pr_token_type == tt_immediate && pr_immediate_type == type_vector && arg < MAX_PARMS && !def_parms[arg].temp->used)
3673 e = &def_parms[arg];
3675 e->ofs = OFS_PARM0+0;
3676 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff));
3677 e->ofs = OFS_PARM0+1;
3678 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff));
3679 e->ofs = OFS_PARM0+2;
3680 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff));
3682 e->type = type_vector;
3687 e = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
3689 if (arg == 0 && func->name)
3691 // save information for model and sound caching
3692 if (!strncmp(func->name,"precache_", 9))
3694 if (!strncmp(func->name+9,"sound", 5))
3695 QCC_PrecacheSound (e, func->name[14]);
3696 else if (!strncmp(func->name+9,"model", 5))
3697 QCC_PrecacheModel (e, func->name[14]);
3698 else if (!strncmp(func->name+9,"texture", 7))
3699 QCC_PrecacheTexture (e, func->name[16]);
3700 else if (!strncmp(func->name+9,"file", 4))
3701 QCC_PrecacheFile (e, func->name[13]);
3707 if (!extra_parms[arg - MAX_PARMS])
3709 d = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t));
3710 d->name = "extra parm";
3711 d->ofs = QCC_GetFreeOffsetSpace (3);
3712 extra_parms[arg - MAX_PARMS] = d;
3714 d = extra_parms[arg - MAX_PARMS];
3717 d = &def_parms[arg];
3719 if (pr_classtype && e->type->type == ev_field && p->type != ev_field)
3721 oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false);
3722 switch(e->type->aux_type->type)
3725 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_S, oself, e, NULL);
3728 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_I, oself, e, NULL);
3731 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_F, oself, e, NULL);
3734 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_FNC, oself, e, NULL);
3737 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_V, oself, e, NULL);
3740 e = QCC_PR_Statement(pr_opcodes+OP_LOAD_ENT, oself, e, NULL);
3743 QCC_Error(ERR_INTERNAL, "Bad member type. Try forced expansion");
3749 if (typecmp(e->type, p))
3750 /*if (e->type->type != ev_integer && p->type != ev_function)
3751 if (e->type->type != ev_function && p->type != ev_integer)
3752 if ( e->type->type != p->type )*/
3754 if (p->type == ev_integer && e->type->type == ev_float) //convert float -> int... is this a constant?
3755 e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL);
3756 else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant?
3757 e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL);
3758 else if ((p->type == ev_function && p->type == ev_string) && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
3759 { //you're allowed to use int 0 to pass a null function pointer
3760 //this is basically because __NULL__ is defined as ~0 (int 0)
3762 else if (p->type != ev_variant && e->type->type != ev_variant) //can cast to variant whatever happens
3764 if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function))
3766 QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
3767 QCC_PR_ParsePrintDef(WARN_LAXCAST, func);
3770 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
3778 // a vector copy will copy everything
3780 d->type = type_void;
3782 if (arg == 1 && !STRCMP(func->name, "setmodel"))
3788 /* if (e->type->size>1)
3789 QCC_PR_Statement (&pr_opcodes[OP_STORE_V], e, d, (QCC_dstatement_t **)0xffffffff);
3791 QCC_PR_Statement (&pr_opcodes[OP_STORE_F], e, d, (QCC_dstatement_t **)0xffffffff);
3794 } while (QCC_PR_CheckToken (","));
3796 if (t->num_parms != -1 && arg < np)
3797 QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "too few parameters on call to %s", func->name);
3798 QCC_PR_Expect (")");
3802 QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "%s: Too few parameters", func->name);
3803 QCC_PR_ParsePrintDef (WARN_TOOFEWPARAMS, func);
3806 return QCC_PR_GenerateFunctionCall(func, param, arg);
3812 QCC_def_t *QCC_MakeIntConst(int value)
3816 // check for a constant with the same value
3817 for (cn=pr.def_head.next ; cn ; cn=cn->next)
3820 if (!cn->initialized)
3825 if (cn->type != type_integer)
3829 if ( G_INT(cn->ofs) == value )
3835 // allocate a new one
3836 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3838 pr.def_tail->next = cn;
3841 cn->type = type_integer;
3842 cn->name = "IMMEDIATE";
3843 cn->constant = true;
3844 cn->initialized = 1;
3845 cn->scope = NULL; // always share immediates
3852 // copy the immediate to the global area
3853 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
3855 G_INT(cn->ofs) = value;
3862 QCC_def_t *QCC_MakeVectorConst(float a, float b, float c)
3866 // check for a constant with the same value
3867 for (cn=pr.def_head.next ; cn ; cn=cn->next)
3870 if (!cn->initialized)
3875 if (cn->type != type_vector)
3879 if ( G_FLOAT(cn->ofs+0) == a &&
3880 G_FLOAT(cn->ofs+1) == b &&
3881 G_FLOAT(cn->ofs+2) == c)
3887 // allocate a new one
3888 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3890 pr.def_tail->next = cn;
3893 cn->type = type_vector;
3894 cn->name = "IMMEDIATE";
3895 cn->constant = true;
3896 cn->initialized = 1;
3897 cn->scope = NULL; // always share immediates
3900 // copy the immediate to the global area
3901 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_vector->type]);
3903 G_FLOAT(cn->ofs+0) = a;
3904 G_FLOAT(cn->ofs+1) = b;
3905 G_FLOAT(cn->ofs+2) = c;
3910 extern hashtable_t floatconstdefstable;
3911 QCC_def_t *QCC_MakeFloatConst(float value)
3922 cn = Hash_GetKey(&floatconstdefstable, fi.i);
3926 // allocate a new one
3927 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3929 pr.def_tail->next = cn;
3932 cn->s_file = s_file;
3933 cn->s_line = pr_source_line;
3934 cn->type = type_float;
3935 cn->name = "IMMEDIATE";
3936 cn->constant = true;
3937 cn->initialized = 1;
3938 cn->scope = NULL; // always share immediates
3941 // copy the immediate to the global area
3942 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
3944 Hash_AddKey(&floatconstdefstable, fi.i, cn, qccHunkAlloc(sizeof(bucket_t)));
3946 G_FLOAT(cn->ofs) = value;
3952 extern hashtable_t stringconstdefstable, stringconstdefstable_trans;
3953 int dotranslate_count;
3954 static QCC_def_t *QCC_MakeStringConstInternal(char *value, pbool translate)
3959 cn = pHash_Get(translate?&stringconstdefstable_trans:&stringconstdefstable, value);
3963 // allocate a new one
3967 sprintf(buf, "dotranslate_%i", ++dotranslate_count);
3968 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t) + strlen(buf)+1);
3969 cn->name = (char*)(cn+1);
3970 strcpy(cn->name, buf);
3974 cn = (void *)qccHunkAlloc (sizeof(QCC_def_t));
3975 cn->name = "IMMEDIATE";
3978 pr.def_tail->next = cn;
3981 cn->type = type_string;
3982 cn->constant = true;
3983 cn->initialized = 1;
3984 cn->scope = NULL; // always share immediates
3987 // copy the immediate to the global area
3988 cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
3990 string = QCC_CopyString (value);
3992 pHash_Add(translate?&stringconstdefstable_trans:&stringconstdefstable, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
3994 G_INT(cn->ofs) = string;
3999 QCC_def_t *QCC_MakeStringConst(char *value)
4001 return QCC_MakeStringConstInternal(value, false);
4003 QCC_def_t *QCC_MakeTranslateStringConst(char *value)
4005 return QCC_MakeStringConstInternal(value, true);
4008 QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type)
4010 QCC_type_t *newtype;
4011 newtype = QCC_PR_NewType("ptr", ev_pointer, false);
4012 newtype->aux_type = type;
4016 int basictypefield[ev_union+1];
4017 char *basictypenames[] = {
4031 QCC_def_t *QCC_MemberInParentClass(char *name, QCC_type_t *clas)
4032 { //if a member exists, return the member field (rather than mapped-to field)
4036 char membername[2048];
4040 def = QCC_PR_GetDef(NULL, name, NULL, 0, 0, false);
4041 if (def && def->type->type == ev_field) //the member existed as a normal entity field.
4046 np = clas->num_parms;
4047 for (p = 0, mt = clas->param; p < np; p++, mt = mt->next)
4049 if (strcmp(mt->name, name))
4052 //the parent has it.
4054 sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, mt->name);
4055 def = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false);
4059 return QCC_MemberInParentClass(name, clas->parentclass);
4062 //create fields for the types, instanciate the members to the fields.
4063 //we retouch the parents each time to guarentee polymorphism works.
4064 //FIXME: virtual methods will not work properly. Need to trace down to see if a parent already defined it
4065 void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas)
4067 //we created fields for each class when we defined the actual classes.
4068 //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..
4070 //basictypefield is cleared before we do this
4071 //we emit the parent's fields first (every time), thus ensuring that we don't reuse parent fields on a child class.
4073 char membername[2048];
4076 QCC_type_t *mt, *ft;
4078 if (clas->parentclass != type_entity) //parents MUST have all their fields set or inheritance would go crazy.
4079 QCC_PR_EmitFieldsForMembers(clas->parentclass);
4081 np = clas->num_parms;
4083 for (p = 0; p < np; p++, mt = mt->next)
4085 sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, mt->name);
4086 m = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false);
4088 f = QCC_MemberInParentClass(mt->name, clas->parentclass);
4092 QCC_Error(ERR_INTERNAL, "FTEQCC does not support overloaded arrays of members");
4094 for (o = 0; o < m->type->size; o++)
4095 ((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs];
4099 for (a = 0; a < (m->arraysize?m->arraysize:1); a++)
4101 /*if it was already set, don't go recursive and generate 500 fields for a one-member class that was intheritted from 500 times*/
4102 if (((int *)qcc_pr_globals)[o+a*mt->size+m->ofs])
4105 //we need the type in here so saved games can still work without saving ints as floats. (would be evil)
4106 ft = QCC_PR_NewType(basictypenames[mt->type], ev_field, false);
4107 ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type, false);
4108 ft->aux_type->aux_type = type_void;
4109 ft->size = ft->aux_type->size;
4110 ft = QCC_PR_FindType(ft);
4111 sprintf(membername, "__f_%s_%i", ft->name, ++basictypefield[mt->type]);
4112 f = QCC_PR_GetDef(ft, membername, NULL, true, 0, true);
4114 for (o = 0; o < m->type->size; o++)
4115 ((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs];
4122 void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_def_t *ed, QCC_def_t **constructor)
4123 { //go through clas, do the virtual thing only if the child class does not override.
4125 char membername[2048];
4130 QCC_def_t *point, *member;
4133 if (clas->parentclass)
4134 QCC_PR_EmitClassFunctionTable(clas->parentclass, childclas, ed, constructor);
4137 for (p = 0; p < clas->num_parms; p++, type = type->next)
4139 for (oc = childclas; oc != clas; oc = oc->parentclass)
4141 sprintf(membername, "%s::"MEMBERFIELDNAME, oc->name, type->name);
4142 if (QCC_PR_GetDef(NULL, membername, NULL, false, 0, false))
4143 break; //a child class overrides.
4148 if (type->type == ev_function) //FIXME: inheritance will not install all the member functions.
4150 sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, type->name);
4151 member = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false);
4154 QCC_PR_Warning(0, NULL, 0, "Member function %s was not defined", membername);
4157 if (!strcmp(type->name, clas->name))
4159 *constructor = member;
4161 point = QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], ed, member, NULL);
4162 sprintf(membername, "%s::%s", clas->name, type->name);
4163 virt = QCC_PR_GetDef(type, membername, NULL, false, 0, false);
4164 QCC_PR_Statement(&pr_opcodes[OP_STOREP_FNC], virt, point, NULL);
4169 //take all functions in the type, and parent types, and make sure the links all work properly.
4170 void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname)
4172 QCC_type_t *basetype;
4174 QCC_dfunction_t *df;
4177 QCC_def_t *ed, *oself, *self;
4178 QCC_def_t *constructor = NULL;
4182 basetype = QCC_TypeForName(tname);
4184 QCC_PR_ParseError(ERR_INTERNAL, "Type %s was not defined...", tname);
4186 if (numfunctions >= MAX_FUNCTIONS)
4187 QCC_Error(ERR_INTERNAL, "Too many function defs");
4190 memset(basictypefield, 0, sizeof(basictypefield));
4191 QCC_PR_EmitFieldsForMembers(basetype);
4198 df = &functions[numfunctions];
4203 df->first_statement = numstatements;
4204 df->parm_size[0] = 1;
4206 df->parm_start = numpr_globals;
4208 G_FUNCTION(scope->ofs) = df - functions;
4211 ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 0, false);
4213 virt = QCC_PR_GetDef(type_function, "spawn", NULL, false, 0, false);
4215 QCC_Error(ERR_INTERNAL, "spawn function was not defined\n");
4216 QCC_PR_SimpleStatement(OP_CALL0, virt->ofs, 0, 0, false); //calling convention doesn't come into it.
4218 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], &def_ret, ed, NULL));
4220 ed->references = 1; //there may be no functions.
4223 QCC_PR_EmitClassFunctionTable(basetype, basetype, ed, &constructor);
4227 self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false);
4228 oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 0, false);
4229 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], self, oself, NULL));
4230 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], ed, self, NULL)); //return to our old self. boom boom.
4231 QCC_PR_SimpleStatement(OP_CALL0, constructor->ofs, 0, 0, false);
4232 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], oself, self, NULL));
4235 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_RETURN], ed, NULL, NULL)); //apparently we do actually have to return something. *sigh*...
4236 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_DONE], NULL, NULL, NULL));
4240 QCC_WriteAsmFunction(scope, df->first_statement, df->parm_start);
4241 pr.localvars = NULL;
4244 locals_end = numpr_globals + basetype->size;
4245 df->locals = locals_end - df->parm_start;
4248 QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign)
4253 QCC_dstatement_t *st;
4262 allowarray = t->arraysize>0;
4265 allowarray = d->arraysize ||
4266 (d->type->type == ev_pointer) ||
4267 (d->type->type == ev_string) ||
4268 (d->type->type == ev_vector);
4271 if (allowarray && QCC_PR_CheckToken("["))
4273 tmp = QCC_PR_Expression (TOP_PRIORITY, 0);
4276 /*if its a pointer that got dereferenced, follow the type*/
4277 if (!idx && t->type == ev_pointer && !d->arraysize)
4280 if (!idx && d->type->type == ev_pointer)
4282 /*no bounds checks on pointer dereferences*/
4284 else if (!idx && d->type->type == ev_string && !d->arraysize)
4286 /*automatic runtime bounds checks on strings, I'm not going to check this too much...*/
4288 else if (!idx && d->type->type == ev_vector && !d->arraysize)
4293 if (tmp->type->type == ev_integer)
4294 i = G_INT(tmp->ofs);
4295 else if (tmp->type->type == ev_float)
4296 i = G_FLOAT(tmp->ofs);
4297 if (i < 0 || i >= 3)
4298 QCC_PR_ParseErrorPrintDef(0, d, "(vector) array index out of bounds");
4300 else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
4302 tmp = QCC_SupplyConversion(tmp, ev_integer, true);
4303 QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, 3, 0, false);
4307 else if (!((!idx)?d->arraysize:t->arraysize))
4309 QCC_PR_ParseErrorPrintDef(0, d, "array index on non-array");
4311 else if (tmp->constant)
4314 if (tmp->type->type == ev_integer)
4315 i = G_INT(tmp->ofs);
4316 else if (tmp->type->type == ev_float)
4317 i = G_FLOAT(tmp->ofs);
4318 if (i < 0 || i >= ((!idx)?d->arraysize:t->arraysize))
4319 QCC_PR_ParseErrorPrintDef(0, d, "(constant) array index out of bounds");
4323 if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
4325 tmp = QCC_SupplyConversion(tmp, ev_integer, true);
4326 QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, ((!idx)?d->arraysize:t->arraysize), 0, false);
4329 if (t->size != 1 && (idx || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))) /*don't multiply by type size if the instruction/emulation will do that instead*/
4331 if (tmp->type->type == ev_float)
4332 tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], tmp, QCC_MakeFloatConst(t->size), NULL);
4334 tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], tmp, QCC_MakeIntConst(t->size), NULL);
4337 /*calc the new index*/
4339 idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, true), NULL);
4343 else if ((t->type == ev_pointer || t->type == ev_struct || t->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
4345 if (!idx && t->type == ev_pointer && !d->arraysize)
4348 for (t = t->param; t; t = t->next)
4350 if (QCC_PR_CheckName(t->name))
4357 QCC_PR_ParseError(0, "%s is not a member", pr_token);
4359 tmp = QCC_MakeIntConst(t->ofs);
4361 idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL);
4371 if (d->type->type == ev_pointer)
4376 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4379 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4382 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4385 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4388 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4391 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4394 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4397 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4401 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4405 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4409 else if (d->type->type == ev_string && d->arraysize == 0)
4411 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_SupplyConversion(idx, ev_float, true), NULL);
4413 else if (d->type->type == ev_vector && d->arraysize == 0)
4415 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4416 d->type = type_float;
4418 else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
4420 /*don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign*/
4421 /*source type is a struct, or its an array, or something that can otherwise be directly accessed*/
4425 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4428 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4431 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4434 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4437 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4440 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4443 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4446 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4451 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_STRUCT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL);
4454 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4458 else if (idx->constant)
4461 idx = QCC_SupplyConversion(idx, ev_integer, true);
4462 cidx = G_INT(idx->ofs);
4465 tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4466 memcpy (tmp, d, sizeof(QCC_def_t));
4468 tmp->ofs = d->ofs + (cidx * type_size[d->type->type]);
4471 //d can be assigned to freely
4473 else if (allowarrayassign && QCC_PR_CheckToken("="))
4475 /*if its assigned to, generate a functioncall to do the store*/
4476 QCC_def_t *args[2], *funcretr, *rhs;
4479 funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 0, false);
4481 rhs = QCC_PR_Expression(TOP_PRIORITY, 0);
4482 if (rhs->type->type != d->type->type)
4483 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment");
4485 args[0] = QCC_SupplyConversion(idx, ev_float, true);
4487 qcc_usefulstatement=true;
4488 d = QCC_PR_GenerateFunctionCall(funcretr, args, 2);
4493 else if (QCC_OPCodeValid(&pr_opcodes[OP_FETCH_GBL_F]))
4496 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on non-array");
4499 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on a temp");
4501 /*hexen2 format has opcodes to read arrays (but has no way to write)*/
4505 d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
4509 d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
4513 d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
4517 d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
4521 d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def.
4525 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
4533 /*emulate the array access using a function call to do the read for us*/
4534 QCC_def_t *args[1], *funcretr;
4538 /*make sure the function type that we're calling exists*/
4539 def_parms[0].type = type_float;
4540 funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false);
4542 args[0] = QCC_SupplyConversion(idx, ev_float, true);
4543 d = QCC_PR_GenerateFunctionCall(funcretr, args, 1);
4547 /*parse recursively*/
4548 d = QCC_PR_ParseArrayPointer(d, allowarrayassign);
4558 Returns the global ofs for the current token
4561 QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign)
4563 QCC_def_t *d, *od, *tmp;
4567 char membername[2048];
4569 // if the token is an immediate, allocate a constant for it
4570 if (pr_token_type == tt_immediate)
4571 return QCC_PR_ParseImmediate ();
4573 if (QCC_PR_CheckToken("[")) //reacc support
4574 { //looks like a funky vector. :)
4576 pr_immediate_type = type_vector;
4577 v[0] = pr_immediate._float;
4579 v[1] = pr_immediate._float;
4581 v[2] = pr_immediate._float;
4582 pr_immediate.vector[0] = v[0];
4583 pr_immediate.vector[1] = v[1];
4584 pr_immediate.vector[2] = v[2];
4585 pr_immediate_type = type_vector;
4586 d = QCC_PR_ParseImmediate();
4590 name = QCC_PR_ParseName ();
4592 if (assumeclass && assumeclass->parentclass) // 'testvar' becomes 'self::testvar'
4593 { //try getting a member.
4597 while(type != type_entity && type)
4599 sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name);
4600 d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false);
4604 type = type->parentclass;
4607 d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
4611 // look through the defs
4612 d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
4617 if ( (!strcmp(name, "random" )) ||
4618 (!strcmp(name, "randomv")) ||
4619 (!strcmp(name, "sizeof")) ||
4620 (!strcmp(name, "entnum")) ||
4621 (!strcmp(name, "_"))) //intrinsics, any old function with no args will do.
4623 d = QCC_PR_GetDef (type_function, name, NULL, true, 0, false);
4626 else if (keyword_class && !strcmp(name, "this"))
4629 QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n");
4630 od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false);
4631 d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 0, od->ofs, true, false);
4633 else if (keyword_class && !strcmp(name, "super"))
4636 QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n");
4637 od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false);
4638 d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 0, od->ofs, true, false);
4642 d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 0, false);
4644 QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
4647 QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name);
4652 d = QCC_PR_ParseArrayPointer(d, allowarrayassign);
4655 if (keyword_class && t->type == ev_entity && t->parentclass && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
4658 if (QCC_PR_CheckToken("("))
4660 field = QCC_PR_Expression(TOP_PRIORITY, 0);
4664 field = QCC_PR_ParseValue(d->type, false);
4665 if (field->type->type == ev_field)
4667 if (!field->type->aux_type)
4669 QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type");
4670 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
4674 switch(field->type->aux_type->type)
4677 QCC_PR_ParseError(ERR_INTERNAL, "Bad field type");
4680 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL);
4683 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
4684 tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4685 memset (tmp, 0, sizeof(QCC_def_t));
4686 tmp->type = field->type->aux_type;
4688 tmp->temp = d->temp;
4689 tmp->constant = false;
4690 tmp->name = d->name;
4694 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL);
4697 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL);
4700 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL);
4703 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL);
4704 tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4705 memset (tmp, 0, sizeof(QCC_def_t));
4706 tmp->type = field->type->aux_type;
4708 tmp->temp = d->temp;
4709 tmp->constant = false;
4710 tmp->name = d->name;
4714 d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL);
4720 QCC_PR_IncludeChunk(".", false, NULL);
4732 QCC_def_t *QCC_PR_Term (void)
4736 if (pr_token_type == tt_punct) //a little extra speed...
4738 if (QCC_PR_CheckToken("++"))
4740 qcc_usefulstatement=true;
4743 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
4745 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Hey! That's a temp! ++ operators cannot work on temps!");
4746 switch (e->type->type)
4749 QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false);
4752 QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false);
4755 QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "++ operator on unsupported type");
4760 else if (QCC_PR_CheckToken("--"))
4762 qcc_usefulstatement=true;
4765 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
4767 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Hey! That's a temp! -- operators cannot work on temps!");
4768 switch (e->type->type)
4771 QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false);
4774 QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false);
4777 QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "-- operator on unsupported type");
4783 if (QCC_PR_CheckToken ("!"))
4785 e = QCC_PR_Expression (NOT_PRIORITY, EXPR_DISALLOW_COMMA|EXPR_WARN_ABOVE_1);
4788 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_F], e, 0, NULL);
4789 else if (t == ev_string)
4790 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_S], e, 0, NULL);
4791 else if (t == ev_entity)
4792 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_ENT], e, 0, NULL);
4793 else if (t == ev_vector)
4794 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_V], e, 0, NULL);
4795 else if (t == ev_function)
4796 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0, NULL);
4797 else if (t == ev_integer)
4798 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0, NULL); //functions are integer values too.
4799 else if (t == ev_pointer)
4800 e2 = QCC_PR_Statement (&pr_opcodes[OP_NOT_FNC], e, 0, NULL); //Pointers are too.
4803 e2 = NULL; // shut up compiler warning;
4804 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for !");
4809 else if (QCC_PR_CheckToken ("&"))
4811 int st = numstatements;
4812 e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
4815 if (st != numstatements)
4816 //woo, something like ent.field?
4818 if ((OP_LOAD_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOAD_FNC) || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
4820 statements[numstatements-1].op = OP_ADDRESS;
4821 e->type = QCC_PR_PointerType(e->type);
4824 else if (OP_LOADA_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADA_I)
4826 statements[numstatements-1].op = OP_GLOBALADDRESS;
4827 e->type = QCC_PR_PointerType(e->type);
4830 else if (OP_LOADP_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADP_I)
4832 statements[numstatements-1].op = OP_POINTER_ADD;
4833 e->type = QCC_PR_PointerType(e->type);
4836 else //this is a restriction that could be lifted, I just want to make sure that I got all the bits first.
4838 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for '&' Must be singular expression or field reference");
4842 // QCC_PR_ParseWarning(0, "debug: &global");
4844 if (!QCC_OPCodeValid(&pr_opcodes[OP_GLOBALADDRESS]))
4845 QCC_PR_ParseError (ERR_BADEXTENSION, "Cannot use addressof operator ('&') on a global. Please use the FTE target.");
4847 e2 = QCC_PR_Statement (&pr_opcodes[OP_GLOBALADDRESS], e, 0, NULL);
4848 e2->type = QCC_PR_PointerType(e->type);
4851 else if (QCC_PR_CheckToken ("*"))
4853 e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
4857 e2 = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], e, QCC_MakeFloatConst(0), NULL);
4858 else if (t == ev_pointer)
4860 switch(e->type->aux_type->type)
4863 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL);
4866 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL);
4869 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL);
4872 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL);
4875 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
4878 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
4881 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
4884 e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
4888 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)");
4892 e2->type = e->type->aux_type;
4895 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *");
4898 else if (QCC_PR_CheckToken ("-"))
4900 e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
4902 switch(e->type->type)
4905 e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatConst(0), e, NULL);
4908 e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorConst(0, 0, 0), e, NULL);
4911 e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntConst(0), e, NULL);
4914 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for -");
4920 else if (QCC_PR_CheckToken ("+"))
4922 e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
4924 switch(e->type->type)
4936 QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for +");
4943 if (QCC_PR_CheckToken ("("))
4945 QCC_type_t *newtype;
4946 newtype = QCC_PR_ParseType(false, true);
4949 QCC_PR_Expect (")");
4950 e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
4952 /*you may cast from a type to itself*/
4953 if (!typecmp(e->type, newtype))
4956 /*you may cast from const 0 to any type of same size for free (from either int or float for simplicity)*/
4957 else if (newtype->size == e->type->size && (e->type->type == ev_integer || e->type->type == ev_float) && e->constant && !G_INT(e->ofs))
4960 e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4961 memset (e2, 0, sizeof(QCC_def_t));
4965 e2->constant = true;
4969 /*cast from int->float will convert*/
4970 else if (newtype->type == ev_float && e->type->type == ev_integer)
4971 return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL);
4972 /*cast from float->int will convert*/
4973 else if (newtype->type == ev_integer && e->type->type == ev_float)
4974 return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL);
4975 /*you may freely cast between pointers (and ints, as this is explicit) (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/
4978 ((newtype->type == ev_pointer || newtype->type == ev_string || newtype->type == ev_integer) && (e->type->type == ev_pointer || e->type->type == ev_string || e->type->type == ev_integer))
4980 || (newtype->type == ev_entity && e->type->type == ev_entity)
4981 //variants are fine too
4982 || (newtype->type == ev_variant || e->type->type == ev_variant)
4986 e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
4987 memset (e2, 0, sizeof(QCC_def_t));
4991 e2->constant = true;
4996 QCC_PR_ParseError(0, "Bad type cast\n");
4998 /* else if (QCC_PR_CheckToken("*"))
5000 QCC_PR_Expect (")");
5002 e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
5003 memset (e2, 0, sizeof(QCC_def_t));
5004 e2->type = type_pointer;
5006 e2->constant = true;
5010 else if (QCC_PR_CheckKeyword(keyword_float, "float")) //check for type casts
5012 QCC_PR_Expect (")");
5014 if (e->type->type == ev_float)
5016 else if (e->type->type == ev_integer)
5017 return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL);
5018 else if (e->type->type == ev_function)
5021 // QCC_PR_ParseError ("invalid typecast");
5023 QCC_PR_ParseWarning (0, "Not all vars make sence as floats");
5025 e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
5026 memset (e2, 0, sizeof(QCC_def_t));
5027 e2->type = type_float;
5029 e2->constant = true;
5033 else if (QCC_PR_CheckKeyword(keyword_class, "class"))
5035 QCC_type_t *classtype = QCC_TypeForName(QCC_PR_ParseName());
5037 QCC_PR_ParseError(ERR_NOTANAME, "Class not defined for cast");
5039 QCC_PR_Expect (")");
5041 e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
5042 memset (e2, 0, sizeof(QCC_def_t));
5043 e2->type = classtype;
5045 e2->constant = true;
5049 else if (QCC_PR_CheckKeyword(keyword_integer, "integer")) //check for type casts
5051 QCC_PR_Expect (")");
5053 if (e->type->type == ev_integer)
5055 else if (e->type->type == ev_float)
5056 return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL);
5058 QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast");
5060 else if (QCC_PR_CheckKeyword(keyword_int, "int")) //check for type casts
5062 QCC_PR_Expect (")");
5064 if (e->type->type == ev_integer)
5066 else if (e->type->type == ev_float)
5067 return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL);
5069 QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast");
5073 pbool oldcond = conditional;
5074 conditional = conditional?2:0;
5075 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5076 QCC_PR_Expect (")");
5077 conditional = oldcond;
5082 return QCC_PR_ParseValue (pr_classtype, true);
5086 int QCC_canConv(QCC_def_t *from, etype_t to)
5088 if (from->type->type == to)
5091 if (from->type->type == ev_vector && to == ev_float)
5096 if (from->type->type == ev_field)
5098 if (from->type->aux_type->type == to)
5103 if (from->type->type == ev_variant)
5106 /* if (from->type->type == ev_pointer && from->type->aux_type->type == to)
5109 if (QCC_ShouldConvert(from, to)>=0)
5112 if (from->type->type == ev_integer && to == ev_function)
5115 if (from->constant && from->arraysize == 0 && (from->type->type == ev_integer || from->type->type == ev_float) && !G_INT(from->ofs))
5126 QCC_def_t *QCC_PR_Expression (int priority, int exprflags)
5128 QCC_dstatement32_t *st;
5129 QCC_opcode_t *op, *oldop;
5131 QCC_opcode_t *bestop;
5132 int numconversions, c;
5137 etype_t type_a, type_b, type_c;
5140 return QCC_PR_Term ();
5142 e = QCC_PR_Expression (priority-1, exprflags);
5146 if (priority == FUNC_PRIORITY)
5148 if (QCC_PR_CheckToken ("(") )
5150 qcc_usefulstatement=true;
5151 e = QCC_PR_ParseFunctionCall (e);
5153 if (QCC_PR_CheckToken ("?"))
5155 QCC_dstatement32_t *fromj, *elsej;
5156 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], e, NULL, &fromj));
5157 e = QCC_PR_Expression(TOP_PRIORITY, 0);
5158 e2 = QCC_GetTemp(e->type);
5159 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[(e2->type->size>=3)?OP_STORE_V:OP_STORE_F], e, e2, NULL));
5160 //e2 can be stomped upon until its reused anyway
5164 QCC_PR_Statement(&pr_opcodes[OP_GOTO], NULL, NULL, &elsej);
5165 fromj->b = &statements[numstatements] - fromj;
5166 e = QCC_PR_Expression(TOP_PRIORITY, 0);
5168 if (typecmp(e->type, e2->type) != 0)
5169 QCC_PR_ParseError(0, "Ternary operator with mismatching types\n");
5170 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[(e2->type->size>=3)?OP_STORE_V:OP_STORE_F], e, e2, NULL));
5173 elsej->a = &statements[numstatements] - elsej;
5180 if (pr_token_type == tt_immediate)
5182 if ((pr_immediate_type->type == ev_float && pr_immediate._float < 0) ||
5183 (pr_immediate_type->type == ev_integer && pr_immediate._int < 0)) //hehehe... was a minus all along...
5185 QCC_PR_IncludeChunk(pr_token, true, NULL);
5186 strcpy(pr_token, "+");//two negatives would make a positive.
5187 pr_token_type = tt_punct;
5191 if (pr_token_type != tt_punct)
5193 QCC_PR_ParseWarning(WARN_UNEXPECTEDPUNCT, "Expected punctuation");
5196 //go straight for the correct priority.
5197 for (op = opcodeprioritized[priority][opnum]; op; op = opcodeprioritized[priority][++opnum])
5198 // for (op=pr_opcodes ; op->name ; op++)
5200 // if (op->priority != priority)
5202 if (!QCC_PR_CheckToken (op->name))
5205 if ( op->associative!=ASSOC_LEFT )
5207 // if last statement is an indirect, change it to an address of
5208 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)
5210 qcc_usefulstatement=true;
5211 statements[numstatements-1].op = OP_ADDRESS;
5212 type_pointer->aux_type->type = e->type->type;
5213 e->type = type_pointer;
5215 //if last statement retrieved a value, switch it to retrieve a usable pointer.
5216 if ( !simplestore && (unsigned)(statements[numstatements-1].op - OP_LOADA_F) < 7)// || statements[numstatements-1].op == OP_LOADA_C)
5218 statements[numstatements-1].op = OP_GLOBALADDRESS;
5219 type_pointer->aux_type->type = e->type->type;
5220 e->type = type_pointer;
5222 if ( !simplestore && (unsigned)(statements[numstatements-1].op - OP_LOADP_F) < 7 && statements[numstatements-1].c == e->ofs)
5224 if (!statements[numstatements-1].b)
5226 //if the loadp has no offset, remove the instruction and convert the dest of this instruction directly to the pointer's load address
5227 //this kills the add 0.
5228 e->ofs = statements[numstatements-1].a;
5233 statements[numstatements-1].op = OP_POINTER_ADD;
5235 if (e->type != type_pointer)
5237 type_pointer->aux_type->type = e->type->type;
5238 e->type = type_pointer;
5241 if ( !simplestore && statements[numstatements-1].op == OP_LOADP_C && e->ofs == statements[numstatements-1].c)
5243 statements[numstatements-1].op = OP_ADD_SF;
5244 e->type = type_string;
5246 //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)
5247 e2 = QCC_PR_Expression (priority, exprflags);
5248 if (e2->type->type == ev_float)
5249 op = &pr_opcodes[OP_STOREP_C];
5252 e2 = QCC_PR_Expression (priority, exprflags);
5256 if (op->priority == 7 && opt_logicops)
5259 st = &statements[numstatements];
5260 if (*op->name == '&') //statement 3 because we don't want to optimise this into if from not ifnot
5261 QCC_PR_Statement3(&pr_opcodes[OP_IFNOT_I], e, NULL, NULL, false);
5263 QCC_PR_Statement3(&pr_opcodes[OP_IF_I], e, NULL, NULL, false);
5266 e2 = QCC_PR_Expression (priority-1, exprflags);
5270 type_a = e->type->type;
5271 type_b = e2->type->type;
5273 // if (type_a == ev_pointer && type_b == ev_pointer)
5274 // QCC_PR_ParseWarning(0, "Debug: pointer op pointer");
5276 if (op->name[0] == '.')// field access gets type from field
5278 if (e2->type->aux_type)
5279 type_c = e2->type->aux_type->type;
5281 type_c = -1; // not a field
5288 numconversions = 32767;
5291 if (!(type_c != ev_void && type_c != (*op->type_c)->type))
5293 if (!STRCMP (op->name , oldop->name)) //matches
5295 //return values are never converted - what to?
5296 // if (type_c != ev_void && type_c != op->type_c->type->type)
5302 if (op->associative!=ASSOC_LEFT)
5304 if (op->type_a == &type_pointer) //ent var
5306 /*FIXME: I don't like this code*/
5307 if (e->type->type != ev_pointer)
5308 c = -200; //don't cast to a pointer.
5309 else if ((*op->type_c)->type == ev_void && op->type_b == &type_pointer && e2->type->type == ev_pointer)
5310 c = 0; //generic pointer... fixme: is this safe? make sure both sides are equivelent
5311 else if (e->type->aux_type->type != (*op->type_b)->type) //if e isn't a pointer to a type_b
5312 c = -200; //don't let the conversion work
5314 c = QCC_canConv(e2, (*op->type_c)->type);
5318 c=QCC_canConv(e2, (*op->type_b)->type);
5319 if (type_a != (*op->type_a)->type) //in this case, a is the final assigned value
5320 c = -300; //don't use this op, as we must not change var b's type
5321 else if ((*op->type_a)->type == ev_pointer && e->type->aux_type->type != (*op->type_a)->aux_type->type)
5322 c = -300; //don't use this op if its a pointer to a different type
5327 if (op->type_a == &type_pointer) //ent var
5329 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
5330 c = -200; //don't let the conversion work
5336 c=QCC_canConv(e, (*op->type_a)->type);
5337 c+=QCC_canConv(e2, (*op->type_b)->type);
5341 if (c>=0 && c < numconversions)
5345 if (c == 0)//can't get less conversions than 0...
5352 op = opcodeprioritized[priority][++opnum];
5356 if (oldop->priority == CONDITION_PRIORITY)
5363 QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch for %s (%s and %s)", oldop->name, e->type->name, e2->type->name);
5366 QCC_PR_ParseError (ERR_TYPEMISMATCH, "type mismatch for %s (%s and %s)", oldop->name, e->type->name, e2->type->name);
5371 if (numconversions>3)
5372 QCC_PR_ParseWarning(WARN_IMPLICITCONVERSION, "Implicit conversion");
5376 // if (type_a == ev_pointer && type_b != e->type->aux_type->type)
5377 // QCC_PR_ParseError ("type mismatch for %s", op->name);
5380 st->b = &statements[numstatements] - st;
5383 if (op->associative!=ASSOC_LEFT)
5385 qcc_usefulstatement = true;
5386 if (e->constant || e->ofs < OFS_PARM0)
5388 if (e->type->type == ev_function)
5390 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANTFUNC, "Assignment to function %s", e->name);
5391 QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANTFUNC, e);
5395 QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
5396 QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, e);
5399 editbadfile(strings+s_file, pr_source_line);
5403 QCC_PR_ParseWarning(WARN_ASSIGNMENTINCONDITIONAL, "Assignment in conditional");
5405 e = QCC_PR_Statement (op, e2, e, NULL);
5408 e = QCC_PR_Statement (op, e, e2, NULL);
5410 if (type_c != ev_void/* && type_c != ev_string*/) // field access gets type from field
5411 e->type = e2->type->aux_type;
5413 if (priority > 1 && exprflags & EXPR_WARN_ABOVE_1)
5414 QCC_PR_ParseWarning(0, "You may wish to add brackets after that ! operator");
5421 QCC_PR_ParseError(ERR_INTERNAL, "e == null");
5424 if (!STRCMP(pr_token, "++"))
5426 //if the last statement was an ent.float (or something)
5427 if (((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I) && statements[numstatements-1].c == e->ofs)
5428 { //we have our load.
5430 //the only inefficiency here is with an extra temp (we can't reuse the original)
5431 //this is not a problem, as the optimise temps or locals marshalling can clean these up for us
5432 qcc_usefulstatement=true;
5435 //store temp to offset
5436 //return original loaded (which is not at the same offset as the pointer we store to)
5437 e2 = QCC_GetTemp(type_float);
5438 e3 = QCC_GetTemp(type_pointer);
5439 QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
5440 if (e->type->type == ev_float)
5442 QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e2, false);
5443 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
5445 else if (e->type->type == ev_integer)
5447 QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e2, false);
5448 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
5452 QCC_PR_ParseError(ERR_PARSEERRORS, "-- suffix operator results in nonstandard behaviour. Use -=1 or prefix form instead");
5453 QCC_PR_IncludeChunk("-=1", false, NULL);
5458 else if (e->type->type == ev_float)
5462 //return temp (which == original)
5463 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "++ suffix operator results in inefficient behaviour. Use +=1 or prefix form instead");
5464 qcc_usefulstatement=true;
5466 e2 = QCC_GetTemp(type_float);
5467 QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
5468 QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false);
5472 else if (e->type->type == ev_integer)
5474 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "++ suffix operator results in inefficient behaviour. Use +=1 or prefix form instead");
5475 qcc_usefulstatement=true;
5477 e2 = QCC_GetTemp(type_integer);
5478 QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
5479 QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false);
5485 QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "++ suffix operator results in nonstandard behaviour. Use +=1 or prefix form instead");
5486 QCC_PR_IncludeChunk("+=1", false, NULL);
5490 else if (!STRCMP(pr_token, "--"))
5492 if (((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I) && statements[numstatements-1].c == e->ofs)
5493 { //we have our load.
5497 //store temp to offset
5498 //return original loaded (which is not at the same offset as the pointer we store to)
5499 e2 = QCC_GetTemp(type_float);
5500 e3 = QCC_GetTemp(type_pointer);
5501 QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false);
5502 if (e->type->type == ev_float)
5504 QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e2, false);
5505 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false);
5507 else if (e->type->type == ev_integer)
5509 QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e2, false);
5510 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false);
5514 QCC_PR_ParseError(ERR_PARSEERRORS, "-- suffix operator results in nonstandard behaviour. Use -=1 or prefix form instead");
5515 QCC_PR_IncludeChunk("-=1", false, NULL);
5520 else if (e->type->type == ev_float)
5522 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "-- suffix operator results in inefficient behaviour. Use -=1 or prefix form instead");
5523 qcc_usefulstatement=true;
5525 e2 = QCC_GetTemp(type_float);
5526 QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false);
5527 QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false);
5531 else if (e->type->type == ev_integer)
5533 QCC_PR_ParseWarning(WARN_INEFFICIENTPLUSPLUS, "-- suffix operator results in inefficient behaviour. Use -=1 or prefix form instead");
5534 qcc_usefulstatement=true;
5536 e2 = QCC_GetTemp(type_integer);
5537 QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false);
5538 QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false);
5544 QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "-- suffix operator results in nonstandard behaviour. Use -=1 or prefix form instead");
5545 QCC_PR_IncludeChunk("-=1", false, NULL);
5549 break; // next token isn't at this priority level
5553 QCC_PR_ParseError(ERR_INTERNAL, "e == null");
5555 if (!(exprflags&EXPR_DISALLOW_COMMA) && priority == TOP_PRIORITY && QCC_PR_CheckToken (","))
5557 if (!qcc_usefulstatement)
5558 QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Effectless statement");
5561 qcc_usefulstatement = false;
5562 e = QCC_PR_Expression(TOP_PRIORITY, exprflags);
5568 int QCC_PR_IntConstExpr(void)
5570 QCC_def_t *def = QCC_PR_Expression(TOP_PRIORITY, 0);
5574 if (def->type->type == ev_integer)
5575 return G_INT(def->ofs);
5576 if (def->type->type == ev_float)
5578 int i = G_FLOAT(def->ofs);
5579 if ((float)i == G_FLOAT(def->ofs))
5583 QCC_PR_ParseError(ERR_NOTACONSTANT, "Value is not an integer constant");
5587 void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname)
5589 if (num_gotos >= max_gotos)
5592 pr_gotos = realloc(pr_gotos, sizeof(*pr_gotos)*max_gotos);
5595 strncpy(pr_gotos[num_gotos].name, labelname, sizeof(pr_gotos[num_gotos].name) -1);
5596 pr_gotos[num_gotos].lineno = pr_source_line;
5597 pr_gotos[num_gotos].statementno = patch2 - statements;
5602 pbool QCC_PR_StatementBlocksMatch(QCC_dstatement_t *p1, int p1count, QCC_dstatement_t *p2, int p2count)
5604 if (p1count != p2count)
5609 if (p1->op != p2->op)
5631 void QCC_PR_ParseStatement (void)
5638 QCC_dstatement_t *patch1, *patch2, *patch3;
5639 int statementstart = pr_source_line;
5641 if (QCC_PR_CheckToken ("{"))
5644 while (!QCC_PR_CheckToken("}"))
5645 QCC_PR_ParseStatement ();
5647 if (pr_subscopedlocals)
5649 for (e2 = pr.localvars; e2 != e; e2 = e2->nextlocal)
5651 if (!e2->subscoped_away)
5653 Hash_RemoveData(&localstable, e2->name, e2);
5654 e2->subscoped_away = true;
5661 if (QCC_PR_CheckKeyword(keyword_return, "return"))
5665 e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
5666 e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
5667 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL));
5670 if (QCC_PR_CheckToken (";"))
5672 if (pr_scope->type->aux_type->type != ev_void)
5673 QCC_PR_ParseWarning(WARN_MISSINGRETURNVALUE, "\'%s\' should return %s", pr_scope->name, pr_scope->type->aux_type->name);
5674 if (opt_return_only)
5675 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_DONE], 0, 0, NULL));
5677 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], 0, 0, NULL));
5680 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5681 e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type, true);
5684 QCC_PR_ParseWarning(WARN_CORRECTEDRETURNTYPE, "\'%s\' returned %s, expected %s, conversion supplied", pr_scope->name, e->type->name, pr_scope->type->aux_type->name);
5687 QCC_PR_Expect (";");
5688 if (pr_scope->type->aux_type->type != e->type->type)
5689 QCC_PR_ParseWarning(WARN_WRONGRETURNTYPE, "\'%s\' returned %s, expected %s", pr_scope->name, e->type->name, pr_scope->type->aux_type->name);
5690 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], e, 0, NULL));
5693 if (QCC_PR_CheckKeyword(keyword_exit, "exit"))
5695 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_DONE], 0, 0, NULL));
5696 QCC_PR_Expect (";");
5700 if (QCC_PR_CheckKeyword(keyword_while, "while"))
5702 continues = num_continues;
5703 breaks = num_breaks;
5705 QCC_PR_Expect ("(");
5706 patch2 = &statements[numstatements];
5708 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5710 if (((e->constant && !e->temp) || !STRCMP(e->name, "IMMEDIATE")) && opt_compound_jumps)
5712 optres_compound_jumps++;
5715 QCC_PR_ParseWarning(0, "while(0)?");
5716 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch1));
5725 if (e->constant && !e->temp)
5727 if (!G_FLOAT(e->ofs))
5728 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch1));
5732 else if (!typecmp( e->type, type_string) && flag_ifstring) //special case, as strings are now pointers, not offsets from string table
5734 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "while(string) can result in bizzare behaviour");
5735 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch1));
5737 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) //special case, as negative 0 is also zero
5738 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
5740 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1));
5742 QCC_PR_Expect (")"); //after the line number is noted..
5743 QCC_PR_ParseStatement ();
5744 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], NULL, 0, &patch3));
5745 patch3->a = patch2 - patch3;
5748 if (patch1->op == OP_GOTO)
5749 patch1->a = &statements[numstatements] - patch1;
5751 patch1->b = &statements[numstatements] - patch1;
5754 if (breaks != num_breaks)
5756 for(i = breaks; i < num_breaks; i++)
5758 patch1 = &statements[pr_breaks[i]];
5759 statements[pr_breaks[i]].a = &statements[numstatements] - patch1; //jump to after the return-to-top goto
5761 num_breaks = breaks;
5763 if (continues != num_continues)
5765 for(i = continues; i < num_continues; i++)
5767 patch1 = &statements[pr_continues[i]];
5768 statements[pr_continues[i]].a = patch2 - patch1; //jump back to top
5770 num_continues = continues;
5774 if (QCC_PR_CheckKeyword(keyword_for, "for"))
5776 int old_numstatements;
5780 QCC_dstatement_t temp[sizeof(linenum)/sizeof(linenum[0])];
5782 continues = num_continues;
5783 breaks = num_breaks;
5786 if (!QCC_PR_CheckToken(";"))
5788 QCC_FreeTemp(QCC_PR_Expression(TOP_PRIORITY, 0));
5792 patch2 = &statements[numstatements];
5793 if (!QCC_PR_CheckToken(";"))
5796 e = QCC_PR_Expression(TOP_PRIORITY, 0);
5803 if (!QCC_PR_CheckToken(")"))
5805 old_numstatements = numstatements;
5806 QCC_FreeTemp(QCC_PR_Expression(TOP_PRIORITY, 0));
5808 numtemp = numstatements - old_numstatements;
5809 if (numtemp > sizeof(linenum)/sizeof(linenum[0]))
5810 QCC_PR_ParseError(ERR_TOOCOMPLEX, "Update expression too large");
5811 numstatements = old_numstatements;
5812 for (i = 0 ; i < numtemp ; i++)
5814 linenum[i] = statement_linenums[numstatements + i];
5815 temp[i] = statements[numstatements + i];
5824 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], e, 0, &patch1));
5827 if (!QCC_PR_CheckToken(";"))
5828 QCC_PR_ParseStatement(); //don't give the hanging ';' warning.
5829 patch3 = &statements[numstatements];
5830 for (i = 0 ; i < numtemp ; i++)
5832 statement_linenums[numstatements] = linenum[i];
5833 statements[numstatements++] = temp[i];
5835 QCC_PR_SimpleStatement(OP_GOTO, patch2 - &statements[numstatements], 0, 0, false);
5837 patch1->b = &statements[numstatements] - patch1;
5839 if (breaks != num_breaks)
5841 for(i = breaks; i < num_breaks; i++)
5843 patch1 = &statements[pr_breaks[i]];
5844 statements[pr_breaks[i]].a = &statements[numstatements] - patch1;
5846 num_breaks = breaks;
5848 if (continues != num_continues)
5850 for(i = continues; i < num_continues; i++)
5852 patch1 = &statements[pr_continues[i]];
5853 statements[pr_continues[i]].a = patch3 - patch1;
5855 num_continues = continues;
5860 if (QCC_PR_CheckKeyword(keyword_do, "do"))
5862 continues = num_continues;
5863 breaks = num_breaks;
5865 patch1 = &statements[numstatements];
5866 QCC_PR_ParseStatement ();
5867 QCC_PR_Expect ("while");
5868 QCC_PR_Expect ("(");
5870 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5873 if (e->constant && !e->temp)
5875 if (G_FLOAT(e->ofs))
5877 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], NULL, 0, &patch2));
5878 patch2->a = patch1 - patch2;
5883 if (!typecmp( e->type, type_string) && flag_ifstring)
5885 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "do {} while(string) can result in bizzare behaviour");
5886 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_S], e, NULL, &patch2));
5888 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
5889 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, NULL, &patch2));
5891 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &patch2));
5893 patch2->b = patch1 - patch2;
5896 QCC_PR_Expect (")");
5897 QCC_PR_Expect (";");
5899 if (breaks != num_breaks)
5901 for(i = breaks; i < num_breaks; i++)
5903 patch2 = &statements[pr_breaks[i]];
5904 statements[pr_breaks[i]].a = &statements[numstatements] - patch2;
5906 num_breaks = breaks;
5908 if (continues != num_continues)
5910 for(i = continues; i < num_continues; i++)
5912 patch2 = &statements[pr_continues[i]];
5913 statements[pr_continues[i]].a = patch1 - patch2;
5915 num_continues = continues;
5921 if (QCC_PR_CheckKeyword(keyword_local, "local"))
5923 QCC_type_t *functionsclasstype = pr_classtype;
5924 // if (locals_end != numpr_globals) //is this breaking because of locals?
5925 // QCC_PR_ParseWarning("local vars after temp vars\n");
5926 QCC_PR_ParseDefs (NULL);
5927 pr_classtype = functionsclasstype;
5928 locals_end = numpr_globals;
5932 if (pr_token_type == tt_name)
5933 if ((keyword_var && !STRCMP ("var", pr_token)) ||
5934 (keyword_string && !STRCMP ("string", pr_token)) ||
5935 (keyword_float && !STRCMP ("float", pr_token)) ||
5936 (keyword_entity && !STRCMP ("entity", pr_token)) ||
5937 (keyword_vector && !STRCMP ("vector", pr_token)) ||
5938 (keyword_integer && !STRCMP ("integer", pr_token)) ||
5939 (keyword_int && !STRCMP ("int", pr_token)) ||
5940 (keyword_class && !STRCMP ("class", pr_token)) ||
5941 (keyword_const && !STRCMP ("const", pr_token)))
5943 // if (locals_end != numpr_globals) //is this breaking because of locals?
5944 // QCC_PR_ParseWarning("local vars after temp vars\n");
5945 QCC_PR_ParseDefs (NULL);
5946 locals_end = numpr_globals;
5950 if (QCC_PR_CheckKeyword(keyword_state, "state"))
5953 QCC_PR_ParseState();
5957 if (QCC_PR_CheckToken("#"))
5960 float frame = pr_immediate._float;
5962 name = QCC_PR_ParseName();
5963 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatConst(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL));
5968 if (QCC_PR_CheckKeyword(keyword_if, "if"))
5970 pbool negate = QCC_PR_CheckKeyword(keyword_not, "not");
5972 QCC_PR_Expect ("(");
5974 e = QCC_PR_Expression (TOP_PRIORITY, 0);
5977 // negate = negate != 0;
5981 if (!typecmp( e->type, type_string) && flag_ifstring)
5983 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if not(string) can result in bizzare behaviour");
5984 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_S], e, 0, &patch1));
5986 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
5987 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, 0, &patch1));
5989 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, 0, &patch1));
5993 if (!typecmp( e->type, type_string) && flag_ifstring)
5995 QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if (string) can result in bizzare behaviour");
5996 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch1));
5998 else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
5999 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
6001 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1));
6004 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
6006 QCC_PR_ParseStatement ();
6008 if (QCC_PR_CheckKeyword (keyword_else, "else"))
6011 lastwasreturn = statements[numstatements-1].op == OP_RETURN || statements[numstatements-1].op == OP_DONE ||
6012 statements[numstatements-1].op == OP_GOTO;
6014 //the last statement of the if was a return, so we don't need the goto at the end
6015 if (lastwasreturn && opt_compound_jumps && !QCC_AStatementJumpsTo(numstatements, patch1-statements, numstatements))
6017 // QCC_PR_ParseWarning(0, "optimised the else");
6018 optres_compound_jumps++;
6019 patch1->b = &statements[numstatements] - patch1;
6020 QCC_PR_ParseStatement ();
6024 // QCC_PR_ParseWarning(0, "using the else");
6025 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2));
6026 patch1->b = &statements[numstatements] - patch1;
6027 QCC_PR_ParseStatement ();
6028 patch2->a = &statements[numstatements] - patch2;
6030 if (QCC_PR_StatementBlocksMatch(patch1+1, patch2-patch1, patch2+1, &statements[numstatements] - patch2))
6031 QCC_PR_ParseWarning(0, "Two identical blocks each side of an else");
6035 patch1->b = &statements[numstatements] - patch1;
6039 if (QCC_PR_CheckKeyword(keyword_switch, "switch"))
6043 int defaultcase = -1;
6046 QCC_type_t *switchtype;
6048 breaks = num_breaks;
6052 QCC_PR_Expect ("(");
6055 e = QCC_PR_Expression (TOP_PRIORITY, 0);
6059 { //copy it out, so our hack just below doesn't crash us
6060 /* if (e->type->type == ev_vector)
6061 e = QCC_PR_Statement(pr_opcodes+OP_STORE_V, e, QCC_GetTemp(type_vector), NULL);
6063 e = QCC_PR_Statement(pr_opcodes+OP_STORE_F, e, QCC_GetTemp(type_float), NULL);
6065 if (e == &def_ret) //this shouldn't be happening
6066 QCC_Error(ERR_INTERNAL, "internal error: switch: e == &def_ret");
6073 e->temp = NULL; //so noone frees it until we finish this loop
6078 //switch (CONDITION)
6089 // x = CONDITION, goto start
6097 // if (x == 1) goto l1;
6098 // if (x == 2) goto l2;
6102 //x is emitted in an opcode, stored as a register that we cannot access later.
6103 //it should be possible to nest these.
6105 switchtype = e->type;
6106 switch(switchtype->type)
6111 case ev_entity: //whu???
6129 hcstyle = QCC_OPCodeValid(&pr_opcodes[op]);
6135 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[op], e, 0, &patch1));
6137 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], e, 0, &patch1));
6139 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
6141 oldst = numstatements;
6142 QCC_PR_ParseStatement ();
6144 //this is so that a missing goto at the end of your switch doesn't end up in the jumptable again
6145 if (oldst == numstatements || !QCC_StatementIsAJump(numstatements-1, numstatements-1))
6147 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2)); //the P1 statement/the theyforgotthebreak statement.
6148 // QCC_PR_ParseWarning(0, "emitted goto");
6153 // QCC_PR_ParseWarning(0, "No goto");
6157 patch1->b = &statements[numstatements] - patch1; //the goto start part
6159 patch1->a = &statements[numstatements] - patch1; //the goto start part
6162 e->type = switchtype; //set it back to the type it was actually meant to be.
6164 for (i = cases; i < num_cases; i++)
6166 if (!pr_casesdef[i])
6168 if (defaultcase >= 0)
6169 QCC_PR_ParseError(ERR_MULTIPLEDEFAULTS, "Duplicated default case");
6174 if (pr_casesdef[i]->type->type != e->type->type)
6176 if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
6177 pr_casesdef[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef[i]->ofs]);
6179 QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch case type mismatch");
6181 if (pr_casesdef2[i])
6183 if (pr_casesdef2[i]->type->type != e->type->type)
6185 if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float)
6186 pr_casesdef2[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef2[i]->ofs]);
6188 QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch caserange type mismatch");
6193 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CASERANGE], pr_casesdef[i], pr_casesdef2[i], &patch3));
6194 patch3->c = &statements[pr_cases[i]] - patch3;
6200 if (e->type->type == ev_float)
6202 e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_F], e, pr_casesdef[i], NULL);
6203 e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_F], e, pr_casesdef2[i], NULL);
6204 e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_F], e2, e3, NULL);
6205 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3));
6206 patch3->b = &statements[pr_cases[i]] - patch3;
6208 else if (e->type->type == ev_integer)
6210 e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_I], e, pr_casesdef[i], NULL);
6211 e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_I], e, pr_casesdef2[i], NULL);
6212 e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_I], e2, e3, NULL);
6213 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3));
6214 patch3->b = &statements[pr_cases[i]] - patch3;
6217 QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch caserange MUST be a float or integer");
6224 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CASE], pr_casesdef[i], 0, &patch3));
6225 patch3->b = &statements[pr_cases[i]] - patch3;
6229 if (!pr_casesdef[i]->constant || G_INT(pr_casesdef[i]->ofs))
6231 switch(e->type->type)
6234 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_F], e, pr_casesdef[i], NULL);
6236 case ev_entity: //whu???
6237 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_E], e, pr_casesdef[i], &patch1);
6240 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_V], e, pr_casesdef[i], &patch1);
6243 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_S], e, pr_casesdef[i], &patch1);
6246 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_FNC], e, pr_casesdef[i], &patch1);
6249 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_FNC], e, pr_casesdef[i], &patch1);
6252 e2 = QCC_PR_Statement (&pr_opcodes[OP_EQ_I], e, pr_casesdef[i], &patch1);
6255 QCC_PR_ParseError(ERR_BADSWITCHTYPE, "Bad switch type");
6259 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3));
6263 if (e->type->type == ev_string)
6264 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch3));
6265 else if (e->type->type == ev_float)
6266 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch3));
6268 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch3));
6270 patch3->b = &statements[pr_cases[i]] - patch3;
6277 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch3));
6278 patch3->a = &statements[pr_cases[defaultcase]] - patch3;
6284 patch3 = &statements[numstatements];
6286 patch2->a = patch3 - patch2; //set P1 jump
6288 if (breaks != num_breaks)
6290 for(i = breaks; i < num_breaks; i++)
6292 patch2 = &statements[pr_breaks[i]];
6293 patch2->a = patch3 - patch2;
6295 num_breaks = breaks;
6306 if (QCC_PR_CheckKeyword(keyword_asm, "asm"))
6308 if (QCC_PR_CheckToken("{"))
6310 while (!QCC_PR_CheckToken("}"))
6318 if (QCC_PR_CheckToken(":"))
6320 if (pr_token_type != tt_name)
6322 QCC_PR_ParseError(ERR_BADLABELNAME, "invalid label name \"%s\"", pr_token);
6326 for (i = 0; i < num_labels; i++)
6327 if (!STRNCMP(pr_labels[i].name, pr_token, sizeof(pr_labels[num_labels].name) -1))
6329 QCC_PR_ParseWarning(WARN_DUPLICATELABEL, "Duplicate label %s", pr_token);
6334 if (num_labels >= max_labels)
6337 pr_labels = realloc(pr_labels, sizeof(*pr_labels)*max_labels);
6340 strncpy(pr_labels[num_labels].name, pr_token, sizeof(pr_labels[num_labels].name) -1);
6341 pr_labels[num_labels].lineno = pr_source_line;
6342 pr_labels[num_labels].statementno = numstatements;
6346 // QCC_PR_ParseWarning("Gotos are evil");
6350 if (QCC_PR_CheckKeyword(keyword_goto, "goto"))
6352 if (pr_token_type != tt_name)
6354 QCC_PR_ParseError(ERR_NOLABEL, "invalid label name \"%s\"", pr_token);
6358 QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2);
6360 QCC_PR_GotoStatement (patch2, pr_token);
6362 // QCC_PR_ParseWarning("Gotos are evil");
6368 if (QCC_PR_CheckKeyword(keyword_break, "break"))
6370 if (!STRCMP ("(", pr_token))
6371 { //make sure it wasn't a call to the break function.
6372 QCC_PR_IncludeChunk("break(", true, NULL);
6373 QCC_PR_Lex(); //so it sees the break.
6377 if (num_breaks >= max_breaks)
6380 pr_breaks = realloc(pr_breaks, sizeof(*pr_breaks)*max_breaks);
6382 pr_breaks[num_breaks] = numstatements;
6383 QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, NULL);
6389 if (QCC_PR_CheckKeyword(keyword_continue, "continue"))
6391 if (num_continues >= max_continues)
6394 pr_continues = realloc(pr_continues, sizeof(*pr_continues)*max_continues);
6396 pr_continues[num_continues] = numstatements;
6397 QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, NULL);
6402 if (QCC_PR_CheckKeyword(keyword_case, "case"))
6404 if (num_cases >= max_cases)
6407 pr_cases = realloc(pr_cases, sizeof(*pr_cases)*max_cases);
6408 pr_casesdef = realloc(pr_casesdef, sizeof(*pr_casesdef)*max_cases);
6409 pr_casesdef2 = realloc(pr_casesdef2, sizeof(*pr_casesdef2)*max_cases);
6411 pr_cases[num_cases] = numstatements;
6412 pr_casesdef[num_cases] = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
6413 if (QCC_PR_CheckToken(".."))
6415 pr_casesdef2[num_cases] = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
6416 if (pr_casesdef[num_cases]->constant && pr_casesdef2[num_cases]->constant &&
6417 !pr_casesdef[num_cases]->temp && !pr_casesdef2[num_cases]->temp)
6418 if (G_FLOAT(pr_casesdef[num_cases]->ofs) >= G_FLOAT(pr_casesdef2[num_cases]->ofs))
6419 QCC_PR_ParseError(ERR_CASENOTIMMEDIATE, "Caserange statement uses backwards range\n");
6422 pr_casesdef2[num_cases] = NULL;
6424 if (numstatements != pr_cases[num_cases])
6425 QCC_PR_ParseError(ERR_CASENOTIMMEDIATE, "Case statements may not use formulas\n");
6430 if (QCC_PR_CheckKeyword(keyword_default, "default"))
6432 if (num_cases >= max_cases)
6435 pr_cases = realloc(pr_cases, sizeof(*pr_cases)*max_cases);
6436 pr_casesdef = realloc(pr_casesdef, sizeof(*pr_casesdef)*max_cases);
6437 pr_casesdef2 = realloc(pr_casesdef2, sizeof(*pr_casesdef2)*max_cases);
6439 pr_cases[num_cases] = numstatements;
6440 pr_casesdef[num_cases] = NULL;
6441 pr_casesdef2[num_cases] = NULL;
6447 if (QCC_PR_CheckKeyword(keyword_thinktime, "thinktime"))
6449 QCC_def_t *nextthink;
6451 e = QCC_PR_Expression (TOP_PRIORITY, 0);
6453 e2 = QCC_PR_Expression (TOP_PRIORITY, 0);
6454 if (e->type->type != ev_entity || e2->type->type != ev_float)
6455 QCC_PR_ParseError(ERR_THINKTIMETYPEMISMATCH, "thinktime type mismatch");
6457 if (QCC_OPCodeValid(&pr_opcodes[OP_THINKTIME]))
6458 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_THINKTIME], e, e2, NULL));
6461 nextthink = QCC_PR_GetDef(NULL, "nextthink", NULL, false, 0, false);
6463 QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", "nextthink");
6464 time = QCC_PR_GetDef(type_float, "time", NULL, false, 0, false);
6466 QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", "time");
6467 nextthink = QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], e, nextthink, NULL);
6468 time = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], time, e2, NULL);
6469 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STOREP_F], time, nextthink, NULL));
6474 if (QCC_PR_CheckToken(";"))
6476 int osl = pr_source_line;
6477 pr_source_line = statementstart;
6478 if (!expandedemptymacro)
6479 QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Hanging ';'");
6480 pr_source_line = osl;
6484 // qcc_functioncalled=0;
6486 qcc_usefulstatement = false;
6487 e = QCC_PR_Expression (TOP_PRIORITY, 0);
6488 expandedemptymacro = false;
6489 QCC_PR_Expect (";");
6491 if (e->type->type != ev_void && !qcc_usefulstatement)
6493 int osl = pr_source_line;
6494 pr_source_line = statementstart;
6495 QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Effectless statement");
6496 pr_source_line = osl;
6501 // qcc_functioncalled=false;
6509 States are special functions made for convenience. They automatically
6510 set frame, nextthink (implicitly), and think (allowing forward definitions).
6512 // void() name = [framenum, nextthink] {code}
6514 // function void name ()
6516 // self.frame=framenum;
6517 // self.nextthink = time + 0.1;
6518 // self.think = nextthink
6523 void QCC_PR_ParseState (void)
6526 QCC_def_t *s1, *def, *sc = pr_scope;
6530 if (QCC_PR_CheckToken("++") || QCC_PR_CheckToken("--"))
6532 s1 = QCC_PR_ParseImmediate ();
6533 QCC_PR_Expect("..");
6534 def = QCC_PR_ParseImmediate ();
6535 QCC_PR_Expect ("]");
6537 if (s1->type->type != ev_float || def->type->type != ev_float)
6538 QCC_PR_ParseError(ERR_STATETYPEMISMATCH, "state type mismatch");
6541 if (QCC_OPCodeValid(&pr_opcodes[OP_CSTATE]))
6542 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CSTATE], s1, def, NULL));
6546 QCC_def_t *framef, *frame;
6548 QCC_def_t *cycle_wrapped;
6551 self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false);
6552 framef = QCC_PR_GetDef(NULL, "frame", NULL, false, 0, false);
6553 cycle_wrapped = QCC_PR_GetDef(type_float, "cycle_wrapped", NULL, false, 0, false);
6555 frame = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], self, framef, NULL);
6557 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(0), cycle_wrapped, NULL));
6558 QCC_UnFreeTemp(frame);
6560 //make sure the frame is within the bounds given.
6561 ftemp = frame->temp;
6563 t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
6564 t2 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
6565 t1 = QCC_PR_Statement(&pr_opcodes[OP_OR_F], t1, t2, NULL);
6566 QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 2, 0, false);
6568 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
6569 QCC_PR_SimpleStatement(OP_GOTO, t1->ofs, 13, 0, false);
6571 t1 = QCC_PR_Statement(&pr_opcodes[OP_GE_F], def, s1, NULL);
6572 QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 7, 0, false);
6573 QCC_FreeTemp(t1); //this block is the 'it's in a forwards direction'
6574 QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, false);
6575 t1 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
6576 QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
6578 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
6579 QCC_UnFreeTemp(frame);
6581 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(1), cycle_wrapped, NULL));
6583 QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false);
6584 //reverse animation.
6585 QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, false);
6586 t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
6587 QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
6589 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL));
6590 QCC_UnFreeTemp(frame);
6592 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(1), cycle_wrapped, NULL));
6594 //self.frame = frame happens with the normal state opcode.
6595 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], frame, pr_scope, NULL));
6597 frame->temp = ftemp;
6598 QCC_FreeTemp(frame);
6603 if (pr_token_type != tt_immediate || pr_immediate_type != type_float)
6604 QCC_PR_ParseError (ERR_STATETYPEMISMATCH, "state frame must be a number");
6605 s1 = QCC_PR_ParseImmediate ();
6607 QCC_PR_CheckToken (",");
6609 name = QCC_PR_ParseName ();
6611 def = QCC_PR_GetDef (type_function, name, NULL, true, 0, false);
6614 QCC_PR_Expect ("]");
6616 QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], s1, def, NULL));
6619 void QCC_PR_ParseAsm(void)
6621 QCC_dstatement_t *patch1;
6623 QCC_def_t *a, *b, *c;
6625 if (QCC_PR_CheckKeyword(keyword_local, "local"))
6627 QCC_PR_ParseDefs (NULL);
6628 locals_end = numpr_globals;
6632 for (op = 0; op < OP_NUMOPS; op++)
6634 if (!STRCMP(pr_token, pr_opcodes[op].opname))
6637 if (pr_opcodes[op].priority==-1 && pr_opcodes[op].associative!=ASSOC_LEFT)
6639 if (pr_opcodes[op].type_a==NULL)
6641 patch1 = &statements[numstatements];
6643 QCC_PR_Statement3(&pr_opcodes[op], NULL, NULL, NULL, true);
6645 if (pr_token_type == tt_name)
6647 QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
6651 p = (int)pr_immediate._float;
6657 else if (pr_opcodes[op].type_b==NULL)
6659 patch1 = &statements[numstatements];
6661 a = QCC_PR_ParseValue(pr_classtype, false);
6662 QCC_PR_Statement3(&pr_opcodes[op], a, NULL, NULL, true);
6664 if (pr_token_type == tt_name)
6666 QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
6670 p = (int)pr_immediate._float;
6678 patch1 = &statements[numstatements];
6680 a = QCC_PR_ParseValue(pr_classtype, false);
6681 b = QCC_PR_ParseValue(pr_classtype, false);
6682 QCC_PR_Statement3(&pr_opcodes[op], a, b, NULL, true);
6684 if (pr_token_type == tt_name)
6686 QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
6690 p = (int)pr_immediate._float;
6699 if (pr_opcodes[op].type_a != &type_void)
6700 a = QCC_PR_ParseValue(pr_classtype, false);
6703 if (pr_opcodes[op].type_b != &type_void)
6704 b = QCC_PR_ParseValue(pr_classtype, false);
6707 if (pr_opcodes[op].associative==ASSOC_LEFT && pr_opcodes[op].type_c != &type_void)
6708 c = QCC_PR_ParseValue(pr_classtype, false);
6712 QCC_PR_Statement3(&pr_opcodes[op], a, b, c, true);
6719 QCC_PR_ParseError(ERR_BADOPCODE, "Bad op code name %s", pr_token);
6722 pbool QCC_FuncJumpsTo(int first, int last, int statement)
6725 for (st = first; st < last; st++)
6727 if (pr_opcodes[statements[st].op].type_a == NULL)
6729 if (st + (signed)statements[st].a == statement)
6733 if (statements[st-1].op == OP_RETURN)
6735 if (statements[st-1].op == OP_DONE)
6741 if (pr_opcodes[statements[st].op].type_b == NULL)
6743 if (st + (signed)statements[st].b == statement)
6747 if (statements[st-1].op == OP_RETURN)
6749 if (statements[st-1].op == OP_DONE)
6755 if (pr_opcodes[statements[st].op].type_c == NULL)
6757 if (st + (signed)statements[st].c == statement)
6761 if (statements[st-1].op == OP_RETURN)
6763 if (statements[st-1].op == OP_DONE)
6773 pbool QCC_FuncJumpsToRange(int first, int last, int firstr, int lastr)
6776 for (st = first; st < last; st++)
6778 if (pr_opcodes[statements[st].op].type_a == NULL)
6780 if (st + (signed)statements[st].a >= firstr && st + (signed)statements[st].a <= lastr)
6784 if (statements[st-1].op == OP_RETURN)
6786 if (statements[st-1].op == OP_DONE)
6792 if (pr_opcodes[statements[st].op].type_b == NULL)
6794 if (st + (signed)statements[st].b >= firstr && st + (signed)statements[st].b <= lastr)
6798 if (statements[st-1].op == OP_RETURN)
6800 if (statements[st-1].op == OP_DONE)
6806 if (pr_opcodes[statements[st].op].type_c == NULL)
6808 if (st + (signed)statements[st].c >= firstr && st + (signed)statements[st].c <= lastr)
6812 if (statements[st-1].op == OP_RETURN)
6814 if (statements[st-1].op == OP_DONE)
6825 void QCC_CompoundJumps(int first, int last)
6827 //jumps to jumps are reordered so they become jumps to the final target.
6830 for (st = first; st < last; st++)
6832 if (pr_opcodes[statements[st].op].type_a == NULL)
6834 statement = st + (signed)statements[st].a;
6835 if (statements[statement].op == OP_RETURN || statements[statement].op == OP_DONE)
6836 { //goto leads to return. Copy the command out to remove the goto.
6837 statements[st].op = statements[statement].op;
6838 statements[st].a = statements[statement].a;
6839 statements[st].b = statements[statement].b;
6840 statements[st].c = statements[statement].c;
6841 optres_compound_jumps++;
6843 while (statements[statement].op == OP_GOTO)
6845 statements[st].a = statement+statements[statement].a - st;
6846 statement = st + (signed)statements[st].a;
6847 optres_compound_jumps++;
6850 if (pr_opcodes[statements[st].op].type_b == NULL)
6852 statement = st + (signed)statements[st].b;
6853 while (statements[statement].op == OP_GOTO)
6855 statements[st].b = statement+statements[statement].a - st;
6856 statement = st + (signed)statements[st].b;
6857 optres_compound_jumps++;
6860 if (pr_opcodes[statements[st].op].type_c == NULL)
6862 statement = st + (signed)statements[st].c;
6863 while (statements[statement].op == OP_GOTO)
6865 statements[st].c = statement+statements[statement].a - st;
6866 statement = st + (signed)statements[st].c;
6867 optres_compound_jumps++;
6873 void QCC_CompoundJumps(int first, int last)
6875 //jumps to jumps are reordered so they become jumps to the final target.
6879 for (st = first; st < last; st++)
6881 if (pr_opcodes[statements[st].op].type_a == NULL)
6883 statement = st + (signed)statements[st].a;
6884 if (statements[statement].op == OP_RETURN || statements[statement].op == OP_DONE)
6885 { //goto leads to return. Copy the command out to remove the goto.
6886 statements[st].op = statements[statement].op;
6887 statements[st].a = statements[statement].a;
6888 statements[st].b = statements[statement].b;
6889 statements[st].c = statements[statement].c;
6890 optres_compound_jumps++;
6893 while (statements[statement].op == OP_GOTO)
6897 QCC_PR_ParseWarning(0, "Infinate loop detected");
6900 statements[st].a = (statement+statements[statement].a - st);
6901 statement = st + (signed)statements[st].a;
6902 optres_compound_jumps++;
6905 if (pr_opcodes[statements[st].op].type_b == NULL)
6907 statement = st + (signed)statements[st].b;
6909 while (statements[statement].op == OP_GOTO)
6913 QCC_PR_ParseWarning(0, "Infinate loop detected");
6916 statements[st].b = (statement+statements[statement].a - st);
6917 statement = st + (signed)statements[st].b;
6918 optres_compound_jumps++;
6921 if (pr_opcodes[statements[st].op].type_c == NULL)
6923 statement = st + (signed)statements[st].c;
6925 while (statements[statement].op == OP_GOTO)
6929 QCC_PR_ParseWarning(0, "Infinate loop detected");
6932 statements[st].c = (statement+statements[statement].a - st);
6933 statement = st + (signed)statements[st].c;
6934 optres_compound_jumps++;
6941 void QCC_CheckForDeadAndMissingReturns(int first, int last, int rettype)
6945 if (statements[last-1].op == OP_DONE)
6946 last--; //don't want the done
6948 if (rettype != ev_void)
6949 if (statements[last-1].op != OP_RETURN)
6951 if (statements[last-1].op != OP_GOTO || (signed)statements[last-1].a > 0)
6953 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
6958 for (st = first; st < last; st++)
6960 if (statements[st].op == OP_RETURN || statements[st].op == OP_GOTO)
6964 continue; //erm... end of function doesn't count as unreachable.
6966 if (!opt_compound_jumps)
6967 { //we can ignore single statements like these without compound jumps (compound jumps correctly removes all).
6968 if (statements[st].op == OP_GOTO) //inefficient compiler, we can ignore this.
6970 if (statements[st].op == OP_DONE) //inefficient compiler, we can ignore this.
6972 if (statements[st].op == OP_RETURN) //inefficient compiler, we can ignore this.
6976 //make sure something goes to just after this return.
6977 for (st2 = first; st2 < last; st2++)
6979 if (pr_opcodes[statements[st2].op].type_a == NULL)
6981 if (st2 + (signed)statements[st2].a == st)
6984 if (pr_opcodes[statements[st2].op].type_b == NULL)
6986 if (st2 + (signed)statements[st2].b == st)
6989 if (pr_opcodes[statements[st2].op].type_c == NULL)
6991 if (st2 + (signed)statements[st2].c == st)
6997 QCC_PR_ParseWarning(WARN_UNREACHABLECODE, "%s: contains unreachable code", pr_scope->name );
7001 if (rettype != ev_void)
7003 if (pr_opcodes[statements[st].op].type_a == NULL)
7005 if (st + (signed)statements[st].a == last)
7007 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
7011 if (pr_opcodes[statements[st].op].type_b == NULL)
7013 if (st + (signed)statements[st].b == last)
7015 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
7019 if (pr_opcodes[statements[st].op].type_c == NULL)
7021 if (st + (signed)statements[st].c == last)
7023 QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
7031 pbool QCC_StatementIsAJump(int stnum, int notifdest) //only the unconditionals.
7033 if (statements[stnum].op == OP_RETURN)
7035 if (statements[stnum].op == OP_DONE)
7037 if (statements[stnum].op == OP_GOTO)
7038 if ((int)statements[stnum].a != notifdest)
7043 int QCC_AStatementJumpsTo(int targ, int first, int last)
7046 for (st = first; st < last; st++)
7048 if (pr_opcodes[statements[st].op].type_a == NULL)
7050 if (st + (signed)statements[st].a == targ && statements[st].a)
7055 if (pr_opcodes[statements[st].op].type_b == NULL)
7057 if (st + (signed)statements[st].b == targ)
7062 if (pr_opcodes[statements[st].op].type_c == NULL)
7064 if (st + (signed)statements[st].c == targ)
7071 for (st = 0; st < num_labels; st++) //assume it's used.
7073 if (pr_labels[st].statementno == targ)
7081 //goes through statements, if it sees a matching statement earlier, it'll strim out the current.
7082 void QCC_CommonSubExpressionRemoval(int first, int last)
7084 int cur; //the current
7085 int prev; //the earlier statement
7086 for (cur = last-1; cur >= first; cur--)
7088 if (pr_opcodes[statements[cur].op].priority == -1)
7090 for (prev = cur-1; prev >= first; prev--)
7092 if (statements[prev].op >= OP_CALL0 && statements[prev].op <= OP_CALL8)
7097 if (statements[prev].op >= OP_CALL1H && statements[prev].op <= OP_CALL8H)
7102 if (pr_opcodes[statements[prev].op].right_associative)
7103 { //make sure no changes to var_a occur.
7104 if (statements[prev].b == statements[cur].a)
7109 if (statements[prev].b == statements[cur].b && !pr_opcodes[statements[cur].op].right_associative)
7117 if (statements[prev].c == statements[cur].a)
7122 if (statements[prev].c == statements[cur].b && !pr_opcodes[statements[cur].op].right_associative)
7129 if (statements[prev].op == statements[cur].op)
7130 if (statements[prev].a == statements[cur].a)
7131 if (statements[prev].b == statements[cur].b)
7132 if (statements[prev].c == statements[cur].c)
7134 if (!QCC_FuncJumpsToRange(first, last, prev, cur))
7136 statements[cur].op = OP_STORE_F;
7137 statements[cur].a = 28;
7138 statements[cur].b = 28;
7139 optres_comexprremoval++;
7150 void QCC_RemapOffsets(unsigned int firststatement, unsigned int laststatement, unsigned int min, unsigned int max, unsigned int newmin)
7152 QCC_dstatement_t *st;
7155 for (i = firststatement, st = &statements[i]; i < laststatement; i++, st++)
7157 if (pr_opcodes[st->op].type_a && st->a >= min && st->a < max)
7158 st->a = st->a - min + newmin;
7159 if (pr_opcodes[st->op].type_b && st->b >= min && st->b < max)
7160 st->b = st->b - min + newmin;
7161 if (pr_opcodes[st->op].type_c && st->c >= min && st->c < max)
7162 st->c = st->c - min + newmin;
7166 void QCC_Marshal_Locals(int first, int laststatement)
7169 unsigned int newofs;
7172 // if (!opt_overlaptemps) //clear these after each function. we arn't overlapping them so why do we need to keep track of them?
7175 // for (t = functemps; t; t = t->next)
7176 // QCC_FreeOffset(t->ofs, t->size);
7177 // functemps = NULL;
7180 if (!pr.localvars) //nothing to marshal
7182 locals_start = numpr_globals;
7183 locals_end = numpr_globals;
7187 if (!opt_locals_marshalling)
7189 pr.localvars = NULL;
7193 //initial backwards bounds.
7194 locals_start = MAX_REGS;
7197 newofs = MAX_REGS; //this is a handy place to put it. :)
7199 //the params need to be in the order that they were allocated
7200 //so we allocate in a backwards order.
7201 for (local = pr.localvars; local; local = local->nextlocal)
7203 if (local->constant)
7206 size = local->type->size*(local->arraysize?local->arraysize:1);
7207 if (local->arraysize)
7213 locals_start = MAX_REGS;
7214 locals_end = newofs;
7217 optres_locals_marshalling+=newofs-MAX_REGS;
7219 for (local = pr.localvars; local; local = local->nextlocal)
7221 if (local->constant)
7224 if (((int*)qcc_pr_globals)[local->ofs])
7225 QCC_PR_ParseError(ERR_INTERNAL, "Marshall of a set value");
7227 size = local->type->size*(local->arraysize?local->arraysize:1);
7228 if (local->arraysize)
7233 QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+size, newofs);
7234 QCC_FreeOffset(local->ofs, size);
7236 local->ofs = newofs;
7240 pr.localvars = NULL;
7244 void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t firstparm)
7256 fprintf(asmfile, "%s(", TypeName(type->aux_type));
7257 p = type->num_parms;
7258 for (o = firstparm, i = 0, type = type->param; i < p; i++, type = type->next)
7261 fprintf(asmfile, ", ");
7263 for (param = pr.localvars; param; param = param->nextlocal)
7265 if (param->ofs == o)
7269 fprintf(asmfile, "%s %s", TypeName(type), param->name);
7271 fprintf(asmfile, "%s", TypeName(type));
7276 fprintf(asmfile, ") %s = asm\n{\n", sc->name);
7278 QCC_fprintfLocals(asmfile, firstparm, o);
7280 for (i = firststatement; i < (unsigned int)numstatements; i++)
7282 fprintf(asmfile, "\t%s", pr_opcodes[statements[i].op].opname);
7283 if (pr_opcodes[statements[i].op].type_a != &type_void)
7285 if (strlen(pr_opcodes[statements[i].op].opname)<6)
7286 fprintf(asmfile, "\t");
7287 if (pr_opcodes[statements[i].op].type_a)
7288 fprintf(asmfile, "\t%s", QCC_VarAtOffset(statements[i].a, (*pr_opcodes[statements[i].op].type_a)->size));
7290 fprintf(asmfile, "\t%i", statements[i].a);
7291 if (pr_opcodes[statements[i].op].type_b != &type_void)
7293 if (pr_opcodes[statements[i].op].type_b)
7294 fprintf(asmfile, ",\t%s", QCC_VarAtOffset(statements[i].b, (*pr_opcodes[statements[i].op].type_b)->size));
7296 fprintf(asmfile, ",\t%i", statements[i].b);
7297 if (pr_opcodes[statements[i].op].type_c != &type_void && pr_opcodes[statements[i].op].associative==ASSOC_LEFT)
7299 if (pr_opcodes[statements[i].op].type_c)
7300 fprintf(asmfile, ",\t%s", QCC_VarAtOffset(statements[i].c, (*pr_opcodes[statements[i].op].type_c)->size));
7302 fprintf(asmfile, ",\t%i", statements[i].c);
7307 if (pr_opcodes[statements[i].op].type_c != &type_void)
7309 if (pr_opcodes[statements[i].op].type_c)
7310 fprintf(asmfile, ",\t%s", QCC_VarAtOffset(statements[i].c, (*pr_opcodes[statements[i].op].type_c)->size));
7312 fprintf(asmfile, ",\t%i", statements[i].c);
7316 fprintf(asmfile, "; /*%i*/\n", statement_linenums[i]);
7319 fprintf(asmfile, "}\n\n");
7325 PR_ParseImmediateStatements
7327 Parse a function body
7330 QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
7334 QCC_def_t *defs[MAX_PARMS+MAX_EXTRA_PARMS], *e2;
7337 pbool needsdone=false;
7338 freeoffset_t *oldfofs;
7342 expandedemptymacro = false;
7345 f = (void *)qccHunkAlloc (sizeof(QCC_function_t));
7348 // check for builtin function definition #1, #2, etc
7350 // hexenC has void name() : 2;
7351 if (QCC_PR_CheckToken ("#") || QCC_PR_CheckToken (":"))
7354 if (pr_token_type == tt_immediate
7355 && pr_immediate_type == type_float
7356 && pr_immediate._float == (int)pr_immediate._float)
7357 binum = (int)pr_immediate._float;
7358 else if (pr_token_type == tt_immediate && pr_immediate_type == type_integer)
7359 binum = pr_immediate._int;
7361 QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
7365 locals_start = locals_end = OFS_PARM0; //hmm...
7368 if (QCC_PR_CheckKeyword(keyword_external, "external"))
7369 { //reacc style builtin
7370 if (pr_token_type != tt_immediate
7371 || pr_immediate_type != type_float
7372 || pr_immediate._float != (int)pr_immediate._float)
7373 QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
7374 f->builtin = (int)-pr_immediate._float;
7378 locals_start = locals_end = OFS_PARM0; //hmm...
7382 if (type->num_parms < 0)
7383 QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
7390 locals_start = locals_end = numpr_globals;
7396 for (i=0 ; i<type->num_parms ; i++)
7398 if (!*pr_parm_names[i])
7399 QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named");
7400 defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 0, false);
7402 defs[i]->references++;
7405 f->parm_ofs[i] = defs[i]->ofs;
7406 if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i-1])
7407 QCC_Error (ERR_BADPARAMORDER, "bad parm order");
7408 if (i > 0 && f->parm_ofs[i] != f->parm_ofs[i-1]+defs[i-1]->type->size)
7409 QCC_Error (ERR_BADPARAMORDER, "parms not packed");
7414 if (type->num_parms)
7415 locals_start = locals_end = defs[0]->ofs;
7419 f->code = numstatements;
7421 if (type->num_parms > MAX_PARMS)
7423 for (i = MAX_PARMS; i < type->num_parms; i++)
7425 if (!extra_parms[i - MAX_PARMS])
7427 e2 = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t));
7428 e2->name = "extra parm";
7429 e2->ofs = QCC_GetFreeOffsetSpace(3);
7430 extra_parms[i - MAX_PARMS] = e2;
7432 extra_parms[i - MAX_PARMS]->type = defs[i]->type;
7433 if (defs[i]->type->type != ev_vector)
7434 QCC_PR_Statement (&pr_opcodes[OP_STORE_F], extra_parms[i - MAX_PARMS], defs[i], NULL);
7436 QCC_PR_Statement (&pr_opcodes[OP_STORE_V], extra_parms[i - MAX_PARMS], defs[i], NULL);
7440 QCC_RemapLockedTemps(-1, -1);
7445 e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 0);
7446 e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 0);
7447 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), e, NULL));
7451 // check for a state opcode
7453 if (QCC_PR_CheckToken ("["))
7454 QCC_PR_ParseState ();
7456 if (QCC_PR_CheckKeyword (keyword_asm, "asm"))
7458 QCC_PR_Expect ("{");
7459 while (!QCC_PR_CheckToken("}"))
7464 if (QCC_PR_CheckKeyword (keyword_var, "var")) //reacc support
7465 { //parse lots of locals
7468 name = QCC_PR_ParseName();
7470 e2 = QCC_PR_GetDef(QCC_PR_ParseType(false, false), name, pr_scope, true, 0, false);
7472 } while(!QCC_PR_CheckToken("{"));
7475 QCC_PR_Expect ("{");
7477 // parse regular statements
7479 while (!QCC_PR_CheckToken("}"))
7481 QCC_PR_ParseStatement ();
7488 // if (type->aux_type->type)
7489 // if (statements[numstatements - 1].op != OP_RETURN)
7490 // QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name );
7492 if (f->code == numstatements)
7494 else if (statements[numstatements - 1].op != OP_RETURN && statements[numstatements - 1].op != OP_DONE)
7500 for (i = 0; i < num_gotos; i++)
7502 for (j = 0; j < num_labels; j++)
7504 if (!strcmp(pr_gotos[i].name, pr_labels[j].name))
7506 if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_a)
7507 statements[pr_gotos[i].statementno].a += pr_labels[j].statementno - pr_gotos[i].statementno;
7508 else if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_b)
7509 statements[pr_gotos[i].statementno].b += pr_labels[j].statementno - pr_gotos[i].statementno;
7511 statements[pr_gotos[i].statementno].c += pr_labels[j].statementno - pr_gotos[i].statementno;
7515 if (j == num_labels)
7518 QCC_PR_ParseError(ERR_NOLABEL, "Goto statement with no matching label \"%s\"", pr_gotos[i].name);
7524 if (opt_return_only && !needsdone)
7525 needsdone = QCC_FuncJumpsTo(f->code, numstatements, numstatements);
7527 // emit an end of statements opcode
7528 if (!opt_return_only || needsdone)
7533 e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0);
7534 e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0);
7535 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL));
7538 QCC_PR_Statement (pr_opcodes, 0,0, NULL);
7541 optres_return_only++;
7543 QCC_CheckForDeadAndMissingReturns(f->code, numstatements, type->aux_type->type);
7545 if (opt_compound_jumps)
7546 QCC_CompoundJumps(f->code, numstatements);
7547 // if (opt_comexprremoval)
7548 // QCC_CommonSubExpressionRemoval(f->code, numstatements);
7551 QCC_RemapLockedTemps(f->code, numstatements);
7552 locals_end = numpr_globals;
7554 QCC_WriteAsmFunction(pr_scope, f->code, locals_start);
7556 QCC_Marshal_Locals(f->code, numstatements);
7565 QCC_PR_ParseError(ERR_ILLEGALCONTINUES, "%s: function contains illegal continues", pr_scope->name);
7570 QCC_PR_ParseError(ERR_ILLEGALBREAKS, "%s: function contains illegal breaks", pr_scope->name);
7575 QCC_PR_ParseError(ERR_ILLEGALCASES, "%s: function contains illegal cases", pr_scope->name);
7581 void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int min, int max)
7583 QCC_dstatement_t *st;
7585 if (min == max || min+1 == max)
7587 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL);
7588 QCC_UnFreeTemp(index);
7589 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7591 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7592 st->a = array->ofs + min*array->type->size;
7596 int mid = min + (max-min)/2;
7600 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL);
7601 QCC_UnFreeTemp(index);
7602 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7606 QCC_PR_ArrayRecurseDivideRegular(array, index, min, mid);
7608 st->b = numstatements - (st-statements);
7609 QCC_PR_ArrayRecurseDivideRegular(array, index, mid, max);
7613 //the idea here is that we return a vector, the caller then figures out the extra 3rd.
7614 //This is useful when we have a load of indexes.
7615 void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, int min, int max)
7617 QCC_dstatement_t *st;
7619 if (min == max || min+1 == max)
7621 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL);
7622 QCC_UnFreeTemp(index);
7623 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7625 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7626 st->a = array->ofs + min*3;
7630 int mid = min + (max-min)/2;
7634 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL);
7635 QCC_UnFreeTemp(index);
7636 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7640 QCC_PR_ArrayRecurseDivideUsingVectors(array, index, min, mid);
7642 st->b = numstatements - (st-statements);
7643 QCC_PR_ArrayRecurseDivideUsingVectors(array, index, mid, max);
7647 //returns a vector overlapping the result needed.
7648 QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array)
7650 QCC_dfunction_t *df;
7651 QCC_def_t *temp, *index, *func;
7653 func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 0, false);
7657 if (numfunctions >= MAX_FUNCTIONS)
7658 QCC_Error(ERR_INTERNAL, "Too many function defs");
7660 df = &functions[numfunctions];
7664 df->s_name = QCC_CopyString(func->name);
7665 df->first_statement = numstatements;
7666 df->parm_size[0] = 1;
7668 df->parm_start = numpr_globals;
7669 index = QCC_PR_GetDef(type_float, "index___", func, true, 0, false);
7670 index->references++;
7671 temp = QCC_PR_GetDef(type_float, "div3___", func, true, 0, false);
7672 locals_end = numpr_globals;
7673 df->locals = locals_end - df->parm_start;
7674 QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatConst(3), temp, false);
7675 QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, temp, temp, temp, false);//round down to int
7677 QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3); //round up
7679 QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL); //err... we didn't find it, give up.
7680 QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); //err... we didn't find it, give up.
7682 G_FUNCTION(func->ofs) = df - functions;
7683 func->initialized = 1;
7687 void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
7689 QCC_def_t *vectortrick;
7690 QCC_dfunction_t *df;
7691 QCC_def_t *def, *index;
7693 QCC_dstatement_t *st;
7696 QCC_def_t *fasttrackpossible;
7698 if (flag_fasttrackarrays)
7699 fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
7701 fasttrackpossible = NULL;
7703 def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
7705 if (def->arraysize >= 15 && def->type->size == 1)
7707 vectortrick = QCC_PR_EmitArrayGetVector(def);
7714 if (numfunctions >= MAX_FUNCTIONS)
7715 QCC_Error(ERR_INTERNAL, "Too many function defs");
7717 df = &functions[numfunctions];
7721 df->s_name = QCC_CopyString(scope->name);
7722 df->first_statement = numstatements;
7723 df->parm_size[0] = 1;
7725 df->parm_start = numpr_globals;
7726 index = QCC_PR_GetDef(type_float, "indexg___", def, true, 0, false);
7728 G_FUNCTION(scope->ofs) = df - functions;
7730 if (fasttrackpossible)
7732 QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, fasttrackpossible, NULL, &st);
7733 //fetch_gbl takes: (float size, variant array[]), float index, variant pos
7734 //note that the array size is coded into the globals, one index before the array.
7736 if (def->type->size >= 3)
7737 QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_V], def, index, &def_ret, true);
7739 QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_F], def, index, &def_ret, true);
7741 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_RETURN], &def_ret, NULL, NULL));
7744 st->b = &statements[numstatements] - st;
7749 QCC_def_t *div3, *intdiv3, *ret;
7751 //okay, we've got a function to retrieve the var as part of a vector.
7752 //we need to work out which part, x/y/z that it's stored in.
7753 //0,1,2 = i - ((int)i/3 *) 3;
7755 div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 0, false);
7756 intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 0, false);
7758 eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatConst((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule!
7759 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7761 QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, &st);
7764 QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
7765 QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatConst(3), div3, false);
7766 QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, div3, div3, intdiv3, false);
7768 QCC_PR_Statement3(pr_opcodes+OP_STORE_F, index, &def_parms[0], NULL, false);
7769 QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, NULL, false);
7770 vectortrick->references++;
7771 ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 0, false);
7773 QCC_PR_Statement3(pr_opcodes+OP_STORE_V, &def_ret, ret, NULL, false);
7774 QCC_FreeTemp(&def_ret);
7776 div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatConst(3), NULL);
7777 QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false);
7780 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(0+0.5f), NULL);
7781 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7783 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7784 st->a = ret->ofs + 0;
7786 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(1+0.5f), NULL);
7787 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7789 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7790 st->a = ret->ofs + 1;
7792 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(2+0.5), NULL);
7793 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7795 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7796 st->a = ret->ofs + 2;
7798 QCC_FreeTemp(index);
7802 QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
7803 QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize);
7806 QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL);
7808 QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
7810 locals_end = numpr_globals;
7811 df->locals = locals_end - df->parm_start;
7814 QCC_WriteAsmFunction(pr_scope, df->first_statement, df->parm_start);
7819 void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t *value, int min, int max)
7821 QCC_dstatement_t *st;
7823 if (min == max || min+1 == max)
7825 eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatConst((float)min), NULL);
7826 QCC_UnFreeTemp(index);
7827 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7829 if (array->type->size == 3)
7830 QCC_PR_Statement(pr_opcodes+OP_STORE_V, value, array, &st);
7832 QCC_PR_Statement(pr_opcodes+OP_STORE_F, value, array, &st);
7833 st->b = array->ofs + min*array->type->size;
7834 QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
7838 int mid = min + (max-min)/2;
7842 eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst((float)mid), NULL);
7843 QCC_UnFreeTemp(index);
7844 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
7848 QCC_PR_ArraySetRecurseDivide(array, index, value, min, mid);
7850 st->b = numstatements - (st-statements);
7851 QCC_PR_ArraySetRecurseDivide(array, index, value, mid, max);
7855 void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
7857 QCC_dfunction_t *df;
7858 QCC_def_t *def, *index, *value;
7860 QCC_def_t *fasttrackpossible;
7862 if (flag_fasttrackarrays)
7863 fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
7865 fasttrackpossible = NULL;
7867 def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
7870 if (numfunctions >= MAX_FUNCTIONS)
7871 QCC_Error(ERR_INTERNAL, "Too many function defs");
7873 df = &functions[numfunctions];
7877 df->s_name = QCC_CopyString(scope->name);
7878 df->first_statement = numstatements;
7879 df->parm_size[0] = 1;
7880 df->parm_size[1] = def->type->size;
7882 df->parm_start = numpr_globals;
7883 index = QCC_PR_GetDef(type_float, "indexs___", def, true, 0, false);
7884 value = QCC_PR_GetDef(def->type, "value___", def, true, 0, false);
7885 locals_end = numpr_globals;
7886 df->locals = locals_end - df->parm_start;
7888 G_FUNCTION(scope->ofs) = df - functions;
7890 if (fasttrackpossible)
7892 QCC_dstatement_t *st;
7894 QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, fasttrackpossible, NULL, &st);
7895 //note that the array size is coded into the globals, one index before the array.
7897 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
7898 QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1]+1, 0, true);//annoy the programmer. :p
7899 if (def->type->size != 1)//shift it upwards for larger types
7900 QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntConst(def->type->size), index, true);
7901 QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], def, index, index, true); //comes with built in add
7902 if (def->type->size >= 3)
7903 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_V], value, index, NULL, true); //*b = a
7905 QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], value, index, NULL, true);
7906 QCC_PR_Statement(&pr_opcodes[OP_RETURN], value, NULL, NULL);
7909 st->b = &statements[numstatements] - st;
7912 QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
7913 QCC_PR_ArraySetRecurseDivide(def, index, value, 0, def->arraysize);
7915 QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
7919 QCC_WriteAsmFunction(pr_scope, df->first_statement, df->parm_start);
7924 //register a def, and all of it's sub parts.
7925 //only the main def is of use to the compiler.
7926 //the subparts are emitted to the compiler and allow correct saving/loading
7927 //be careful with fields, this doesn't allocated space, so will it allocate fields. It only creates defs at specified offsets.
7928 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)
7933 QCC_def_t *def, *first=NULL;
7935 #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;}
7945 if (type->type != ev_function)
7950 if (qcc_targetformat != QCF_HEXEN2)
7951 KEYWORD(float); //hmm... hexen2 requires this...
7958 for (a = 0; a < (arraysize?arraysize:1); a++)
7963 sprintf(array, "[%i]", a);
7966 sprintf(newname, "%s%s", name, array);
7970 // allocate a new def
7971 def = (void *)qccHunkAlloc (sizeof(QCC_def_t));
7972 memset (def, 0, sizeof(*def));
7974 def->arraysize = a?0:arraysize;
7977 pr.def_tail->next = def;
7984 def->s_line = pr_source_line;
7985 def->s_file = s_file;
7987 def->initialized = 1;
7989 def->name = (void *)qccHunkAlloc (strlen(newname)+1);
7990 strcpy (def->name, newname);
7996 //if (type->type = ev_field)
7997 def->constant = true;
7999 if (ofs + type->size*a >= MAX_REGS)
8000 QCC_Error(ERR_TOOMANYGLOBALS, "MAX_REGS is too small");
8001 def->ofs = ofs + type->size*a;
8005 // printf("Emited %s\n", newname);
8007 if (type->type == ev_struct)
8010 QCC_type_t *parttype;
8011 parttype = type->param;
8012 for (partnum = 0; partnum < type->num_parms; partnum++)
8014 switch (parttype->type)
8017 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8018 QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved);
8020 sprintf(newname, "%s%s.%s_x", name, array, parttype->name);
8021 QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, false);
8022 sprintf(newname, "%s%s.%s_y", name, array, parttype->name);
8023 QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+1, false, false);
8024 sprintf(newname, "%s%s.%s_z", name, array, parttype->name);
8025 QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+2, false, false);
8036 case ev_variant: //for lack of any better alternative
8037 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8038 QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved);
8042 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8043 QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true;
8048 parttype=parttype->next;
8051 else if (type->type == ev_vector)
8052 { //do the vector thing.
8053 sprintf(newname, "%s%s_x", name, array);
8054 QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+0, referable, false);
8055 sprintf(newname, "%s%s_y", name, array);
8056 QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+1, referable, false);
8057 sprintf(newname, "%s%s_z", name, array);
8058 QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+2, referable, false);
8060 else if (type->type == ev_field)
8062 if (type->aux_type->type == ev_vector)
8064 //do the vector thing.
8065 sprintf(newname, "%s%s_x", name, array);
8066 QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+0, referable, false);
8067 sprintf(newname, "%s%s_y", name, array);
8068 QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+1, referable, false);
8069 sprintf(newname, "%s%s_z", name, array);
8070 QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+2, referable, false);
8073 first->deftail = pr.def_tail;
8078 if (!pHash_Get(&globalstable, "end_sys_fields"))
8079 first->references++; //anything above needs to be left in, and so warning about not using it is just going to pee people off.
8080 if (!arraysize && first->type->type != ev_field)
8081 first->constant = false;
8083 pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
8085 pHash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
8087 if (!scope && asmfile)
8088 fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name);
8098 If type is NULL, it will match any type
8099 If allocate is true, a new def will be allocated if it can't be found
8100 If arraysize=0, its not an array and has 1 element.
8101 If arraysize>0, its an array and requires array notation
8102 If arraysize<0, its an array with undefined size - GetDef will fail if its not already allocated.
8106 QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool allocate, int arraysize, pbool saved)
8110 // char element[MAX_NAME];
8112 QCC_def_t *foundstatic = NULL;
8119 def = Hash_Get(&localstable, name);
8123 if ( def->scope && def->scope != scope)
8125 def = Hash_GetNext(&localstable, name, def);
8126 continue; // in a different function
8129 if (type && typecmp(def->type, type))
8130 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8131 if (def->arraysize != arraysize && arraysize>=0)
8132 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
8133 if (allocate && scope)
8135 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8136 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8138 // QCC_PR_ParsePrintDef(def);
8145 def = Hash_Get(&globalstable, name);
8149 if ( def->scope && def->scope != scope)
8151 def = Hash_GetNext(&globalstable, name, def);
8152 continue; // in a different function
8155 if (def->isstatic && def->s_file != s_file)
8156 { //warn? or would that be pointless?
8158 def = Hash_GetNext(&globalstable, name, def);
8159 continue; // in a different function
8162 if (type && typecmp(def->type, type))
8165 QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8167 if (def->arraysize != arraysize && arraysize>=0)
8168 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
8169 if (allocate && scope)
8172 { //warn? or would that be pointless?
8173 def = Hash_GetNext(&globalstable, name, def);
8174 continue; // in a different function
8177 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8178 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8180 // QCC_PR_ParsePrintDef(def);
8185 if (pHash_Get != &Hash_Get && !allocate) //do we want to try case insensative too?
8189 def = pHash_Get(&localstable, name);
8193 if ( def->scope && def->scope != scope)
8195 def = pHash_GetNext(&localstable, name, def);
8196 continue; // in a different function
8199 if (type && typecmp(def->type, type))
8200 QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8201 if (def->arraysize != arraysize && arraysize>=0)
8202 QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
8203 if (allocate && scope)
8205 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8206 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8208 // QCC_PR_ParsePrintDef(def);
8215 def = pHash_Get(&globalstable, name);
8219 if ( def->scope && def->scope != scope)
8221 def = pHash_GetNext(&globalstable, name, def);
8222 continue; // in a different function
8225 if (def->isstatic && def->s_file != s_file)
8226 { //warn? or would that be pointless?
8228 def = Hash_GetNext(&globalstable, name, def);
8229 continue; // in a different function
8232 if (type && typecmp(def->type, type))
8235 QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
8237 if (def->arraysize != arraysize && arraysize>=0)
8238 QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
8239 if (allocate && scope)
8242 { //warn? or would that be pointless?
8243 def = pHash_GetNext(&globalstable, name, def);
8244 continue; // in a different function
8247 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
8248 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
8250 // QCC_PR_ParsePrintDef(def);
8256 if (foundstatic && !allocate)
8258 QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s defined static", name);
8259 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, foundstatic);
8267 QCC_PR_ParseError (ERR_ARRAYNEEDSSIZE, "First declaration of array %s with no size",name);
8272 if (QCC_PR_GetDef(type, name, NULL, false, arraysize, false))
8273 QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL, "Local \"%s\" defined with name of a global", name);
8276 ofs = numpr_globals;
8278 { //write the array size
8279 ofs = QCC_GetFreeOffsetSpace(1 + (type->size * arraysize));
8281 ((int *)qcc_pr_globals)[ofs] = arraysize-1; //An array needs the size written first. This is a hexen2 opcode thing.
8285 ofs = QCC_GetFreeOffsetSpace(type->size);
8287 def = QCC_PR_DummyDef(type, name, scope, arraysize, ofs, true, saved);
8290 if (type->type == ev_field && allocate != 2)
8292 for (i = 0; i < type->size*(arraysize?arraysize:1); i++) //make arrays of fields work.
8293 *(int *)&qcc_pr_globals[def->ofs+i] = pr.size_fields+i;
8295 pr.size_fields += i;
8300 def->nextlocal = pr.localvars;
8307 QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int *fieldofs, pbool saved)
8312 QCC_def_t *def, *first=NULL;
8313 unsigned int maxfield, startfield;
8316 startfield = *fieldofs;
8317 maxfield = startfield;
8319 for (a = 0; a < (arraysize?arraysize:1); a++)
8324 sprintf(array, "[%i]", a);
8328 sprintf(newname, "%s%s", name, array);
8330 // allocate a new def
8331 def = (void *)qccHunkAlloc (sizeof(QCC_def_t));
8332 memset (def, 0, sizeof(*def));
8334 def->arraysize = arraysize;
8336 pr.def_tail->next = def;
8339 def->s_line = pr_source_line;
8340 def->s_file = s_file;
8342 def->name = (void *)qccHunkAlloc (strlen(newname)+1);
8343 strcpy (def->name, newname);
8348 def->ofs = QCC_GetFreeOffsetSpace(1);
8349 ((int *)qcc_pr_globals)[def->ofs] = *fieldofs;
8359 // printf("Emited %s\n", newname);
8361 if ((type)->type == ev_struct||(type)->type == ev_union)
8364 QCC_type_t *parttype;
8367 parttype = (type)->param;
8368 isunion = ((type)->type == ev_union);
8369 for (partnum = 0, parms = (type)->num_parms; partnum < parms; partnum++)
8371 switch (parttype->type)
8376 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8378 sprintf(newname, "%s%s", parttype->name, array);
8379 def = QCC_PR_DummyFieldDef(parttype, newname, scope, 1, fieldofs, saved);
8390 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8392 sprintf(newname, "%s%s", parttype->name, array);
8393 ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false);
8394 ftype->aux_type = parttype;
8395 if (parttype->type == ev_vector)
8396 ftype->size = parttype->size; //vector fields create a _y and _z too, so we need this still.
8397 def = QCC_PR_GetDef(NULL, newname, scope, false, 0, saved);
8400 def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
8404 QCC_PR_ParseWarning(WARN_CONFLICTINGUNIONMEMBER, "conflicting offsets for union/struct expansion of %s. Ignoring new def.", newname);
8405 QCC_PR_ParsePrintDef(WARN_CONFLICTINGUNIONMEMBER, def);
8411 sprintf(newname, "%s%s.%s", name, array, parttype->name);
8413 sprintf(newname, "%s%s", parttype->name, array);
8414 ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false);
8415 ftype->aux_type = parttype;
8416 def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
8417 def->initialized = true;
8418 ((int *)qcc_pr_globals)[def->ofs] = *fieldofs;
8419 *fieldofs += parttype->size;
8424 if (*fieldofs > maxfield)
8425 maxfield = *fieldofs;
8427 *fieldofs = startfield;
8430 parttype=parttype->next;
8435 *fieldofs = maxfield; //final size of the union.
8441 void QCC_PR_ExpandUnionToFields(QCC_type_t *type, int *fields)
8443 QCC_type_t *pass = type->aux_type;
8444 QCC_PR_DummyFieldDef(pass, "", pr_scope, 1, fields, true);
8448 void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type, int offset)
8455 //arrays go recursive
8457 for (i = 0; i < arraysize; i++)
8459 QCC_PR_ParseInitializerType(0, def, type, offset + i*type->size);
8460 if (!QCC_PR_CheckToken(","))
8467 if (type->type == ev_function && pr_token_type == tt_punct)
8469 /*begin function special case*/
8470 QCC_def_t *parentfunc = pr_scope;
8472 QCC_dfunction_t *df;
8479 if (QCC_PR_CheckToken ("#") || QCC_PR_CheckToken (":"))
8482 if (pr_token_type == tt_immediate
8483 && pr_immediate_type == type_float
8484 && pr_immediate._float == (int)pr_immediate._float)
8485 binum = (int)pr_immediate._float;
8486 else if (pr_token_type == tt_immediate && pr_immediate_type == type_integer)
8487 binum = pr_immediate._int;
8489 QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
8492 if (def->initialized)
8493 for (i = 0; i < numfunctions; i++)
8495 if (functions[i].first_statement == -binum)
8497 tmp = QCC_MakeIntConst(i);
8504 f = (void *)qccHunkAlloc (sizeof(QCC_function_t));
8507 locals_start = locals_end = OFS_PARM0; //hmm...
8513 f = QCC_PR_ParseImmediateStatements (type);
8516 pr_scope = parentfunc;
8517 tmp = QCC_MakeIntConst(numfunctions);
8520 if (numfunctions >= MAX_FUNCTIONS)
8521 QCC_Error(ERR_INTERNAL, "Too many function defs");
8523 // fill in the dfunction
8524 df = &functions[numfunctions];
8527 df->first_statement = -f->builtin;
8529 df->first_statement = f->code;
8531 if (f->builtin && opt_function_names)
8532 optres_function_names += strlen(f->def->name);
8534 df->s_name = QCC_CopyString (f->def->name);
8535 df->s_file = s_file2;
8536 df->numparms = f->def->type->num_parms;
8537 df->locals = locals_end - locals_start;
8538 df->parm_start = locals_start;
8539 for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
8541 df->parm_size[i] = parm->size;
8543 /*end function special case*/
8546 else if (type->type == ev_string && QCC_PR_CheckName("_"))
8550 if (pr_token_type != tt_immediate || pr_immediate_type->type != ev_string)
8551 QCC_PR_ParseError(0, "_() intrinsic accepts only a string immediate");
8552 tmp = QCC_MakeStringConst(pr_immediate_string);
8556 if (!pr_scope || def->constant)
8559 sprintf(trname, "dotranslate_%i", ++dotranslate_count);
8560 dt = QCC_PR_DummyDef(type_string, trname, pr_scope, 0, offset, true, true);
8563 dt->initialized = 1;
8566 else if (type->type == ev_struct || type->type == ev_union)
8568 //structs go recursive
8569 QCC_type_t *parttype;
8575 isunion = ((type)->type == ev_union);
8576 for (partnum = 0, parttype = (type)->param, parms = (type)->num_parms; partnum < parms; partnum++, parttype = parttype->next)
8578 QCC_PR_ParseInitializerType(parttype->arraysize, def, parttype, offset + parttype->ofs);
8579 if (isunion || !QCC_PR_CheckToken(","))
8587 tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
8588 if (typecmp(type, tmp->type))
8590 /*you can cast from const 0 to anything*/
8591 if (tmp->type->size == type->size && (tmp->type->type == ev_integer || tmp->type->type == ev_float) && tmp->constant && !G_INT(tmp->ofs))
8594 /*cast from int->float will convert*/
8595 else if (type->type == ev_float && tmp->type->type == ev_integer)
8596 tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], tmp, 0, NULL);
8597 /*cast from float->int will convert*/
8598 else if (type->type == ev_integer && tmp->type->type == ev_float)
8599 tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], tmp, 0, NULL);
8601 QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "wrong initializer type");
8605 if (!pr_scope || def->constant)
8608 QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "initializer is not constant");
8610 if (def->initialized)
8612 for (i = 0; (unsigned)i < type->size; i++)
8613 if (G_INT(offset+i) != G_INT(tmp->ofs+i))
8614 QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "incompatible redeclaration");
8618 for (i = 0; (unsigned)i < type->size; i++)
8619 G_INT(offset+i) = G_INT(tmp->ofs+i);
8625 if (def->initialized)
8626 QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s initialised twice", def->name);
8628 memset(&lhs, 0, sizeof(lhs));
8629 memset(&rhs, 0, sizeof(rhs));
8631 for (i = 0; (unsigned)i < type->size; )
8633 rhs.type = lhs.type = type_float;
8636 rhs.ofs = tmp->ofs+i;
8638 if (type->size - i >= 3)
8640 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &rhs, &lhs, NULL));
8645 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &rhs, &lhs, NULL));
8654 void QCC_PR_ParseInitializerDef(QCC_def_t *def, pbool isvar, pbool isconst)
8656 def->constant = (isconst || (!isvar && !pr_scope));
8657 QCC_PR_ParseInitializerType(def->arraysize, def, def->type, def->ofs);
8658 if (!def->initialized)
8659 def->initialized = 1;
8662 int accglobalsblock; //0 = error, 1 = var, 2 = function, 3 = objdata
8667 Called at the outer layer and when a local statement is hit
8670 void QCC_PR_ParseDefs (char *classname)
8673 QCC_type_t *type, *parm;
8676 QCC_dfunction_t *df;
8677 int i = 0; // warning:
\91i
\92 may be used uninitialized in this function
8679 pbool isstatic=defaultstatic;
8680 pbool externfnc=false;
8681 pbool isconstant = false;
8682 pbool isvar = false;
8683 pbool noref = defaultnoref;
8684 pbool nosave = false;
8685 pbool allocatenew = true;
8686 pbool inlinefunction = false;
8690 while (QCC_PR_CheckToken(";"))
8693 if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
8695 if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int"))
8703 name = QCC_PR_ParseName();
8704 if (QCC_PR_CheckToken("="))
8706 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_integer)
8708 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8712 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name);
8714 iv = G_INT(def->ofs);
8717 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number");
8721 iv = pr_immediate._int;
8725 def = QCC_MakeIntConst(iv);
8726 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8729 if (QCC_PR_CheckToken("}"))
8732 if (QCC_PR_CheckToken("}"))
8733 break; // accept trailing comma
8739 QCC_PR_CheckKeyword(keyword_float, "float");
8745 name = QCC_PR_ParseName();
8746 if (QCC_PR_CheckToken("="))
8748 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float)
8750 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8754 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name);
8756 fv = G_FLOAT(def->ofs);
8759 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number");
8763 fv = pr_immediate._float;
8767 def = QCC_MakeFloatConst(fv);
8768 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8771 if (QCC_PR_CheckToken("}"))
8774 if (QCC_PR_CheckToken("}"))
8775 break; // accept trailing comma
8782 if (QCC_PR_CheckKeyword(keyword_enumflags, "enumflags"))
8786 if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int"))
8794 name = QCC_PR_ParseName();
8795 if (QCC_PR_CheckToken("="))
8797 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_integer)
8799 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8803 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name);
8805 iv = G_INT(def->ofs);
8808 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number");
8812 iv = pr_immediate._int;
8820 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", iv);
8825 if (((i>>1)<<1) != i)
8830 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)iv);
8833 def = QCC_MakeIntConst(iv);
8834 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8838 if (QCC_PR_CheckToken("}"))
8846 QCC_PR_CheckKeyword(keyword_float, "float");
8853 name = QCC_PR_ParseName();
8854 if (QCC_PR_CheckToken("="))
8856 if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float)
8858 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false);
8862 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name);
8864 fv = G_FLOAT(def->ofs);
8867 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number");
8871 fv = pr_immediate._float;
8879 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", fv);
8884 if (((i>>1)<<1) != i)
8889 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)fv);
8892 def = QCC_MakeFloatConst(fv);
8893 pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t)));
8897 if (QCC_PR_CheckToken("}"))
8906 if (QCC_PR_CheckKeyword (keyword_typedef, "typedef"))
8908 type = QCC_PR_ParseType(true, false);
8911 QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens");
8913 type->name = QCC_CopyString(pr_token)+strings;
8914 type->typedefed = true;
8923 if (QCC_PR_CheckKeyword (keyword_codesys, "CodeSys")) //reacc support.
8926 QCC_PR_ParseError(ERR_BADEXTENSION, "progs crc was already specified - only one is allowed");
8927 ForcedCRC = (int)pr_immediate._float;
8934 if (QCC_PR_CheckKeyword (keyword_var, "var")) //reacc support.
8936 if (accglobalsblock == 3)
8938 if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
8939 QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false);
8943 if (QCC_PR_CheckToken(":"))
8944 accglobalsblock = 1;
8949 if (QCC_PR_CheckKeyword (keyword_function, "function")) //reacc support.
8951 accglobalsblock = 2;
8953 if (QCC_PR_CheckKeyword (keyword_objdata, "objdata")) //reacc support.
8955 if (accglobalsblock == 3)
8957 if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false))
8958 QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false);
8961 if (!QCC_PR_GetDef(type_void, "end_sys_globals", NULL, false, 0, false))
8962 QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 0, false);
8963 accglobalsblock = 3;
8968 switch(accglobalsblock)//reacc support.
8972 char *oldp = pr_file_p;
8973 name = QCC_PR_ParseName();
8974 if (!QCC_PR_CheckToken(":")) //nope, it wasn't!
8976 QCC_PR_IncludeChunk(name, true, NULL);
8982 if (QCC_PR_CheckKeyword(keyword_object, "object"))
8983 QCC_PR_GetDef(type_entity, name, NULL, true, 0, true);
8984 else if (QCC_PR_CheckKeyword(keyword_string, "string"))
8985 QCC_PR_GetDef(type_string, name, NULL, true, 0, true);
8986 else if (QCC_PR_CheckKeyword(keyword_real, "real"))
8988 def = QCC_PR_GetDef(type_float, name, NULL, true, 0, true);
8989 if (QCC_PR_CheckToken("="))
8991 G_FLOAT(def->ofs) = pr_immediate._float;
8995 else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
8997 def = QCC_PR_GetDef(type_vector, name, NULL, true, 0, true);
8998 if (QCC_PR_CheckToken("="))
9001 G_FLOAT(def->ofs+0) = pr_immediate._float;
9003 G_FLOAT(def->ofs+1) = pr_immediate._float;
9005 G_FLOAT(def->ofs+2) = pr_immediate._float;
9010 else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
9011 QCC_PR_GetDef(type_function, name, NULL, true, 0, true);
9013 QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
9014 QCC_PR_Expect (";");
9016 if (QCC_PR_CheckKeyword (keyword_system, "system"))
9017 QCC_PR_Expect (";");
9021 name = QCC_PR_ParseName();
9022 QCC_PR_GetDef(type_function, name, NULL, true, 1, true);
9023 QCC_PR_CheckToken (";");
9027 char *oldp = pr_file_p;
9028 name = QCC_PR_ParseName();
9029 if (!QCC_PR_CheckToken(":")) //nope, it wasn't!
9031 QCC_PR_IncludeChunk(name, true, NULL);
9037 if (QCC_PR_CheckKeyword(keyword_object, "object"))
9038 QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 0, true);
9039 else if (QCC_PR_CheckKeyword(keyword_string, "string"))
9040 QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 0, true);
9041 else if (QCC_PR_CheckKeyword(keyword_real, "real"))
9042 QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 0, true);
9043 else if (QCC_PR_CheckKeyword(keyword_vector, "vector"))
9044 QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 0, true);
9045 else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc"))
9046 QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 0, true);
9048 QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
9049 QCC_PR_Expect (";");
9056 if (QCC_PR_CheckKeyword(keyword_extern, "extern"))
9058 else if (QCC_PR_CheckKeyword(keyword_shared, "shared"))
9062 QCC_PR_ParseError (ERR_NOSHAREDLOCALS, "Cannot have shared locals");
9064 else if (QCC_PR_CheckKeyword(keyword_const, "const"))
9066 else if (QCC_PR_CheckKeyword(keyword_var, "var"))
9068 else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "static"))
9070 else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "nonstatic"))
9072 else if (QCC_PR_CheckKeyword(keyword_noref, "noref"))
9074 else if (QCC_PR_CheckKeyword(keyword_nosave, "nosave"))
9080 type = QCC_PR_ParseType (false, false);
9081 if (type == NULL) //ignore
9084 inlinefunction = type_inlinefunction;
9086 if (externfnc && type->type != ev_function)
9088 printf ("Only functions may be defined as external (yet)\n");
9092 if (!pr_scope && QCC_PR_CheckKeyword(keyword_function, "function")) //reacc support.
9094 name = QCC_PR_ParseName ();
9096 type = QCC_PR_ParseFunctionTypeReacc(false, type);
9098 def = QCC_PR_GetDef (type, name, NULL, true, 0, false);
9101 { //ignore the code and stuff
9103 if (QCC_PR_CheckKeyword(keyword_external, "external"))
9112 while (!QCC_PR_CheckToken("{")) //skip over the locals.
9114 if (pr_token_type == tt_eof)
9116 QCC_PR_ParseError(0, "Unexpected EOF");
9122 //balance out the { and }
9125 if (pr_token_type == tt_eof)
9127 if (QCC_PR_CheckToken("{"))
9129 else if (QCC_PR_CheckToken("}"))
9132 QCC_PR_Lex(); //ignore it.
9141 f = QCC_PR_ParseImmediateStatements (type);
9143 def->initialized = 1;
9144 def->isstatic = isstatic;
9145 G_FUNCTION(def->ofs) = numfunctions;
9148 // PR_PrintFunction (def);
9150 if (numfunctions >= MAX_FUNCTIONS)
9151 QCC_Error(ERR_INTERNAL, "Too many function defs");
9153 // fill in the dfunction
9154 df = &functions[numfunctions];
9157 df->first_statement = -f->builtin;
9159 df->first_statement = f->code;
9161 if (f->builtin && opt_function_names)
9162 optres_function_names += strlen(f->def->name);
9164 df->s_name = QCC_CopyString (f->def->name);
9165 df->s_file = s_file2;
9166 df->numparms = f->def->type->num_parms;
9167 df->locals = locals_end - locals_start;
9168 df->parm_start = locals_start;
9169 for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
9171 df->parm_size[i] = parm->size;
9177 // if (pr_scope && (type->type == ev_field) )
9178 // QCC_PR_ParseError ("Fields must be global");
9182 if (QCC_PR_CheckToken (";"))
9184 if (type->type == ev_field && (type->aux_type->type == ev_union || type->aux_type->type == ev_struct))
9186 QCC_PR_ExpandUnionToFields(type, &pr.size_fields);
9189 // if (type->type == ev_union)
9193 QCC_PR_ParseError (ERR_TYPEWITHNONAME, "type with no name");
9198 name = QCC_PR_ParseName ();
9201 if (QCC_PR_CheckToken("::") && !classname)
9204 name = QCC_PR_ParseName();
9207 //check for an array
9209 if ( QCC_PR_CheckToken ("[") )
9211 char *oldprfile = pr_file_p;
9213 if (QCC_PR_CheckToken("]"))
9221 if(pr_token_type == tt_eof)
9223 if (QCC_PR_CheckToken(","))
9225 if (QCC_PR_CheckToken("}"))
9229 pr_file_p = oldprfile;
9234 arraysize = QCC_PR_IntConstExpr();
9240 QCC_PR_ParseError (ERR_BADARRAYSIZE, "Definition of array (%s) size is not of a numerical value", name);
9241 arraysize=1; //grrr...
9247 if (QCC_PR_CheckToken("("))
9250 QCC_PR_ParseWarning(WARN_UNSAFEFUNCTIONRETURNTYPE, "Function returning function. Is this what you meant? (suggestion: use typedefs)");
9251 inlinefunction = false;
9252 type = QCC_PR_ParseFunctionType(false, type);
9257 char *membername = name;
9258 name = qccHunkAlloc(strlen(classname) + strlen(name) + 3);
9259 sprintf(name, "%s::"MEMBERFIELDNAME, classname, membername);
9260 if (!QCC_PR_GetDef(NULL, name, NULL, false, 0, false))
9261 QCC_PR_ParseError(ERR_NOTANAME, "%s %s is not a member of class %s\n", TypeName(type), membername, classname);
9262 sprintf(name, "%s::%s", classname, membername);
9264 pr_classtype = QCC_TypeForName(classname);
9265 if (!pr_classtype || !pr_classtype->parentclass)
9266 QCC_PR_ParseError(ERR_NOTANAME, "%s is not a class\n", classname);
9269 pr_classtype = NULL;
9271 oldglobals = numpr_globals;
9273 def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave);
9276 QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of class %s", name, classname);
9281 if (!def->initialized && shared) //shared count as initiialised
9283 def->shared = shared;
9284 def->initialized = true;
9287 def->initialized = 2;
9291 if (def->s_file == s_file)
9292 def->isstatic = isstatic;
9293 else //if (type->type != ev_function && defaultstatic) //functions don't quite consitiute a definition
9294 QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "can't redefine non-static as static");
9297 // check for an initialization
9298 if (type->type == ev_function && (pr_scope))
9300 if ( QCC_PR_CheckToken ("=") )
9302 QCC_PR_ParseError (ERR_INITIALISEDLOCALFUNCTION, "local functions may not be initialised");
9306 while (d != def->deftail)
9309 d->initialized = 1; //fake function
9310 G_FUNCTION(d->ofs) = 0;
9316 if (type->type == ev_field && QCC_PR_CheckName ("alias"))
9318 QCC_PR_ParseError(ERR_INTERNAL, "FTEQCC does not support this variant of decompiled hexenc\nPlease obtain the original version released by Raven Software instead.");
9319 name = QCC_PR_ParseName();
9321 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)
9324 QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name);
9325 if (def->initialized == 1)
9327 // if (def->type->type == ev_function)
9329 // i = G_FUNCTION(def->ofs);
9330 // df = &functions[i];
9331 // QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
9334 // QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
9338 { //ignore the code and stuff
9339 if (QCC_PR_CheckToken("["))
9341 while (!QCC_PR_CheckToken("]"))
9343 if (pr_token_type == tt_eof)
9348 if (QCC_PR_CheckToken("{"))
9351 //balance out the { and }
9354 if (pr_token_type == tt_eof)
9356 if (QCC_PR_CheckToken("{"))
9358 else if (QCC_PR_CheckToken("}"))
9361 QCC_PR_Lex(); //ignore it.
9366 QCC_PR_CheckToken("#");
9372 QCC_PR_ParseInitializerDef(def, isvar, isconstant);
9376 if (type->type == ev_function && isvar)
9378 isconstant = !isvar;
9379 def->initialized = 1;
9382 if (type->type == ev_field)
9385 def->constant = 2; //special flag on fields, 2, makes the pointer obtained from them also constant.
9392 def->constant = isconstant;
9396 while (d != def->deftail)
9399 d->constant = def->constant;
9400 d->initialized = def->initialized;
9402 } while (QCC_PR_CheckToken (","));
9404 if (type->type == ev_function)
9405 QCC_PR_CheckToken (";");
9408 if (!QCC_PR_CheckToken (";"))
9409 QCC_PR_ParseWarning(WARN_UNDESIRABLECONVENTION, "Missing semicolon at end of definition");
9417 compiles the 0 terminated text, adding defintions to the pr structure
9420 pbool QCC_PR_CompileFile (char *string, char *filename)
9424 QCC_Error (ERR_INTERNAL, "PR_CompileFile: Didn't clear");
9426 QCC_PR_ClearGrabMacros (); // clear the frame macros
9428 compilingfile = filename;
9432 optres_filenames += strlen(filename);
9433 pr_file_p = qccHunkAlloc(strlen(filename)+1);
9434 strcpy(pr_file_p, filename);
9435 s_file = pr_file_p - strings;
9440 s_file = s_file2 = QCC_CopyString (filename);
9446 memcpy(&oldjb, &pr_parse_abort, sizeof(oldjb));
9448 if( setjmp( pr_parse_abort ) ) {
9449 // dont count it as error
9451 //clock up the first line
9452 QCC_PR_NewLine (false);
9454 QCC_PR_Lex (); // read first token
9457 while (pr_token_type != tt_eof)
9459 if (setjmp(pr_parse_abort))
9461 if (++pr_error_count > MAX_ERRORS)
9463 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
9469 QCC_PR_SkipToSemicolon ();
9470 if (pr_token_type == tt_eof)
9472 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
9477 pr_scope = NULL; // outside all functions
9479 QCC_PR_ParseDefs (NULL);
9481 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
9483 return (pr_error_count == 0);
9486 pbool QCC_Include(char *filename)
9491 QCC_string_t os_file, os_file2;
9492 int opr_source_line;
9493 char *ocompilingfile;
9494 struct qcc_includechunk_s *oldcurrentchunk;
9496 ocompilingfile = compilingfile;
9499 opr_source_line = pr_source_line;
9500 opr_file_p = pr_file_p;
9501 oldcurrentchunk = currentchunk;
9503 strcpy(fname, filename);
9504 QCC_LoadFile(fname, (void*)&newfile);
9505 currentchunk = NULL;
9506 pr_file_p = newfile;
9507 QCC_PR_CompileFile(newfile, fname);
9508 currentchunk = oldcurrentchunk;
9510 compilingfile = ocompilingfile;
9513 pr_source_line = opr_source_line;
9514 pr_file_p = opr_file_p;
9516 // QCC_PR_IncludeChunk(newfile, false, fname);