]> git.xonotic.org Git - xonotic/gmqcc.git/blob - parser.c
find aliases in parser_find_global instead of parser_sya_operand
[xonotic/gmqcc.git] / parser.c
1 /*
2  * Copyright (C) 2012, 2013
3  *     Wolfgang Bumiller
4  *     Dale Weiler
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy of
7  * this software and associated documentation files (the "Software"), to deal in
8  * the Software without restriction, including without limitation the rights to
9  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is furnished to do
11  * so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #include "gmqcc.h"
28 #include "lexer.h"
29 #include "ast.h"
30
31 /* beginning of locals */
32 #define PARSER_HT_LOCALS  2
33
34 #define PARSER_HT_SIZE    128
35 #define TYPEDEF_HT_SIZE   16
36
37 typedef struct {
38     lex_file *lex;
39     int      tok;
40
41     ast_expression **globals;
42     ast_expression **fields;
43     ast_function **functions;
44     ast_value    **imm_float;
45     ast_value    **imm_string;
46     ast_value    **imm_vector;
47     size_t         translated;
48
49     /* must be deleted first, they reference immediates and values */
50     ast_value    **accessors;
51
52     ast_value *imm_float_zero;
53     ast_value *imm_float_one;
54     ast_value *imm_float_neg_one;
55
56     ast_value *imm_vector_zero;
57
58     ast_value *nil;
59     ast_value *reserved_version;
60
61     size_t crc_globals;
62     size_t crc_fields;
63
64     ast_function *function;
65     ht            aliases;
66
67     /* All the labels the function defined...
68      * Should they be in ast_function instead?
69      */
70     ast_label  **labels;
71     ast_goto   **gotos;
72     const char **breaks;
73     const char **continues;
74
75     /* A list of hashtables for each scope */
76     ht *variables;
77     ht htfields;
78     ht htglobals;
79     ht *typedefs;
80
81     /* same as above but for the spelling corrector */
82     correct_trie_t  **correct_variables;
83     size_t         ***correct_variables_score;  /* vector of vector of size_t* */
84
85     /* not to be used directly, we use the hash table */
86     ast_expression **_locals;
87     size_t          *_blocklocals;
88     ast_value      **_typedefs;
89     size_t          *_blocktypedefs;
90     lex_ctx         *_block_ctx;
91
92     /* we store the '=' operator info */
93     const oper_info *assign_op;
94
95     /* magic values */
96     ast_value *const_vec[3];
97
98     /* pragma flags */
99     bool noref;
100
101     /* collected information */
102     size_t     max_param_count;
103 } parser_t;
104
105 static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1;
106
107 static void parser_enterblock(parser_t *parser);
108 static bool parser_leaveblock(parser_t *parser);
109 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
110 static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e);
111 static bool parse_typedef(parser_t *parser);
112 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
113 static ast_block* parse_block(parser_t *parser);
114 static bool parse_block_into(parser_t *parser, ast_block *block);
115 static bool parse_statement_or_block(parser_t *parser, ast_expression **out);
116 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases);
117 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels);
118 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels);
119 static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname);
120 static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname);
121 static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
122
123 static void parseerror(parser_t *parser, const char *fmt, ...)
124 {
125     va_list ap;
126     va_start(ap, fmt);
127     vcompile_error(parser->lex->tok.ctx, fmt, ap);
128     va_end(ap);
129 }
130
131 /* returns true if it counts as an error */
132 static bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, ...)
133 {
134     bool    r;
135     va_list ap;
136     va_start(ap, fmt);
137     r = vcompile_warning(parser->lex->tok.ctx, warntype, fmt, ap);
138     va_end(ap);
139     return r;
140 }
141
142 /**********************************************************************
143  * some maths used for constant folding
144  */
145
146 vector vec3_add(vector a, vector b)
147 {
148     vector out;
149     out.x = a.x + b.x;
150     out.y = a.y + b.y;
151     out.z = a.z + b.z;
152     return out;
153 }
154
155 vector vec3_sub(vector a, vector b)
156 {
157     vector out;
158     out.x = a.x - b.x;
159     out.y = a.y - b.y;
160     out.z = a.z - b.z;
161     return out;
162 }
163
164 qcfloat vec3_mulvv(vector a, vector b)
165 {
166     return (a.x * b.x + a.y * b.y + a.z * b.z);
167 }
168
169 vector vec3_mulvf(vector a, float b)
170 {
171     vector out;
172     out.x = a.x * b;
173     out.y = a.y * b;
174     out.z = a.z * b;
175     return out;
176 }
177
178 /**********************************************************************
179  * parsing
180  */
181
182 bool parser_next(parser_t *parser)
183 {
184     /* lex_do kills the previous token */
185     parser->tok = lex_do(parser->lex);
186     if (parser->tok == TOKEN_EOF)
187         return true;
188     if (parser->tok >= TOKEN_ERROR) {
189         parseerror(parser, "lex error");
190         return false;
191     }
192     return true;
193 }
194
195 #define parser_tokval(p) ((p)->lex->tok.value)
196 #define parser_token(p)  (&((p)->lex->tok))
197 #define parser_ctx(p)    ((p)->lex->tok.ctx)
198
199 static ast_value* parser_const_float(parser_t *parser, double d)
200 {
201     size_t i;
202     ast_value *out;
203     lex_ctx ctx;
204     for (i = 0; i < vec_size(parser->imm_float); ++i) {
205         const double compare = parser->imm_float[i]->constval.vfloat;
206         if (memcmp((const void*)&compare, (const void *)&d, sizeof(double)) == 0)
207             return parser->imm_float[i];
208     }
209     if (parser->lex)
210         ctx = parser_ctx(parser);
211     else {
212         memset(&ctx, 0, sizeof(ctx));
213     }
214     out = ast_value_new(ctx, "#IMMEDIATE", TYPE_FLOAT);
215     out->cvq      = CV_CONST;
216     out->hasvalue = true;
217     out->constval.vfloat = d;
218     vec_push(parser->imm_float, out);
219     return out;
220 }
221
222 static ast_value* parser_const_float_0(parser_t *parser)
223 {
224     if (!parser->imm_float_zero)
225         parser->imm_float_zero = parser_const_float(parser, 0);
226     return parser->imm_float_zero;
227 }
228
229 static ast_value* parser_const_float_neg1(parser_t *parser) {
230     if (!parser->imm_float_neg_one)
231         parser->imm_float_neg_one = parser_const_float(parser, -1);
232     return parser->imm_float_neg_one;
233 }
234
235 static ast_value* parser_const_float_1(parser_t *parser)
236 {
237     if (!parser->imm_float_one)
238         parser->imm_float_one = parser_const_float(parser, 1);
239     return parser->imm_float_one;
240 }
241
242 static char *parser_strdup(const char *str)
243 {
244     if (str && !*str) {
245         /* actually dup empty strings */
246         char *out = (char*)mem_a(1);
247         *out = 0;
248         return out;
249     }
250     return util_strdup(str);
251 }
252
253 static ast_value* parser_const_string(parser_t *parser, const char *str, bool dotranslate)
254 {
255     size_t i;
256     ast_value *out;
257     for (i = 0; i < vec_size(parser->imm_string); ++i) {
258         if (!strcmp(parser->imm_string[i]->constval.vstring, str))
259             return parser->imm_string[i];
260     }
261     if (dotranslate) {
262         char name[32];
263         snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++));
264         out = ast_value_new(parser_ctx(parser), name, TYPE_STRING);
265     } else
266         out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING);
267     out->cvq      = CV_CONST;
268     out->hasvalue = true;
269     out->constval.vstring = parser_strdup(str);
270     vec_push(parser->imm_string, out);
271     return out;
272 }
273
274 static ast_value* parser_const_vector(parser_t *parser, vector v)
275 {
276     size_t i;
277     ast_value *out;
278     for (i = 0; i < vec_size(parser->imm_vector); ++i) {
279         if (!memcmp(&parser->imm_vector[i]->constval.vvec, &v, sizeof(v)))
280             return parser->imm_vector[i];
281     }
282     out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_VECTOR);
283     out->cvq      = CV_CONST;
284     out->hasvalue = true;
285     out->constval.vvec = v;
286     vec_push(parser->imm_vector, out);
287     return out;
288 }
289
290 static ast_value* parser_const_vector_f(parser_t *parser, float x, float y, float z)
291 {
292     vector v;
293     v.x = x;
294     v.y = y;
295     v.z = z;
296     return parser_const_vector(parser, v);
297 }
298
299 static ast_value* parser_const_vector_0(parser_t *parser)
300 {
301     if (!parser->imm_vector_zero)
302         parser->imm_vector_zero = parser_const_vector_f(parser, 0, 0, 0);
303     return parser->imm_vector_zero;
304 }
305
306 static ast_expression* parser_find_field(parser_t *parser, const char *name)
307 {
308     return ( ast_expression*)util_htget(parser->htfields, name);
309 }
310
311 static ast_expression* parser_find_label(parser_t *parser, const char *name)
312 {
313     size_t i;
314     for(i = 0; i < vec_size(parser->labels); i++)
315         if (!strcmp(parser->labels[i]->name, name))
316             return (ast_expression*)parser->labels[i];
317     return NULL;
318 }
319
320 static ast_expression* parser_find_global(parser_t *parser, const char *name)
321 {
322     ast_expression *var = (ast_expression*)util_htget(parser->aliases, parser_tokval(parser));
323     if (var)
324         return var;
325     return (ast_expression*)util_htget(parser->htglobals, name);
326 }
327
328 static ast_expression* parser_find_param(parser_t *parser, const char *name)
329 {
330     size_t i;
331     ast_value *fun;
332     if (!parser->function)
333         return NULL;
334     fun = parser->function->vtype;
335     for (i = 0; i < vec_size(fun->expression.params); ++i) {
336         if (!strcmp(fun->expression.params[i]->name, name))
337             return (ast_expression*)(fun->expression.params[i]);
338     }
339     return NULL;
340 }
341
342 static ast_expression* parser_find_local(parser_t *parser, const char *name, size_t upto, bool *isparam)
343 {
344     size_t          i, hash;
345     ast_expression *e;
346
347     hash = util_hthash(parser->htglobals, name);
348
349     *isparam = false;
350     for (i = vec_size(parser->variables); i > upto;) {
351         --i;
352         if ( (e = (ast_expression*)util_htgeth(parser->variables[i], name, hash)) )
353             return e;
354     }
355     *isparam = true;
356     return parser_find_param(parser, name);
357 }
358
359 static ast_expression* parser_find_var(parser_t *parser, const char *name)
360 {
361     bool dummy;
362     ast_expression *v;
363     v         = parser_find_local(parser, name, 0, &dummy);
364     if (!v) v = parser_find_global(parser, name);
365     return v;
366 }
367
368 static ast_value* parser_find_typedef(parser_t *parser, const char *name, size_t upto)
369 {
370     size_t     i, hash;
371     ast_value *e;
372     hash = util_hthash(parser->typedefs[0], name);
373
374     for (i = vec_size(parser->typedefs); i > upto;) {
375         --i;
376         if ( (e = (ast_value*)util_htgeth(parser->typedefs[i], name, hash)) )
377             return e;
378     }
379     return NULL;
380 }
381
382 typedef struct
383 {
384     size_t etype; /* 0 = expression, others are operators */
385     bool            isparen;
386     size_t          off;
387     ast_expression *out;
388     ast_block      *block; /* for commas and function calls */
389     lex_ctx ctx;
390 } sy_elem;
391
392 enum {
393     PAREN_EXPR,
394     PAREN_FUNC,
395     PAREN_INDEX,
396     PAREN_TERNARY1,
397     PAREN_TERNARY2
398 };
399 typedef struct
400 {
401     sy_elem        *out;
402     sy_elem        *ops;
403     size_t         *argc;
404     unsigned int   *paren;
405 } shunt;
406
407 static sy_elem syexp(lex_ctx ctx, ast_expression *v) {
408     sy_elem e;
409     e.etype = 0;
410     e.off   = 0;
411     e.out   = v;
412     e.block = NULL;
413     e.ctx   = ctx;
414     e.isparen = false;
415     return e;
416 }
417
418 static sy_elem syblock(lex_ctx ctx, ast_block *v) {
419     sy_elem e;
420     e.etype = 0;
421     e.off   = 0;
422     e.out   = (ast_expression*)v;
423     e.block = v;
424     e.ctx   = ctx;
425     e.isparen = false;
426     return e;
427 }
428
429 static sy_elem syop(lex_ctx ctx, const oper_info *op) {
430     sy_elem e;
431     e.etype = 1 + (op - operators);
432     e.off   = 0;
433     e.out   = NULL;
434     e.block = NULL;
435     e.ctx   = ctx;
436     e.isparen = false;
437     return e;
438 }
439
440 static sy_elem syparen(lex_ctx ctx, size_t off) {
441     sy_elem e;
442     e.etype = 0;
443     e.off   = off;
444     e.out   = NULL;
445     e.block = NULL;
446     e.ctx   = ctx;
447     e.isparen = true;
448     return e;
449 }
450
451 /* With regular precedence rules, ent.foo[n] is the same as (ent.foo)[n],
452  * so we need to rotate it to become ent.(foo[n]).
453  */
454 static bool rotate_entfield_array_index_nodes(ast_expression **out)
455 {
456     ast_array_index *index, *oldindex;
457     ast_entfield    *entfield;
458
459     ast_value       *field;
460     ast_expression  *sub;
461     ast_expression  *entity;
462
463     lex_ctx ctx = ast_ctx(*out);
464
465     if (!ast_istype(*out, ast_array_index))
466         return false;
467     index = (ast_array_index*)*out;
468
469     if (!ast_istype(index->array, ast_entfield))
470         return false;
471     entfield = (ast_entfield*)index->array;
472
473     if (!ast_istype(entfield->field, ast_value))
474         return false;
475     field = (ast_value*)entfield->field;
476
477     sub    = index->index;
478     entity = entfield->entity;
479
480     oldindex = index;
481
482     index = ast_array_index_new(ctx, (ast_expression*)field, sub);
483     entfield = ast_entfield_new(ctx, entity, (ast_expression*)index);
484     *out = (ast_expression*)entfield;
485
486     oldindex->array = NULL;
487     oldindex->index = NULL;
488     ast_delete(oldindex);
489
490     return true;
491 }
492
493 static bool immediate_is_true(lex_ctx ctx, ast_value *v)
494 {
495     switch (v->expression.vtype) {
496         case TYPE_FLOAT:
497             return !!v->constval.vfloat;
498         case TYPE_INTEGER:
499             return !!v->constval.vint;
500         case TYPE_VECTOR:
501             if (OPTS_FLAG(CORRECT_LOGIC))
502                 return v->constval.vvec.x &&
503                        v->constval.vvec.y &&
504                        v->constval.vvec.z;
505             else
506                 return !!(v->constval.vvec.x);
507         case TYPE_STRING:
508             if (!v->constval.vstring)
509                 return false;
510             if (v->constval.vstring && OPTS_FLAG(TRUE_EMPTY_STRINGS))
511                 return true;
512             return !!v->constval.vstring[0];
513         default:
514             compile_error(ctx, "internal error: immediate_is_true on invalid type");
515             return !!v->constval.vfunc;
516     }
517 }
518
519 static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
520 {
521     const oper_info *op;
522     lex_ctx ctx;
523     ast_expression *out = NULL;
524     ast_expression *exprs[3];
525     ast_block      *blocks[3];
526     ast_value      *asvalue[3];
527     ast_binstore   *asbinstore;
528     size_t i, assignop, addop, subop;
529     qcint  generated_op = 0;
530
531     char ty1[1024];
532     char ty2[1024];
533
534     if (!vec_size(sy->ops)) {
535         parseerror(parser, "internal error: missing operator");
536         return false;
537     }
538
539     if (vec_last(sy->ops).isparen) {
540         parseerror(parser, "unmatched parenthesis");
541         return false;
542     }
543
544     op = &operators[vec_last(sy->ops).etype - 1];
545     ctx = vec_last(sy->ops).ctx;
546
547     if (vec_size(sy->out) < op->operands) {
548         compile_error(ctx, "internal error: not enough operands: %i (operator %s (%i))", vec_size(sy->out),
549                       op->op, (int)op->id);
550         return false;
551     }
552
553     vec_shrinkby(sy->ops, 1);
554
555     /* op(:?) has no input and no output */
556     if (!op->operands)
557         return true;
558
559     vec_shrinkby(sy->out, op->operands);
560     for (i = 0; i < op->operands; ++i) {
561         exprs[i]  = sy->out[vec_size(sy->out)+i].out;
562         blocks[i] = sy->out[vec_size(sy->out)+i].block;
563         asvalue[i] = (ast_value*)exprs[i];
564
565         if (exprs[i]->expression.vtype == TYPE_NOEXPR &&
566             !(i != 0 && op->id == opid2('?',':')) &&
567             !(i == 1 && op->id == opid1('.')))
568         {
569             if (ast_istype(exprs[i], ast_label))
570                 compile_error(ast_ctx(exprs[i]), "expected expression, got an unknown identifier");
571             else
572                 compile_error(ast_ctx(exprs[i]), "not an expression");
573             (void)!compile_warning(ast_ctx(exprs[i]), WARN_DEBUG, "expression %u\n", (unsigned int)i);
574         }
575     }
576
577     if (blocks[0] && !vec_size(blocks[0]->exprs) && op->id != opid1(',')) {
578         compile_error(ctx, "internal error: operator cannot be applied on empty blocks");
579         return false;
580     }
581
582 #define NotSameType(T) \
583              (exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
584               exprs[0]->expression.vtype != T)
585 #define CanConstFold1(A) \
586              (ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && (((ast_value*)(A))->cvq == CV_CONST) &&\
587               (A)->expression.vtype != TYPE_FUNCTION)
588 #define CanConstFold(A, B) \
589              (CanConstFold1(A) && CanConstFold1(B))
590 #define ConstV(i) (asvalue[(i)]->constval.vvec)
591 #define ConstF(i) (asvalue[(i)]->constval.vfloat)
592 #define ConstS(i) (asvalue[(i)]->constval.vstring)
593     switch (op->id)
594     {
595         default:
596             compile_error(ctx, "internal error: unhandled operator: %s (%i)", op->op, (int)op->id);
597             return false;
598
599         case opid1('.'):
600             if (exprs[0]->expression.vtype == TYPE_VECTOR &&
601                 exprs[1]->expression.vtype == TYPE_NOEXPR)
602             {
603                 if      (exprs[1] == (ast_expression*)parser->const_vec[0])
604                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
605                 else if (exprs[1] == (ast_expression*)parser->const_vec[1])
606                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
607                 else if (exprs[1] == (ast_expression*)parser->const_vec[2])
608                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
609                 else {
610                     compile_error(ctx, "access to invalid vector component");
611                     return false;
612                 }
613             }
614             else if (exprs[0]->expression.vtype == TYPE_ENTITY) {
615                 if (exprs[1]->expression.vtype != TYPE_FIELD) {
616                     compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
617                     return false;
618                 }
619                 out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
620             }
621             else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
622                 compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
623                 return false;
624             }
625             else {
626                 compile_error(ast_ctx(exprs[1]), "type error: member-of operator on something that is not an entity or vector");
627                 return false;
628             }
629             break;
630
631         case opid1('['):
632             if (exprs[0]->expression.vtype != TYPE_ARRAY &&
633                 !(exprs[0]->expression.vtype == TYPE_FIELD &&
634                   exprs[0]->expression.next->expression.vtype == TYPE_ARRAY))
635             {
636                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
637                 compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
638                 return false;
639             }
640             if (exprs[1]->expression.vtype != TYPE_FLOAT) {
641                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
642                 compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
643                 return false;
644             }
645             out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]);
646             if (rotate_entfield_array_index_nodes(&out))
647             {
648 #if 0
649                 /* This is not broken in fteqcc anymore */
650                 if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
651                     /* this error doesn't need to make us bail out */
652                     (void)!parsewarning(parser, WARN_EXTENSIONS,
653                                         "accessing array-field members of an entity without parenthesis\n"
654                                         " -> this is an extension from -std=gmqcc");
655                 }
656 #endif
657             }
658             break;
659
660         case opid1(','):
661             if (vec_size(sy->paren) && vec_last(sy->paren) == PAREN_FUNC) {
662                 vec_push(sy->out, syexp(ctx, exprs[0]));
663                 vec_push(sy->out, syexp(ctx, exprs[1]));
664                 vec_last(sy->argc)++;
665                 return true;
666             }
667             if (blocks[0]) {
668                 if (!ast_block_add_expr(blocks[0], exprs[1]))
669                     return false;
670             } else {
671                 blocks[0] = ast_block_new(ctx);
672                 if (!ast_block_add_expr(blocks[0], exprs[0]) ||
673                     !ast_block_add_expr(blocks[0], exprs[1]))
674                 {
675                     return false;
676                 }
677             }
678             ast_block_set_type(blocks[0], exprs[1]);
679
680             vec_push(sy->out, syblock(ctx, blocks[0]));
681             return true;
682
683         case opid2('+','P'):
684             out = exprs[0];
685             break;
686         case opid2('-','P'):
687             switch (exprs[0]->expression.vtype) {
688                 case TYPE_FLOAT:
689                     if (CanConstFold1(exprs[0]))
690                         out = (ast_expression*)parser_const_float(parser, -ConstF(0));
691                     else
692                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F,
693                                                               (ast_expression*)parser_const_float_0(parser),
694                                                               exprs[0]);
695                     break;
696                 case TYPE_VECTOR:
697                     if (CanConstFold1(exprs[0]))
698                         out = (ast_expression*)parser_const_vector_f(parser,
699                             -ConstV(0).x, -ConstV(0).y, -ConstV(0).z);
700                     else
701                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V,
702                                                               (ast_expression*)parser_const_vector_0(parser),
703                                                               exprs[0]);
704                     break;
705                 default:
706                 compile_error(ctx, "invalid types used in expression: cannot negate type %s",
707                               type_name[exprs[0]->expression.vtype]);
708                 return false;
709             }
710             break;
711
712         case opid2('!','P'):
713             switch (exprs[0]->expression.vtype) {
714                 case TYPE_FLOAT:
715                     if (CanConstFold1(exprs[0]))
716                         out = (ast_expression*)parser_const_float(parser, !ConstF(0));
717                     else
718                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
719                     break;
720                 case TYPE_VECTOR:
721                     if (CanConstFold1(exprs[0]))
722                         out = (ast_expression*)parser_const_float(parser,
723                             (!ConstV(0).x && !ConstV(0).y && !ConstV(0).z));
724                     else
725                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]);
726                     break;
727                 case TYPE_STRING:
728                     if (CanConstFold1(exprs[0])) {
729                         if (OPTS_FLAG(TRUE_EMPTY_STRINGS))
730                             out = (ast_expression*)parser_const_float(parser, !ConstS(0));
731                         else
732                             out = (ast_expression*)parser_const_float(parser, !ConstS(0) || !*ConstS(0));
733                     } else {
734                         if (OPTS_FLAG(TRUE_EMPTY_STRINGS))
735                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
736                         else
737                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]);
738                     }
739                     break;
740                 /* we don't constant-fold NOT for these types */
741                 case TYPE_ENTITY:
742                     out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_ENT, exprs[0]);
743                     break;
744                 case TYPE_FUNCTION:
745                     out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_FNC, exprs[0]);
746                     break;
747                 default:
748                 compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
749                               type_name[exprs[0]->expression.vtype]);
750                 return false;
751             }
752             break;
753
754         case opid1('+'):
755             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
756                 (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
757             {
758                 compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
759                               type_name[exprs[0]->expression.vtype],
760                               type_name[exprs[1]->expression.vtype]);
761                 return false;
762             }
763             switch (exprs[0]->expression.vtype) {
764                 case TYPE_FLOAT:
765                     if (CanConstFold(exprs[0], exprs[1]))
766                     {
767                         out = (ast_expression*)parser_const_float(parser, ConstF(0) + ConstF(1));
768                     }
769                     else
770                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
771                     break;
772                 case TYPE_VECTOR:
773                     if (CanConstFold(exprs[0], exprs[1]))
774                         out = (ast_expression*)parser_const_vector(parser, vec3_add(ConstV(0), ConstV(1)));
775                     else
776                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
777                     break;
778                 default:
779                     compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
780                                   type_name[exprs[0]->expression.vtype],
781                                   type_name[exprs[1]->expression.vtype]);
782                     return false;
783             };
784             break;
785         case opid1('-'):
786             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
787                 (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
788             {
789                 compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
790                               type_name[exprs[1]->expression.vtype],
791                               type_name[exprs[0]->expression.vtype]);
792                 return false;
793             }
794             switch (exprs[0]->expression.vtype) {
795                 case TYPE_FLOAT:
796                     if (CanConstFold(exprs[0], exprs[1]))
797                         out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1));
798                     else
799                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
800                     break;
801                 case TYPE_VECTOR:
802                     if (CanConstFold(exprs[0], exprs[1]))
803                         out = (ast_expression*)parser_const_vector(parser, vec3_sub(ConstV(0), ConstV(1)));
804                     else
805                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
806                     break;
807                 default:
808                     compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
809                                   type_name[exprs[1]->expression.vtype],
810                                   type_name[exprs[0]->expression.vtype]);
811                     return false;
812             };
813             break;
814         case opid1('*'):
815             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype &&
816                 !(exprs[0]->expression.vtype == TYPE_VECTOR &&
817                   exprs[1]->expression.vtype == TYPE_FLOAT) &&
818                 !(exprs[1]->expression.vtype == TYPE_VECTOR &&
819                   exprs[0]->expression.vtype == TYPE_FLOAT)
820                 )
821             {
822                 compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
823                               type_name[exprs[1]->expression.vtype],
824                               type_name[exprs[0]->expression.vtype]);
825                 return false;
826             }
827             switch (exprs[0]->expression.vtype) {
828                 case TYPE_FLOAT:
829                     if (exprs[1]->expression.vtype == TYPE_VECTOR)
830                     {
831                         if (CanConstFold(exprs[0], exprs[1]))
832                             out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0)));
833                         else
834                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
835                     }
836                     else
837                     {
838                         if (CanConstFold(exprs[0], exprs[1]))
839                             out = (ast_expression*)parser_const_float(parser, ConstF(0) * ConstF(1));
840                         else
841                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
842                     }
843                     break;
844                 case TYPE_VECTOR:
845                     if (exprs[1]->expression.vtype == TYPE_FLOAT)
846                     {
847                         if (CanConstFold(exprs[0], exprs[1]))
848                             out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1)));
849                         else
850                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
851                     }
852                     else
853                     {
854                         if (CanConstFold(exprs[0], exprs[1]))
855                             out = (ast_expression*)parser_const_float(parser, vec3_mulvv(ConstV(0), ConstV(1)));
856                         else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && CanConstFold1(exprs[0])) {
857                             vector vec = ConstV(0);
858                             if (!vec.y && !vec.z) { /* 'n 0 0' * v */
859                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
860                                 out = (ast_expression*)ast_member_new(ctx, exprs[1], 0, NULL);
861                                 out->expression.node.keep = false;
862                                 ((ast_member*)out)->rvalue = true;
863                                 if (vec.x != 1)
864                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out);
865                             }
866                             else if (!vec.x && !vec.z) { /* '0 n 0' * v */
867                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
868                                 out = (ast_expression*)ast_member_new(ctx, exprs[1], 1, NULL);
869                                 out->expression.node.keep = false;
870                                 ((ast_member*)out)->rvalue = true;
871                                 if (vec.y != 1)
872                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out);
873                             }
874                             else if (!vec.x && !vec.y) { /* '0 n 0' * v */
875                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
876                                 out = (ast_expression*)ast_member_new(ctx, exprs[1], 2, NULL);
877                                 out->expression.node.keep = false;
878                                 ((ast_member*)out)->rvalue = true;
879                                 if (vec.z != 1)
880                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out);
881                             }
882                             else
883                                 out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
884                         }
885                         else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && CanConstFold1(exprs[1])) {
886                             vector vec = ConstV(1);
887                             if (!vec.y && !vec.z) { /* v * 'n 0 0' */
888                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
889                                 out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
890                                 out->expression.node.keep = false;
891                                 ((ast_member*)out)->rvalue = true;
892                                 if (vec.x != 1)
893                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x));
894                             }
895                             else if (!vec.x && !vec.z) { /* v * '0 n 0' */
896                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
897                                 out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
898                                 out->expression.node.keep = false;
899                                 ((ast_member*)out)->rvalue = true;
900                                 if (vec.y != 1)
901                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y));
902                             }
903                             else if (!vec.x && !vec.y) { /* v * '0 n 0' */
904                                 ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
905                                 out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
906                                 out->expression.node.keep = false;
907                                 ((ast_member*)out)->rvalue = true;
908                                 if (vec.z != 1)
909                                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z));
910                             }
911                             else
912                                 out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
913                         }
914                         else
915                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
916                     }
917                     break;
918                 default:
919                     compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
920                                   type_name[exprs[1]->expression.vtype],
921                                   type_name[exprs[0]->expression.vtype]);
922                     return false;
923             };
924             break;
925         case opid1('/'):
926             if (exprs[1]->expression.vtype != TYPE_FLOAT) {
927                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
928                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
929                 compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2);
930                 return false;
931             }
932             if (exprs[0]->expression.vtype == TYPE_FLOAT) {
933                 if (CanConstFold(exprs[0], exprs[1]))
934                     out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
935                 else
936                     out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
937             }
938             else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
939                 if (CanConstFold(exprs[0], exprs[1]))
940                     out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
941                 else {
942                     if (CanConstFold1(exprs[1])) {
943                         out = (ast_expression*)parser_const_float(parser, 1.0 / ConstF(1));
944                     } else {
945                         out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
946                                                               (ast_expression*)parser_const_float_1(parser),
947                                                               exprs[1]);
948                     }
949                     if (!out) {
950                         compile_error(ctx, "internal error: failed to generate division");
951                         return false;
952                     }
953                     out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], out);
954                 }
955             }
956             else
957             {
958                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
959                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
960                 compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2);
961                 return false;
962             }
963             break;
964         case opid1('%'):
965         case opid2('%','='):
966             compile_error(ctx, "qc does not have a modulo operator");
967             return false;
968         case opid1('|'):
969         case opid1('&'):
970             if (NotSameType(TYPE_FLOAT)) {
971                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
972                               type_name[exprs[0]->expression.vtype],
973                               type_name[exprs[1]->expression.vtype]);
974                 return false;
975             }
976             if (CanConstFold(exprs[0], exprs[1]))
977                 out = (ast_expression*)parser_const_float(parser,
978                     (op->id == opid1('|') ? (float)( ((qcint)ConstF(0)) | ((qcint)ConstF(1)) ) :
979                                             (float)( ((qcint)ConstF(0)) & ((qcint)ConstF(1)) ) ));
980             else
981                 out = (ast_expression*)ast_binary_new(ctx,
982                     (op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND),
983                     exprs[0], exprs[1]);
984             break;
985         case opid1('^'):
986             compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor via ^");
987             return false;
988
989         case opid2('<','<'):
990         case opid2('>','>'):
991             if (CanConstFold(exprs[0], exprs[1]) && ! NotSameType(TYPE_FLOAT)) {
992                 if (op->id == opid2('<','<'))
993                     out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) << (int)(ConstF(1))));
994                 else
995                     out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) >> (int)(ConstF(1))));
996                 break;
997             }
998         case opid3('<','<','='):
999         case opid3('>','>','='):
1000             compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts");
1001             return false;
1002
1003         case opid2('|','|'):
1004             generated_op += 1; /* INSTR_OR */
1005         case opid2('&','&'):
1006             generated_op += INSTR_AND;
1007             if (CanConstFold(exprs[0], exprs[1]))
1008             {
1009                 if (OPTS_FLAG(PERL_LOGIC)) {
1010                     if (immediate_is_true(ctx, asvalue[0]))
1011                         out = exprs[1];
1012                 }
1013                 else
1014                     out = (ast_expression*)parser_const_float(parser,
1015                           ( (generated_op == INSTR_OR)
1016                             ? (immediate_is_true(ctx, asvalue[0]) || immediate_is_true(ctx, asvalue[1]))
1017                             : (immediate_is_true(ctx, asvalue[0]) && immediate_is_true(ctx, asvalue[1])) )
1018                           ? 1 : 0);
1019             }
1020             else
1021             {
1022                 if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) {
1023                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1024                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1025                     compile_error(ctx, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2);
1026                     return false;
1027                 }
1028                 for (i = 0; i < 2; ++i) {
1029                     if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->expression.vtype == TYPE_VECTOR) {
1030                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
1031                         if (!out) break;
1032                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
1033                         if (!out) break;
1034                         exprs[i] = out; out = NULL;
1035                         if (OPTS_FLAG(PERL_LOGIC)) {
1036                             /* here we want to keep the right expressions' type */
1037                             break;
1038                         }
1039                     }
1040                     else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->expression.vtype == TYPE_STRING) {
1041                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
1042                         if (!out) break;
1043                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
1044                         if (!out) break;
1045                         exprs[i] = out; out = NULL;
1046                         if (OPTS_FLAG(PERL_LOGIC)) {
1047                             /* here we want to keep the right expressions' type */
1048                             break;
1049                         }
1050                     }
1051                 }
1052                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
1053             }
1054             break;
1055
1056         case opid2('?',':'):
1057             if (vec_last(sy->paren) != PAREN_TERNARY2) {
1058                 compile_error(ctx, "mismatched parenthesis/ternary");
1059                 return false;
1060             }
1061             vec_pop(sy->paren);
1062             if (!ast_compare_type(exprs[1], exprs[2])) {
1063                 ast_type_to_string(exprs[1], ty1, sizeof(ty1));
1064                 ast_type_to_string(exprs[2], ty2, sizeof(ty2));
1065                 compile_error(ctx, "operands of ternary expression must have the same type, got %s and %s", ty1, ty2);
1066                 return false;
1067             }
1068             if (CanConstFold1(exprs[0]))
1069                 out = (immediate_is_true(ctx, asvalue[0]) ? exprs[1] : exprs[2]);
1070             else
1071                 out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]);
1072             break;
1073
1074         case opid3('<','=','>'): /* -1, 0, or 1 */
1075             if (NotSameType(TYPE_FLOAT)) {
1076                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1077                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1078                 compile_error(ctx, "invalid types used in comparision: %s and %s",
1079                     ty1, ty2);
1080
1081                 return false;
1082             }
1083
1084             if (CanConstFold(exprs[0], exprs[1])) {
1085                 if (ConstF(0) < ConstF(1))
1086                     out = (ast_expression*)parser_const_float_neg1(parser);
1087                 else if (ConstF(0) == ConstF(1))
1088                     out = (ast_expression*)parser_const_float_0(parser);
1089                 else if (ConstF(0) > ConstF(1))
1090                     out = (ast_expression*)parser_const_float_1(parser);
1091             } else {
1092                 ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
1093
1094                 eq->refs = false; /* references nothing */
1095
1096                     /* if (lt) { */
1097                 out = (ast_expression*)ast_ternary_new(ctx,
1098                         (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]),
1099                         /* out = -1 */
1100                         (ast_expression*)parser_const_float_neg1(parser),
1101                     /* } else { */
1102                         /* if (eq) { */
1103                         (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq,
1104                             /* out = 0 */
1105                             (ast_expression*)parser_const_float_0(parser),
1106                         /* } else { */
1107                             /* out = 1 */
1108                             (ast_expression*)parser_const_float_1(parser)
1109                         /* } */
1110                         )
1111                     /* } */
1112                     );
1113
1114             }
1115             break;
1116
1117         case opid1('>'):
1118             generated_op += 1; /* INSTR_GT */
1119         case opid1('<'):
1120             generated_op += 1; /* INSTR_LT */
1121         case opid2('>', '='):
1122             generated_op += 1; /* INSTR_GE */
1123         case opid2('<', '='):
1124             generated_op += INSTR_LE;
1125             if (NotSameType(TYPE_FLOAT)) {
1126                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
1127                               type_name[exprs[0]->expression.vtype],
1128                               type_name[exprs[1]->expression.vtype]);
1129                 return false;
1130             }
1131             out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
1132             break;
1133         case opid2('!', '='):
1134             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
1135                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
1136                               type_name[exprs[0]->expression.vtype],
1137                               type_name[exprs[1]->expression.vtype]);
1138                 return false;
1139             }
1140             out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
1141             break;
1142         case opid2('=', '='):
1143             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
1144                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
1145                               type_name[exprs[0]->expression.vtype],
1146                               type_name[exprs[1]->expression.vtype]);
1147                 return false;
1148             }
1149             out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
1150             break;
1151
1152         case opid1('='):
1153             if (ast_istype(exprs[0], ast_entfield)) {
1154                 ast_expression *field = ((ast_entfield*)exprs[0])->field;
1155                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
1156                     exprs[0]->expression.vtype == TYPE_FIELD &&
1157                     exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
1158                 {
1159                     assignop = type_storep_instr[TYPE_VECTOR];
1160                 }
1161                 else
1162                     assignop = type_storep_instr[exprs[0]->expression.vtype];
1163                 if (assignop == VINSTR_END || !ast_compare_type(field->expression.next, exprs[1]))
1164                 {
1165                     ast_type_to_string(field->expression.next, ty1, sizeof(ty1));
1166                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1167                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
1168                         field->expression.next->expression.vtype == TYPE_FUNCTION &&
1169                         exprs[1]->expression.vtype == TYPE_FUNCTION)
1170                     {
1171                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
1172                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
1173                     }
1174                     else
1175                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
1176                 }
1177             }
1178             else
1179             {
1180                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
1181                     exprs[0]->expression.vtype == TYPE_FIELD &&
1182                     exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
1183                 {
1184                     assignop = type_store_instr[TYPE_VECTOR];
1185                 }
1186                 else {
1187                     assignop = type_store_instr[exprs[0]->expression.vtype];
1188                 }
1189
1190                 if (assignop == VINSTR_END) {
1191                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1192                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1193                     compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
1194                 }
1195                 else if (!ast_compare_type(exprs[0], exprs[1]))
1196                 {
1197                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1198                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1199                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
1200                         exprs[0]->expression.vtype == TYPE_FUNCTION &&
1201                         exprs[1]->expression.vtype == TYPE_FUNCTION)
1202                     {
1203                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
1204                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
1205                     }
1206                     else
1207                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
1208                 }
1209             }
1210             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1211                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1212             }
1213             out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]);
1214             break;
1215         case opid3('+','+','P'):
1216         case opid3('-','-','P'):
1217             /* prefix ++ */
1218             if (exprs[0]->expression.vtype != TYPE_FLOAT) {
1219                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1220                 compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
1221                 return false;
1222             }
1223             if (op->id == opid3('+','+','P'))
1224                 addop = INSTR_ADD_F;
1225             else
1226                 addop = INSTR_SUB_F;
1227             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1228                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
1229             }
1230             if (ast_istype(exprs[0], ast_entfield)) {
1231                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
1232                                                         exprs[0],
1233                                                         (ast_expression*)parser_const_float_1(parser));
1234             } else {
1235                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
1236                                                         exprs[0],
1237                                                         (ast_expression*)parser_const_float_1(parser));
1238             }
1239             break;
1240         case opid3('S','+','+'):
1241         case opid3('S','-','-'):
1242             /* prefix ++ */
1243             if (exprs[0]->expression.vtype != TYPE_FLOAT) {
1244                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1245                 compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
1246                 return false;
1247             }
1248             if (op->id == opid3('S','+','+')) {
1249                 addop = INSTR_ADD_F;
1250                 subop = INSTR_SUB_F;
1251             } else {
1252                 addop = INSTR_SUB_F;
1253                 subop = INSTR_ADD_F;
1254             }
1255             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1256                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
1257             }
1258             if (ast_istype(exprs[0], ast_entfield)) {
1259                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
1260                                                         exprs[0],
1261                                                         (ast_expression*)parser_const_float_1(parser));
1262             } else {
1263                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
1264                                                         exprs[0],
1265                                                         (ast_expression*)parser_const_float_1(parser));
1266             }
1267             if (!out)
1268                 return false;
1269             out = (ast_expression*)ast_binary_new(ctx, subop,
1270                                                   out,
1271                                                   (ast_expression*)parser_const_float_1(parser));
1272             break;
1273         case opid2('+','='):
1274         case opid2('-','='):
1275             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
1276                 (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
1277             {
1278                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1279                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1280                 compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1281                               ty1, ty2);
1282                 return false;
1283             }
1284             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1285                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1286             }
1287             if (ast_istype(exprs[0], ast_entfield))
1288                 assignop = type_storep_instr[exprs[0]->expression.vtype];
1289             else
1290                 assignop = type_store_instr[exprs[0]->expression.vtype];
1291             switch (exprs[0]->expression.vtype) {
1292                 case TYPE_FLOAT:
1293                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1294                                                             (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
1295                                                             exprs[0], exprs[1]);
1296                     break;
1297                 case TYPE_VECTOR:
1298                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1299                                                             (op->id == opid2('+','=') ? INSTR_ADD_V : INSTR_SUB_V),
1300                                                             exprs[0], exprs[1]);
1301                     break;
1302                 default:
1303                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1304                                   type_name[exprs[0]->expression.vtype],
1305                                   type_name[exprs[1]->expression.vtype]);
1306                     return false;
1307             };
1308             break;
1309         case opid2('*','='):
1310         case opid2('/','='):
1311             if (exprs[1]->expression.vtype != TYPE_FLOAT ||
1312                 !(exprs[0]->expression.vtype == TYPE_FLOAT ||
1313                   exprs[0]->expression.vtype == TYPE_VECTOR))
1314             {
1315                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1316                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1317                 compile_error(ctx, "invalid types used in expression: %s and %s",
1318                               ty1, ty2);
1319                 return false;
1320             }
1321             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1322                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1323             }
1324             if (ast_istype(exprs[0], ast_entfield))
1325                 assignop = type_storep_instr[exprs[0]->expression.vtype];
1326             else
1327                 assignop = type_store_instr[exprs[0]->expression.vtype];
1328             switch (exprs[0]->expression.vtype) {
1329                 case TYPE_FLOAT:
1330                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1331                                                             (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
1332                                                             exprs[0], exprs[1]);
1333                     break;
1334                 case TYPE_VECTOR:
1335                     if (op->id == opid2('*','=')) {
1336                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1337                                                                 exprs[0], exprs[1]);
1338                     } else {
1339                         /* there's no DIV_VF */
1340                         if (CanConstFold1(exprs[1])) {
1341                             out = (ast_expression*)parser_const_float(parser, 1.0 / ConstF(1));
1342                         } else {
1343                             out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
1344                                                                   (ast_expression*)parser_const_float_1(parser),
1345                                                                   exprs[1]);
1346                         }
1347                         if (!out) {
1348                             compile_error(ctx, "internal error: failed to generate division");
1349                             return false;
1350                         }
1351                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1352                                                                 exprs[0], out);
1353                     }
1354                     break;
1355                 default:
1356                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1357                                   type_name[exprs[0]->expression.vtype],
1358                                   type_name[exprs[1]->expression.vtype]);
1359                     return false;
1360             };
1361             break;
1362         case opid2('&','='):
1363         case opid2('|','='):
1364             if (NotSameType(TYPE_FLOAT)) {
1365                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1366                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1367                 compile_error(ctx, "invalid types used in expression: %s and %s",
1368                               ty1, ty2);
1369                 return false;
1370             }
1371             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1372                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1373             }
1374             if (ast_istype(exprs[0], ast_entfield))
1375                 assignop = type_storep_instr[exprs[0]->expression.vtype];
1376             else
1377                 assignop = type_store_instr[exprs[0]->expression.vtype];
1378             out = (ast_expression*)ast_binstore_new(ctx, assignop,
1379                                                     (op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
1380                                                     exprs[0], exprs[1]);
1381             break;
1382         case opid3('&','~','='):
1383             /* This is like: a &= ~(b);
1384              * But QC has no bitwise-not, so we implement it as
1385              * a -= a & (b);
1386              */
1387             if (NotSameType(TYPE_FLOAT)) {
1388                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1389                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1390                 compile_error(ctx, "invalid types used in expression: %s and %s",
1391                               ty1, ty2);
1392                 return false;
1393             }
1394             if (ast_istype(exprs[0], ast_entfield))
1395                 assignop = type_storep_instr[exprs[0]->expression.vtype];
1396             else
1397                 assignop = type_store_instr[exprs[0]->expression.vtype];
1398             out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
1399             if (!out)
1400                 return false;
1401             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1402                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1403             }
1404             asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out);
1405             asbinstore->keep_dest = true;
1406             out = (ast_expression*)asbinstore;
1407             break;
1408
1409         case opid2('~', 'P'):
1410             if (exprs[0]->expression.vtype != TYPE_FLOAT) {
1411                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1412                 compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
1413                 return false;
1414             }
1415
1416             if(CanConstFold1(exprs[0]))
1417                 out = (ast_expression*)parser_const_float(parser, ~(qcint)ConstF(0));
1418             else
1419                 out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser_const_float_neg1(parser), exprs[0]);
1420             break;
1421     }
1422 #undef NotSameType
1423
1424     if (!out) {
1425         compile_error(ctx, "failed to apply operator %s", op->op);
1426         return false;
1427     }
1428
1429     vec_push(sy->out, syexp(ctx, out));
1430     return true;
1431 }
1432
1433 static bool parser_close_call(parser_t *parser, shunt *sy)
1434 {
1435     /* was a function call */
1436     ast_expression *fun;
1437     ast_value      *funval = NULL;
1438     ast_call       *call;
1439
1440     size_t          fid;
1441     size_t          paramcount, i;
1442
1443     fid = vec_last(sy->ops).off;
1444     vec_shrinkby(sy->ops, 1);
1445
1446     /* out[fid] is the function
1447      * everything above is parameters...
1448      */
1449     if (!vec_size(sy->argc)) {
1450         parseerror(parser, "internal error: no argument counter available");
1451         return false;
1452     }
1453
1454     paramcount = vec_last(sy->argc);
1455     vec_pop(sy->argc);
1456
1457     if (vec_size(sy->out) < fid) {
1458         parseerror(parser, "internal error: broken function call%lu < %lu+%lu\n",
1459                    (unsigned long)vec_size(sy->out),
1460                    (unsigned long)fid,
1461                    (unsigned long)paramcount);
1462         return false;
1463     }
1464
1465     fun = sy->out[fid].out;
1466
1467     if (fun == intrinsic_debug_typestring) {
1468         char ty[1024];
1469         if (fid+2 != vec_size(sy->out) ||
1470             vec_last(sy->out).block)
1471         {
1472             parseerror(parser, "intrinsic __builtin_debug_typestring requires exactly 1 parameter");
1473             return false;
1474         }
1475         ast_type_to_string(vec_last(sy->out).out, ty, sizeof(ty));
1476         ast_unref(vec_last(sy->out).out);
1477         sy->out[fid] = syexp(ast_ctx(vec_last(sy->out).out),
1478                              (ast_expression*)parser_const_string(parser, ty, false));
1479         vec_shrinkby(sy->out, 1);
1480         return true;
1481     }
1482
1483     call = ast_call_new(sy->ops[vec_size(sy->ops)].ctx, fun);
1484     if (!call)
1485         return false;
1486
1487     if (fid+1 < vec_size(sy->out))
1488         ++paramcount;
1489
1490     if (fid+1 + paramcount != vec_size(sy->out)) {
1491         parseerror(parser, "internal error: parameter count mismatch: (%lu+1+%lu), %lu",
1492                    (unsigned long)fid, (unsigned long)paramcount, (unsigned long)vec_size(sy->out));
1493         return false;
1494     }
1495
1496     for (i = 0; i < paramcount; ++i)
1497         vec_push(call->params, sy->out[fid+1 + i].out);
1498     vec_shrinkby(sy->out, paramcount);
1499     (void)!ast_call_check_types(call);
1500     if (parser->max_param_count < paramcount)
1501         parser->max_param_count = paramcount;
1502
1503     if (ast_istype(fun, ast_value)) {
1504         funval = (ast_value*)fun;
1505         if ((fun->expression.flags & AST_FLAG_VARIADIC) &&
1506             !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
1507         {
1508             call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
1509         }
1510     }
1511
1512     /* overwrite fid, the function, with a call */
1513     sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
1514
1515     if (fun->expression.vtype != TYPE_FUNCTION) {
1516         parseerror(parser, "not a function (%s)", type_name[fun->expression.vtype]);
1517         return false;
1518     }
1519
1520     if (!fun->expression.next) {
1521         parseerror(parser, "could not determine function return type");
1522         return false;
1523     } else {
1524         ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
1525
1526         if (fun->expression.flags & AST_FLAG_DEPRECATED) {
1527             if (!fval) {
1528                 return !parsewarning(parser, WARN_DEPRECATED,
1529                         "call to function (which is marked deprecated)\n",
1530                         "-> it has been declared here: %s:%i",
1531                         ast_ctx(fun).file, ast_ctx(fun).line);
1532             }
1533             if (!fval->desc) {
1534                 return !parsewarning(parser, WARN_DEPRECATED,
1535                         "call to `%s` (which is marked deprecated)\n"
1536                         "-> `%s` declared here: %s:%i",
1537                         fval->name, fval->name, ast_ctx(fun).file, ast_ctx(fun).line);
1538             }
1539             return !parsewarning(parser, WARN_DEPRECATED,
1540                     "call to `%s` (deprecated: %s)\n"
1541                     "-> `%s` declared here: %s:%i",
1542                     fval->name, fval->desc, fval->name, ast_ctx(fun).file,
1543                     ast_ctx(fun).line);
1544         }
1545
1546         if (vec_size(fun->expression.params) != paramcount &&
1547             !((fun->expression.flags & AST_FLAG_VARIADIC) &&
1548               vec_size(fun->expression.params) < paramcount))
1549         {
1550             const char *fewmany = (vec_size(fun->expression.params) > paramcount) ? "few" : "many";
1551             if (fval)
1552                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1553                                      "too %s parameters for call to %s: expected %i, got %i\n"
1554                                      " -> `%s` has been declared here: %s:%i",
1555                                      fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
1556                                      fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1557             else
1558                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1559                                      "too %s parameters for function call: expected %i, got %i\n"
1560                                      " -> it has been declared here: %s:%i",
1561                                      fewmany, (int)vec_size(fun->expression.params), (int)paramcount,
1562                                      ast_ctx(fun).file, (int)ast_ctx(fun).line);
1563         }
1564     }
1565
1566     return true;
1567 }
1568
1569 static bool parser_close_paren(parser_t *parser, shunt *sy)
1570 {
1571     if (!vec_size(sy->ops)) {
1572         parseerror(parser, "unmatched closing paren");
1573         return false;
1574     }
1575
1576     while (vec_size(sy->ops)) {
1577         if (vec_last(sy->ops).isparen) {
1578             if (vec_last(sy->paren) == PAREN_FUNC) {
1579                 vec_pop(sy->paren);
1580                 if (!parser_close_call(parser, sy))
1581                     return false;
1582                 break;
1583             }
1584             if (vec_last(sy->paren) == PAREN_EXPR) {
1585                 vec_pop(sy->paren);
1586                 if (!vec_size(sy->out)) {
1587                     compile_error(vec_last(sy->ops).ctx, "empty paren expression");
1588                     vec_shrinkby(sy->ops, 1);
1589                     return false;
1590                 }
1591                 vec_shrinkby(sy->ops, 1);
1592                 break;
1593             }
1594             if (vec_last(sy->paren) == PAREN_INDEX) {
1595                 vec_pop(sy->paren);
1596                 /* pop off the parenthesis */
1597                 vec_shrinkby(sy->ops, 1);
1598                 /* then apply the index operator */
1599                 if (!parser_sy_apply_operator(parser, sy))
1600                     return false;
1601                 break;
1602             }
1603             if (vec_last(sy->paren) == PAREN_TERNARY1) {
1604                 vec_last(sy->paren) = PAREN_TERNARY2;
1605                 /* pop off the parenthesis */
1606                 vec_shrinkby(sy->ops, 1);
1607                 break;
1608             }
1609             compile_error(vec_last(sy->ops).ctx, "invalid parenthesis");
1610             return false;
1611         }
1612         if (!parser_sy_apply_operator(parser, sy))
1613             return false;
1614     }
1615     return true;
1616 }
1617
1618 static void parser_reclassify_token(parser_t *parser)
1619 {
1620     size_t i;
1621     for (i = 0; i < operator_count; ++i) {
1622         if (!strcmp(parser_tokval(parser), operators[i].op)) {
1623             parser->tok = TOKEN_OPERATOR;
1624             return;
1625         }
1626     }
1627 }
1628
1629 static ast_expression* parse_vararg_do(parser_t *parser)
1630 {
1631     ast_expression *idx, *out;
1632     ast_value      *typevar;
1633     ast_value      *funtype = parser->function->vtype;
1634
1635     lex_ctx ctx = parser_ctx(parser);
1636
1637     if (!parser_next(parser) || parser->tok != '(') {
1638         parseerror(parser, "expected parameter index and type in parenthesis");
1639         return NULL;
1640     }
1641     if (!parser_next(parser)) {
1642         parseerror(parser, "error parsing parameter index");
1643         return NULL;
1644     }
1645
1646     idx = parse_expression_leave(parser, true, false, false);
1647     if (!idx)
1648         return NULL;
1649
1650     if (parser->tok != ',') {
1651         ast_unref(idx);
1652         parseerror(parser, "expected comma after parameter index");
1653         return NULL;
1654     }
1655
1656     if (!parser_next(parser) || (parser->tok != TOKEN_IDENT && parser->tok != TOKEN_TYPENAME)) {
1657         ast_unref(idx);
1658         parseerror(parser, "expected typename for vararg");
1659         return NULL;
1660     }
1661
1662     typevar = parse_typename(parser, NULL, NULL);
1663     if (!typevar) {
1664         ast_unref(idx);
1665         return NULL;
1666     }
1667
1668     if (parser->tok != ')') {
1669         ast_unref(idx);
1670         ast_delete(typevar);
1671         parseerror(parser, "expected closing paren");
1672         return NULL;
1673     }
1674
1675 #if 0
1676     if (!parser_next(parser)) {
1677         ast_unref(idx);
1678         ast_delete(typevar);
1679         parseerror(parser, "parse error after vararg");
1680         return NULL;
1681     }
1682 #endif
1683
1684     if (!parser->function->varargs) {
1685         ast_unref(idx);
1686         ast_delete(typevar);
1687         parseerror(parser, "function has no variable argument list");
1688         return NULL;
1689     }
1690
1691     if (funtype->expression.varparam &&
1692         !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
1693     {
1694         char ty1[1024];
1695         char ty2[1024];
1696         ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1));
1697         ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2));
1698         compile_error(ast_ctx(typevar),
1699                       "function was declared to take varargs of type `%s`, requested type is: %s",
1700                       ty2, ty1);
1701     }
1702
1703     out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->varargs), idx);
1704     ast_type_adopt(out, typevar);
1705     ast_delete(typevar);
1706     return out;
1707 }
1708
1709 static ast_expression* parse_vararg(parser_t *parser)
1710 {
1711     bool           old_noops = parser->lex->flags.noops;
1712
1713     ast_expression *out;
1714
1715     parser->lex->flags.noops = true;
1716     out = parse_vararg_do(parser);
1717
1718     parser->lex->flags.noops = old_noops;
1719     return out;
1720 }
1721
1722 static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
1723 {
1724     if (OPTS_FLAG(TRANSLATABLE_STRINGS) &&
1725         parser->tok == TOKEN_IDENT &&
1726         !strcmp(parser_tokval(parser), "_"))
1727     {
1728         /* a translatable string */
1729         ast_value *val;
1730
1731         parser->lex->flags.noops = true;
1732         if (!parser_next(parser) || parser->tok != '(') {
1733             parseerror(parser, "use _(\"string\") to create a translatable string constant");
1734             return false;
1735         }
1736         parser->lex->flags.noops = false;
1737         if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
1738             parseerror(parser, "expected a constant string in translatable-string extension");
1739             return false;
1740         }
1741         val = parser_const_string(parser, parser_tokval(parser), true);
1742         if (!val)
1743             return false;
1744         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1745
1746         if (!parser_next(parser) || parser->tok != ')') {
1747             parseerror(parser, "expected closing paren after translatable string");
1748             return false;
1749         }
1750         return true;
1751     }
1752     else if (parser->tok == TOKEN_DOTS)
1753     {
1754         ast_expression *va;
1755         if (!OPTS_FLAG(VARIADIC_ARGS)) {
1756             parseerror(parser, "cannot access varargs (try -fvariadic-args)");
1757             return false;
1758         }
1759         va = parse_vararg(parser);
1760         if (!va)
1761             return false;
1762         vec_push(sy->out, syexp(parser_ctx(parser), va));
1763         return true;
1764     }
1765     else if (parser->tok == TOKEN_FLOATCONST) {
1766         ast_value *val;
1767         val = parser_const_float(parser, (parser_token(parser)->constval.f));
1768         if (!val)
1769             return false;
1770         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1771         return true;
1772     }
1773     else if (parser->tok == TOKEN_INTCONST || parser->tok == TOKEN_CHARCONST) {
1774         ast_value *val;
1775         val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
1776         if (!val)
1777             return false;
1778         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1779         return true;
1780     }
1781     else if (parser->tok == TOKEN_STRINGCONST) {
1782         ast_value *val;
1783         val = parser_const_string(parser, parser_tokval(parser), false);
1784         if (!val)
1785             return false;
1786         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1787         return true;
1788     }
1789     else if (parser->tok == TOKEN_VECTORCONST) {
1790         ast_value *val;
1791         val = parser_const_vector(parser, parser_token(parser)->constval.v);
1792         if (!val)
1793             return false;
1794         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1795         return true;
1796     }
1797     else if (parser->tok == TOKEN_IDENT)
1798     {
1799         const char     *ctoken = parser_tokval(parser);
1800         ast_expression *prev = vec_size(sy->out) ? vec_last(sy->out).out : NULL;
1801         ast_expression *var;
1802         /* a_vector.{x,y,z} */
1803         if (!vec_size(sy->ops) ||
1804             !vec_last(sy->ops).etype ||
1805             operators[vec_last(sy->ops).etype-1].id != opid1('.') ||
1806             (prev >= intrinsic_debug_typestring &&
1807              prev <= intrinsic_debug_typestring))
1808         {
1809             /* When adding more intrinsics, fix the above condition */
1810             prev = NULL;
1811         }
1812         if (prev && prev->expression.vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
1813         {
1814             var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
1815         } else {
1816             var = parser_find_var(parser, parser_tokval(parser));
1817             if (!var)
1818                 var = parser_find_field(parser, parser_tokval(parser));
1819         }
1820         if (!var && with_labels) {
1821             var = (ast_expression*)parser_find_label(parser, parser_tokval(parser));
1822             if (!with_labels) {
1823                 ast_label *lbl = ast_label_new(parser_ctx(parser), parser_tokval(parser), true);
1824                 var = (ast_expression*)lbl;
1825                 vec_push(parser->labels, lbl);
1826             }
1827         }
1828         if (!var) {
1829             /* intrinsics */
1830             if (!strcmp(parser_tokval(parser), "__builtin_debug_typestring")) {
1831                 var = (ast_expression*)intrinsic_debug_typestring;
1832             }
1833                 
1834             if (!var) {
1835                 char *correct = NULL;
1836                 size_t i;
1837
1838                 /*
1839                  * sometimes people use preprocessing predefs without enabling them
1840                  * i've done this thousands of times already myself.  Lets check for
1841                  * it in the predef table.  And diagnose it better :)
1842                  */
1843                 if (!OPTS_FLAG(FTEPP_PREDEFS)) {
1844                     for (i = 0; i < sizeof(ftepp_predefs)/sizeof(*ftepp_predefs); i++) {
1845                         if (!strcmp(ftepp_predefs[i].name, parser_tokval(parser))) {
1846                             parseerror(parser, "unexpected ident: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
1847                             return false;
1848                         }
1849                     }
1850                 }
1851
1852                 /*
1853                  * TODO: determine the best score for the identifier: be it
1854                  * a variable, a field.
1855                  *
1856                  * We should also consider adding correction tables for
1857                  * other things as well.
1858                  */
1859                 if (OPTS_OPTION_BOOL(OPTION_CORRECTION)) {
1860                     correction_t corr;
1861                     correct_init(&corr);
1862
1863                     for (i = 0; i < vec_size(parser->correct_variables); i++) {
1864                         correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser));
1865                         if (strcmp(correct, parser_tokval(parser))) {
1866                             break;
1867                         } else if (correct) {
1868                             mem_d(correct);
1869                             correct = NULL;
1870                         }
1871                     }
1872                     correct_free(&corr);
1873
1874                     if (correct) {
1875                         parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct);
1876                         mem_d(correct);
1877                         return false;
1878                     }
1879                 }
1880                 parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
1881                 return false;
1882             }
1883         }
1884         else
1885         {
1886             if (ast_istype(var, ast_value)) {
1887                 ((ast_value*)var)->uses++;
1888             }
1889             else if (ast_istype(var, ast_member)) {
1890                 ast_member *mem = (ast_member*)var;
1891                 if (ast_istype(mem->owner, ast_value))
1892                     ((ast_value*)(mem->owner))->uses++;
1893             }
1894         }
1895         vec_push(sy->out, syexp(parser_ctx(parser), var));
1896         return true;
1897     }
1898     parseerror(parser, "unexpected token `%s`", parser_tokval(parser));
1899     return false;
1900 }
1901
1902 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels)
1903 {
1904     ast_expression *expr = NULL;
1905     shunt sy;
1906     size_t i;
1907     bool wantop = false;
1908     /* only warn once about an assignment in a truth value because the current code
1909      * would trigger twice on: if(a = b && ...), once for the if-truth-value, once for the && part
1910      */
1911     bool warn_truthvalue = true;
1912
1913     /* count the parens because an if starts with one, so the
1914      * end of a condition is an unmatched closing paren
1915      */
1916     int ternaries = 0;
1917
1918     memset(&sy, 0, sizeof(sy));
1919
1920     parser->lex->flags.noops = false;
1921
1922     parser_reclassify_token(parser);
1923
1924     while (true)
1925     {
1926         if (parser->tok == TOKEN_TYPENAME) {
1927             parseerror(parser, "unexpected typename");
1928             goto onerr;
1929         }
1930
1931         if (parser->tok == TOKEN_OPERATOR)
1932         {
1933             /* classify the operator */
1934             const oper_info *op;
1935             const oper_info *olast = NULL;
1936             size_t o;
1937             for (o = 0; o < operator_count; ++o) {
1938                 if (((!(operators[o].flags & OP_PREFIX) == !!wantop)) &&
1939                     /* !(operators[o].flags & OP_SUFFIX) && / * remove this */
1940                     !strcmp(parser_tokval(parser), operators[o].op))
1941                 {
1942                     break;
1943                 }
1944             }
1945             if (o == operator_count) {
1946                 compile_error(parser_ctx(parser), "unknown operator: %s", parser_tokval(parser));
1947                 goto onerr;
1948             }
1949             /* found an operator */
1950             op = &operators[o];
1951
1952             /* when declaring variables, a comma starts a new variable */
1953             if (op->id == opid1(',') && !vec_size(sy.paren) && stopatcomma) {
1954                 /* fixup the token */
1955                 parser->tok = ',';
1956                 break;
1957             }
1958
1959             /* a colon without a pervious question mark cannot be a ternary */
1960             if (!ternaries && op->id == opid2(':','?')) {
1961                 parser->tok = ':';
1962                 break;
1963             }
1964
1965             if (op->id == opid1(',')) {
1966                 if (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1967                     (void)!parsewarning(parser, WARN_TERNARY_PRECEDENCE, "suggesting parenthesis around ternary expression");
1968                 }
1969             }
1970
1971             if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
1972                 olast = &operators[vec_last(sy.ops).etype-1];
1973
1974 #define IsAssignOp(x) (\
1975                 (x) == opid1('=') || \
1976                 (x) == opid2('+','=') || \
1977                 (x) == opid2('-','=') || \
1978                 (x) == opid2('*','=') || \
1979                 (x) == opid2('/','=') || \
1980                 (x) == opid2('%','=') || \
1981                 (x) == opid2('&','=') || \
1982                 (x) == opid2('|','=') || \
1983                 (x) == opid3('&','~','=') \
1984                 )
1985             if (warn_truthvalue) {
1986                 if ( (olast && IsAssignOp(olast->id) && (op->id == opid2('&','&') || op->id == opid2('|','|'))) ||
1987                      (olast && IsAssignOp(op->id) && (olast->id == opid2('&','&') || olast->id == opid2('|','|'))) ||
1988                      (truthvalue && !vec_size(sy.paren) && IsAssignOp(op->id))
1989                    )
1990                 {
1991                     (void)!parsewarning(parser, WARN_PARENTHESIS, "suggesting parenthesis around assignment used as truth value");
1992                     warn_truthvalue = false;
1993                 }
1994             }
1995
1996             while (olast && (
1997                     (op->prec < olast->prec) ||
1998                     (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
1999             {
2000                 if (!parser_sy_apply_operator(parser, &sy))
2001                     goto onerr;
2002                 if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
2003                     olast = &operators[vec_last(sy.ops).etype-1];
2004                 else
2005                     olast = NULL;
2006             }
2007
2008             if (op->id == opid1('(')) {
2009                 if (wantop) {
2010                     size_t sycount = vec_size(sy.out);
2011                     /* we expected an operator, this is the function-call operator */
2012                     vec_push(sy.paren, PAREN_FUNC);
2013                     vec_push(sy.ops, syparen(parser_ctx(parser), sycount-1));
2014                     vec_push(sy.argc, 0);
2015                 } else {
2016                     vec_push(sy.paren, PAREN_EXPR);
2017                     vec_push(sy.ops, syparen(parser_ctx(parser), 0));
2018                 }
2019                 wantop = false;
2020             } else if (op->id == opid1('[')) {
2021                 if (!wantop) {
2022                     parseerror(parser, "unexpected array subscript");
2023                     goto onerr;
2024                 }
2025                 vec_push(sy.paren, PAREN_INDEX);
2026                 /* push both the operator and the paren, this makes life easier */
2027                 vec_push(sy.ops, syop(parser_ctx(parser), op));
2028                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
2029                 wantop = false;
2030             } else if (op->id == opid2('?',':')) {
2031                 vec_push(sy.ops, syop(parser_ctx(parser), op));
2032                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
2033                 wantop = false;
2034                 ++ternaries;
2035                 vec_push(sy.paren, PAREN_TERNARY1);
2036             } else if (op->id == opid2(':','?')) {
2037                 if (!vec_size(sy.paren)) {
2038                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
2039                     goto onerr;
2040                 }
2041                 if (vec_last(sy.paren) != PAREN_TERNARY1) {
2042                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
2043                     goto onerr;
2044                 }
2045                 if (!parser_close_paren(parser, &sy))
2046                     goto onerr;
2047                 vec_push(sy.ops, syop(parser_ctx(parser), op));
2048                 wantop = false;
2049                 --ternaries;
2050             } else {
2051                 vec_push(sy.ops, syop(parser_ctx(parser), op));
2052                 wantop = !!(op->flags & OP_SUFFIX);
2053             }
2054         }
2055         else if (parser->tok == ')') {
2056             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
2057                 if (!parser_sy_apply_operator(parser, &sy))
2058                     goto onerr;
2059             }
2060             if (!vec_size(sy.paren))
2061                 break;
2062             if (wantop) {
2063                 if (vec_last(sy.paren) == PAREN_TERNARY1) {
2064                     parseerror(parser, "mismatched parentheses (closing paren in ternary expression?)");
2065                     goto onerr;
2066                 }
2067                 if (!parser_close_paren(parser, &sy))
2068                     goto onerr;
2069             } else {
2070                 /* must be a function call without parameters */
2071                 if (vec_last(sy.paren) != PAREN_FUNC) {
2072                     parseerror(parser, "closing paren in invalid position");
2073                     goto onerr;
2074                 }
2075                 if (!parser_close_paren(parser, &sy))
2076                     goto onerr;
2077             }
2078             wantop = true;
2079         }
2080         else if (parser->tok == '(') {
2081             parseerror(parser, "internal error: '(' should be classified as operator");
2082             goto onerr;
2083         }
2084         else if (parser->tok == '[') {
2085             parseerror(parser, "internal error: '[' should be classified as operator");
2086             goto onerr;
2087         }
2088         else if (parser->tok == ']') {
2089             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
2090                 if (!parser_sy_apply_operator(parser, &sy))
2091                     goto onerr;
2092             }
2093             if (!vec_size(sy.paren))
2094                 break;
2095             if (vec_last(sy.paren) != PAREN_INDEX) {
2096                 parseerror(parser, "mismatched parentheses, unexpected ']'");
2097                 goto onerr;
2098             }
2099             if (!parser_close_paren(parser, &sy))
2100                 goto onerr;
2101             wantop = true;
2102         }
2103         else if (!wantop) {
2104             if (!parse_sya_operand(parser, &sy, with_labels))
2105                 goto onerr;
2106 #if 0
2107             if (vec_size(sy.paren) && vec_last(sy.ops).isparen && vec_last(sy.paren) == PAREN_FUNC)
2108                 vec_last(sy.argc)++;
2109 #endif
2110             wantop = true;
2111         }
2112         else {
2113             parseerror(parser, "expected operator or end of statement");
2114             goto onerr;
2115         }
2116
2117         if (!parser_next(parser)) {
2118             goto onerr;
2119         }
2120         if (parser->tok == ';' ||
2121             ((!vec_size(sy.paren) || (vec_size(sy.paren) == 1 && vec_last(sy.paren) == PAREN_TERNARY2)) &&
2122             (parser->tok == ']' || parser->tok == ')' || parser->tok == '}')))
2123         {
2124             break;
2125         }
2126     }
2127
2128     while (vec_size(sy.ops)) {
2129         if (!parser_sy_apply_operator(parser, &sy))
2130             goto onerr;
2131     }
2132
2133     parser->lex->flags.noops = true;
2134     if (!vec_size(sy.out)) {
2135         parseerror(parser, "empty expression");
2136         expr = NULL;
2137     } else
2138         expr = sy.out[0].out;
2139     vec_free(sy.out);
2140     vec_free(sy.ops);
2141     if (vec_size(sy.paren)) {
2142         parseerror(parser, "internal error: vec_size(sy.paren) = %lu", (unsigned long)vec_size(sy.paren));
2143         return NULL;
2144     }
2145     vec_free(sy.paren);
2146     vec_free(sy.argc);
2147     return expr;
2148
2149 onerr:
2150     parser->lex->flags.noops = true;
2151     for (i = 0; i < vec_size(sy.out); ++i) {
2152         if (sy.out[i].out)
2153             ast_unref(sy.out[i].out);
2154     }
2155     vec_free(sy.out);
2156     vec_free(sy.ops);
2157     vec_free(sy.paren);
2158     vec_free(sy.argc);
2159     return NULL;
2160 }
2161
2162 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels)
2163 {
2164     ast_expression *e = parse_expression_leave(parser, stopatcomma, false, with_labels);
2165     if (!e)
2166         return NULL;
2167     if (parser->tok != ';') {
2168         parseerror(parser, "semicolon expected after expression");
2169         ast_unref(e);
2170         return NULL;
2171     }
2172     if (!parser_next(parser)) {
2173         ast_unref(e);
2174         return NULL;
2175     }
2176     return e;
2177 }
2178
2179 static void parser_enterblock(parser_t *parser)
2180 {
2181     vec_push(parser->variables, util_htnew(PARSER_HT_SIZE));
2182     vec_push(parser->_blocklocals, vec_size(parser->_locals));
2183     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
2184     vec_push(parser->_blocktypedefs, vec_size(parser->_typedefs));
2185     vec_push(parser->_block_ctx, parser_ctx(parser));
2186
2187     /* corrector */
2188     vec_push(parser->correct_variables, correct_trie_new());
2189     vec_push(parser->correct_variables_score, NULL);
2190 }
2191
2192 static bool parser_leaveblock(parser_t *parser)
2193 {
2194     bool   rv = true;
2195     size_t locals, typedefs;
2196
2197     if (vec_size(parser->variables) <= PARSER_HT_LOCALS) {
2198         parseerror(parser, "internal error: parser_leaveblock with no block");
2199         return false;
2200     }
2201
2202     util_htdel(vec_last(parser->variables));
2203     correct_del(vec_last(parser->correct_variables), vec_last(parser->correct_variables_score));
2204
2205     vec_pop(parser->variables);
2206     vec_pop(parser->correct_variables);
2207     vec_pop(parser->correct_variables_score);
2208     if (!vec_size(parser->_blocklocals)) {
2209         parseerror(parser, "internal error: parser_leaveblock with no block (2)");
2210         return false;
2211     }
2212
2213     locals = vec_last(parser->_blocklocals);
2214     vec_pop(parser->_blocklocals);
2215     while (vec_size(parser->_locals) != locals) {
2216         ast_expression *e = vec_last(parser->_locals);
2217         ast_value      *v = (ast_value*)e;
2218         vec_pop(parser->_locals);
2219         if (ast_istype(e, ast_value) && !v->uses) {
2220             if (compile_warning(ast_ctx(v), WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name))
2221                 rv = false;
2222         }
2223     }
2224
2225     typedefs = vec_last(parser->_blocktypedefs);
2226     while (vec_size(parser->_typedefs) != typedefs) {
2227         ast_delete(vec_last(parser->_typedefs));
2228         vec_pop(parser->_typedefs);
2229     }
2230     util_htdel(vec_last(parser->typedefs));
2231     vec_pop(parser->typedefs);
2232
2233     vec_pop(parser->_block_ctx);
2234
2235     return rv;
2236 }
2237
2238 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e)
2239 {
2240     vec_push(parser->_locals, e);
2241     util_htset(vec_last(parser->variables), name, (void*)e);
2242
2243     /* corrector */
2244     correct_add (
2245          vec_last(parser->correct_variables),
2246         &vec_last(parser->correct_variables_score),
2247         name
2248     );
2249 }
2250
2251 static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e)
2252 {
2253     vec_push(parser->globals, e);
2254     util_htset(parser->htglobals, name, e);
2255
2256     /* corrector */
2257     correct_add (
2258          parser->correct_variables[0],
2259         &parser->correct_variables_score[0],
2260         name
2261     );
2262 }
2263
2264 static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
2265 {
2266     bool       ifnot = false;
2267     ast_unary *unary;
2268     ast_expression *prev;
2269
2270     if (cond->expression.vtype == TYPE_VOID || cond->expression.vtype >= TYPE_VARIANT) {
2271         char ty[1024];
2272         ast_type_to_string(cond, ty, sizeof(ty));
2273         compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty);
2274     }
2275
2276     if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING)
2277     {
2278         prev = cond;
2279         cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
2280         if (!cond) {
2281             ast_unref(prev);
2282             parseerror(parser, "internal error: failed to process condition");
2283             return NULL;
2284         }
2285         ifnot = !ifnot;
2286     }
2287     else if (OPTS_FLAG(CORRECT_LOGIC) && cond->expression.vtype == TYPE_VECTOR)
2288     {
2289         /* vector types need to be cast to true booleans */
2290         ast_binary *bin = (ast_binary*)cond;
2291         if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR))
2292         {
2293             /* in perl-logic, AND and OR take care of the -fcorrect-logic */
2294             prev = cond;
2295             cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond);
2296             if (!cond) {
2297                 ast_unref(prev);
2298                 parseerror(parser, "internal error: failed to process condition");
2299                 return NULL;
2300             }
2301             ifnot = !ifnot;
2302         }
2303     }
2304
2305     unary = (ast_unary*)cond;
2306     while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F)
2307     {
2308         cond = unary->operand;
2309         unary->operand = NULL;
2310         ast_delete(unary);
2311         ifnot = !ifnot;
2312         unary = (ast_unary*)cond;
2313     }
2314
2315     if (!cond)
2316         parseerror(parser, "internal error: failed to process condition");
2317
2318     if (ifnot) *_ifnot = !*_ifnot;
2319     return cond;
2320 }
2321
2322 static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
2323 {
2324     ast_ifthen *ifthen;
2325     ast_expression *cond, *ontrue = NULL, *onfalse = NULL;
2326     bool ifnot = false;
2327
2328     lex_ctx ctx = parser_ctx(parser);
2329
2330     (void)block; /* not touching */
2331
2332     /* skip the 'if', parse an optional 'not' and check for an opening paren */
2333     if (!parser_next(parser)) {
2334         parseerror(parser, "expected condition or 'not'");
2335         return false;
2336     }
2337     if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "not")) {
2338         ifnot = true;
2339         if (!parser_next(parser)) {
2340             parseerror(parser, "expected condition in parenthesis");
2341             return false;
2342         }
2343     }
2344     if (parser->tok != '(') {
2345         parseerror(parser, "expected 'if' condition in parenthesis");
2346         return false;
2347     }
2348     /* parse into the expression */
2349     if (!parser_next(parser)) {
2350         parseerror(parser, "expected 'if' condition after opening paren");
2351         return false;
2352     }
2353     /* parse the condition */
2354     cond = parse_expression_leave(parser, false, true, false);
2355     if (!cond)
2356         return false;
2357     /* closing paren */
2358     if (parser->tok != ')') {
2359         parseerror(parser, "expected closing paren after 'if' condition");
2360         ast_delete(cond);
2361         return false;
2362     }
2363     /* parse into the 'then' branch */
2364     if (!parser_next(parser)) {
2365         parseerror(parser, "expected statement for on-true branch of 'if'");
2366         ast_delete(cond);
2367         return false;
2368     }
2369     if (!parse_statement_or_block(parser, &ontrue)) {
2370         ast_delete(cond);
2371         return false;
2372     }
2373     if (!ontrue)
2374         ontrue = (ast_expression*)ast_block_new(parser_ctx(parser));
2375     /* check for an else */
2376     if (!strcmp(parser_tokval(parser), "else")) {
2377         /* parse into the 'else' branch */
2378         if (!parser_next(parser)) {
2379             parseerror(parser, "expected on-false branch after 'else'");
2380             ast_delete(ontrue);
2381             ast_delete(cond);
2382             return false;
2383         }
2384         if (!parse_statement_or_block(parser, &onfalse)) {
2385             ast_delete(ontrue);
2386             ast_delete(cond);
2387             return false;
2388         }
2389     }
2390
2391     cond = process_condition(parser, cond, &ifnot);
2392     if (!cond) {
2393         if (ontrue)  ast_delete(ontrue);
2394         if (onfalse) ast_delete(onfalse);
2395         return false;
2396     }
2397
2398     if (ifnot)
2399         ifthen = ast_ifthen_new(ctx, cond, onfalse, ontrue);
2400     else
2401         ifthen = ast_ifthen_new(ctx, cond, ontrue, onfalse);
2402     *out = (ast_expression*)ifthen;
2403     return true;
2404 }
2405
2406 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out);
2407 static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out)
2408 {
2409     bool rv;
2410     char *label = NULL;
2411
2412     /* skip the 'while' and get the body */
2413     if (!parser_next(parser)) {
2414         if (OPTS_FLAG(LOOP_LABELS))
2415             parseerror(parser, "expected loop label or 'while' condition in parenthesis");
2416         else
2417             parseerror(parser, "expected 'while' condition in parenthesis");
2418         return false;
2419     }
2420
2421     if (parser->tok == ':') {
2422         if (!OPTS_FLAG(LOOP_LABELS))
2423             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2424         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2425             parseerror(parser, "expected loop label");
2426             return false;
2427         }
2428         label = util_strdup(parser_tokval(parser));
2429         if (!parser_next(parser)) {
2430             mem_d(label);
2431             parseerror(parser, "expected 'while' condition in parenthesis");
2432             return false;
2433         }
2434     }
2435
2436     if (parser->tok != '(') {
2437         parseerror(parser, "expected 'while' condition in parenthesis");
2438         return false;
2439     }
2440
2441     vec_push(parser->breaks, label);
2442     vec_push(parser->continues, label);
2443
2444     rv = parse_while_go(parser, block, out);
2445     if (label)
2446         mem_d(label);
2447     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2448         parseerror(parser, "internal error: label stack corrupted");
2449         rv = false;
2450         ast_delete(*out);
2451         *out = NULL;
2452     }
2453     else {
2454         vec_pop(parser->breaks);
2455         vec_pop(parser->continues);
2456     }
2457     return rv;
2458 }
2459
2460 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out)
2461 {
2462     ast_loop *aloop;
2463     ast_expression *cond, *ontrue;
2464
2465     bool ifnot = false;
2466
2467     lex_ctx ctx = parser_ctx(parser);
2468
2469     (void)block; /* not touching */
2470
2471     /* parse into the expression */
2472     if (!parser_next(parser)) {
2473         parseerror(parser, "expected 'while' condition after opening paren");
2474         return false;
2475     }
2476     /* parse the condition */
2477     cond = parse_expression_leave(parser, false, true, false);
2478     if (!cond)
2479         return false;
2480     /* closing paren */
2481     if (parser->tok != ')') {
2482         parseerror(parser, "expected closing paren after 'while' condition");
2483         ast_delete(cond);
2484         return false;
2485     }
2486     /* parse into the 'then' branch */
2487     if (!parser_next(parser)) {
2488         parseerror(parser, "expected while-loop body");
2489         ast_delete(cond);
2490         return false;
2491     }
2492     if (!parse_statement_or_block(parser, &ontrue)) {
2493         ast_delete(cond);
2494         return false;
2495     }
2496
2497     cond = process_condition(parser, cond, &ifnot);
2498     if (!cond) {
2499         ast_delete(ontrue);
2500         return false;
2501     }
2502     aloop = ast_loop_new(ctx, NULL, cond, ifnot, NULL, false, NULL, ontrue);
2503     *out = (ast_expression*)aloop;
2504     return true;
2505 }
2506
2507 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out);
2508 static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **out)
2509 {
2510     bool rv;
2511     char *label = NULL;
2512
2513     /* skip the 'do' and get the body */
2514     if (!parser_next(parser)) {
2515         if (OPTS_FLAG(LOOP_LABELS))
2516             parseerror(parser, "expected loop label or body");
2517         else
2518             parseerror(parser, "expected loop body");
2519         return false;
2520     }
2521
2522     if (parser->tok == ':') {
2523         if (!OPTS_FLAG(LOOP_LABELS))
2524             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2525         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2526             parseerror(parser, "expected loop label");
2527             return false;
2528         }
2529         label = util_strdup(parser_tokval(parser));
2530         if (!parser_next(parser)) {
2531             mem_d(label);
2532             parseerror(parser, "expected loop body");
2533             return false;
2534         }
2535     }
2536
2537     vec_push(parser->breaks, label);
2538     vec_push(parser->continues, label);
2539
2540     rv = parse_dowhile_go(parser, block, out);
2541     if (label)
2542         mem_d(label);
2543     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2544         parseerror(parser, "internal error: label stack corrupted");
2545         rv = false;
2546         ast_delete(*out);
2547         *out = NULL;
2548     }
2549     else {
2550         vec_pop(parser->breaks);
2551         vec_pop(parser->continues);
2552     }
2553     return rv;
2554 }
2555
2556 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out)
2557 {
2558     ast_loop *aloop;
2559     ast_expression *cond, *ontrue;
2560
2561     bool ifnot = false;
2562
2563     lex_ctx ctx = parser_ctx(parser);
2564
2565     (void)block; /* not touching */
2566
2567     if (!parse_statement_or_block(parser, &ontrue))
2568         return false;
2569
2570     /* expect the "while" */
2571     if (parser->tok != TOKEN_KEYWORD ||
2572         strcmp(parser_tokval(parser), "while"))
2573     {
2574         parseerror(parser, "expected 'while' and condition");
2575         ast_delete(ontrue);
2576         return false;
2577     }
2578
2579     /* skip the 'while' and check for opening paren */
2580     if (!parser_next(parser) || parser->tok != '(') {
2581         parseerror(parser, "expected 'while' condition in parenthesis");
2582         ast_delete(ontrue);
2583         return false;
2584     }
2585     /* parse into the expression */
2586     if (!parser_next(parser)) {
2587         parseerror(parser, "expected 'while' condition after opening paren");
2588         ast_delete(ontrue);
2589         return false;
2590     }
2591     /* parse the condition */
2592     cond = parse_expression_leave(parser, false, true, false);
2593     if (!cond)
2594         return false;
2595     /* closing paren */
2596     if (parser->tok != ')') {
2597         parseerror(parser, "expected closing paren after 'while' condition");
2598         ast_delete(ontrue);
2599         ast_delete(cond);
2600         return false;
2601     }
2602     /* parse on */
2603     if (!parser_next(parser) || parser->tok != ';') {
2604         parseerror(parser, "expected semicolon after condition");
2605         ast_delete(ontrue);
2606         ast_delete(cond);
2607         return false;
2608     }
2609
2610     if (!parser_next(parser)) {
2611         parseerror(parser, "parse error");
2612         ast_delete(ontrue);
2613         ast_delete(cond);
2614         return false;
2615     }
2616
2617     cond = process_condition(parser, cond, &ifnot);
2618     if (!cond) {
2619         ast_delete(ontrue);
2620         return false;
2621     }
2622     aloop = ast_loop_new(ctx, NULL, NULL, false, cond, ifnot, NULL, ontrue);
2623     *out = (ast_expression*)aloop;
2624     return true;
2625 }
2626
2627 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out);
2628 static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
2629 {
2630     bool rv;
2631     char *label = NULL;
2632
2633     /* skip the 'for' and check for opening paren */
2634     if (!parser_next(parser)) {
2635         if (OPTS_FLAG(LOOP_LABELS))
2636             parseerror(parser, "expected loop label or 'for' expressions in parenthesis");
2637         else
2638             parseerror(parser, "expected 'for' expressions in parenthesis");
2639         return false;
2640     }
2641
2642     if (parser->tok == ':') {
2643         if (!OPTS_FLAG(LOOP_LABELS))
2644             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2645         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2646             parseerror(parser, "expected loop label");
2647             return false;
2648         }
2649         label = util_strdup(parser_tokval(parser));
2650         if (!parser_next(parser)) {
2651             mem_d(label);
2652             parseerror(parser, "expected 'for' expressions in parenthesis");
2653             return false;
2654         }
2655     }
2656
2657     if (parser->tok != '(') {
2658         parseerror(parser, "expected 'for' expressions in parenthesis");
2659         return false;
2660     }
2661
2662     vec_push(parser->breaks, label);
2663     vec_push(parser->continues, label);
2664
2665     rv = parse_for_go(parser, block, out);
2666     if (label)
2667         mem_d(label);
2668     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2669         parseerror(parser, "internal error: label stack corrupted");
2670         rv = false;
2671         ast_delete(*out);
2672         *out = NULL;
2673     }
2674     else {
2675         vec_pop(parser->breaks);
2676         vec_pop(parser->continues);
2677     }
2678     return rv;
2679 }
2680 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out)
2681 {
2682     ast_loop       *aloop;
2683     ast_expression *initexpr, *cond, *increment, *ontrue;
2684     ast_value      *typevar;
2685
2686     bool retval = true;
2687     bool ifnot  = false;
2688
2689     lex_ctx ctx = parser_ctx(parser);
2690
2691     parser_enterblock(parser);
2692
2693     initexpr  = NULL;
2694     cond      = NULL;
2695     increment = NULL;
2696     ontrue    = NULL;
2697
2698     /* parse into the expression */
2699     if (!parser_next(parser)) {
2700         parseerror(parser, "expected 'for' initializer after opening paren");
2701         goto onerr;
2702     }
2703
2704     typevar = NULL;
2705     if (parser->tok == TOKEN_IDENT)
2706         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
2707
2708     if (typevar || parser->tok == TOKEN_TYPENAME) {
2709 #if 0
2710         if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
2711             if (parsewarning(parser, WARN_EXTENSIONS,
2712                              "current standard does not allow variable declarations in for-loop initializers"))
2713                 goto onerr;
2714         }
2715 #endif
2716         if (!parse_variable(parser, block, true, CV_VAR, typevar, false, false, 0, NULL))
2717             goto onerr;
2718     }
2719     else if (parser->tok != ';')
2720     {
2721         initexpr = parse_expression_leave(parser, false, false, false);
2722         if (!initexpr)
2723             goto onerr;
2724     }
2725
2726     /* move on to condition */
2727     if (parser->tok != ';') {
2728         parseerror(parser, "expected semicolon after for-loop initializer");
2729         goto onerr;
2730     }
2731     if (!parser_next(parser)) {
2732         parseerror(parser, "expected for-loop condition");
2733         goto onerr;
2734     }
2735
2736     /* parse the condition */
2737     if (parser->tok != ';') {
2738         cond = parse_expression_leave(parser, false, true, false);
2739         if (!cond)
2740             goto onerr;
2741     }
2742
2743     /* move on to incrementor */
2744     if (parser->tok != ';') {
2745         parseerror(parser, "expected semicolon after for-loop initializer");
2746         goto onerr;
2747     }
2748     if (!parser_next(parser)) {
2749         parseerror(parser, "expected for-loop condition");
2750         goto onerr;
2751     }
2752
2753     /* parse the incrementor */
2754     if (parser->tok != ')') {
2755         lex_ctx condctx = parser_ctx(parser);
2756         increment = parse_expression_leave(parser, false, false, false);
2757         if (!increment)
2758             goto onerr;
2759         if (!ast_side_effects(increment)) {
2760             if (compile_warning(condctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
2761                 goto onerr;
2762         }
2763     }
2764
2765     /* closing paren */
2766     if (parser->tok != ')') {
2767         parseerror(parser, "expected closing paren after 'for-loop' incrementor");
2768         goto onerr;
2769     }
2770     /* parse into the 'then' branch */
2771     if (!parser_next(parser)) {
2772         parseerror(parser, "expected for-loop body");
2773         goto onerr;
2774     }
2775     if (!parse_statement_or_block(parser, &ontrue))
2776         goto onerr;
2777
2778     if (cond) {
2779         cond = process_condition(parser, cond, &ifnot);
2780         if (!cond)
2781             goto onerr;
2782     }
2783     aloop = ast_loop_new(ctx, initexpr, cond, ifnot, NULL, false, increment, ontrue);
2784     *out = (ast_expression*)aloop;
2785
2786     if (!parser_leaveblock(parser))
2787         retval = false;
2788     return retval;
2789 onerr:
2790     if (initexpr)  ast_delete(initexpr);
2791     if (cond)      ast_delete(cond);
2792     if (increment) ast_delete(increment);
2793     (void)!parser_leaveblock(parser);
2794     return false;
2795 }
2796
2797 static bool parse_return(parser_t *parser, ast_block *block, ast_expression **out)
2798 {
2799     ast_expression *exp = NULL;
2800     ast_return     *ret = NULL;
2801     ast_value      *expected = parser->function->vtype;
2802
2803     lex_ctx ctx = parser_ctx(parser);
2804
2805     (void)block; /* not touching */
2806
2807     if (!parser_next(parser)) {
2808         parseerror(parser, "expected return expression");
2809         return false;
2810     }
2811
2812     if (parser->tok != ';') {
2813         exp = parse_expression(parser, false, false);
2814         if (!exp)
2815             return false;
2816
2817         if (exp->expression.vtype != TYPE_NIL &&
2818             exp->expression.vtype != expected->expression.next->expression.vtype)
2819         {
2820             parseerror(parser, "return with invalid expression");
2821         }
2822
2823         ret = ast_return_new(ctx, exp);
2824         if (!ret) {
2825             ast_delete(exp);
2826             return false;
2827         }
2828     } else {
2829         if (!parser_next(parser))
2830             parseerror(parser, "parse error");
2831         if (expected->expression.next->expression.vtype != TYPE_VOID) {
2832             (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
2833         }
2834         ret = ast_return_new(ctx, NULL);
2835     }
2836     *out = (ast_expression*)ret;
2837     return true;
2838 }
2839
2840 static bool parse_break_continue(parser_t *parser, ast_block *block, ast_expression **out, bool is_continue)
2841 {
2842     size_t       i;
2843     unsigned int levels = 0;
2844     lex_ctx      ctx = parser_ctx(parser);
2845     const char **loops = (is_continue ? parser->continues : parser->breaks);
2846
2847     (void)block; /* not touching */
2848     if (!parser_next(parser)) {
2849         parseerror(parser, "expected semicolon or loop label");
2850         return false;
2851     }
2852
2853     if (!vec_size(loops)) {
2854         if (is_continue)
2855             parseerror(parser, "`continue` can only be used inside loops");
2856         else
2857             parseerror(parser, "`break` can only be used inside loops or switches");
2858     }
2859
2860     if (parser->tok == TOKEN_IDENT) {
2861         if (!OPTS_FLAG(LOOP_LABELS))
2862             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2863         i = vec_size(loops);
2864         while (i--) {
2865             if (loops[i] && !strcmp(loops[i], parser_tokval(parser)))
2866                 break;
2867             if (!i) {
2868                 parseerror(parser, "no such loop to %s: `%s`",
2869                            (is_continue ? "continue" : "break out of"),
2870                            parser_tokval(parser));
2871                 return false;
2872             }
2873             ++levels;
2874         }
2875         if (!parser_next(parser)) {
2876             parseerror(parser, "expected semicolon");
2877             return false;
2878         }
2879     }
2880
2881     if (parser->tok != ';') {
2882         parseerror(parser, "expected semicolon");
2883         return false;
2884     }
2885
2886     if (!parser_next(parser))
2887         parseerror(parser, "parse error");
2888
2889     *out = (ast_expression*)ast_breakcont_new(ctx, is_continue, levels);
2890     return true;
2891 }
2892
2893 /* returns true when it was a variable qualifier, false otherwise!
2894  * on error, cvq is set to CV_WRONG
2895  */
2896 static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *noref, bool *is_static, uint32_t *_flags, char **message)
2897 {
2898     bool had_const    = false;
2899     bool had_var      = false;
2900     bool had_noref    = false;
2901     bool had_attrib   = false;
2902     bool had_static   = false;
2903     uint32_t flags    = 0;
2904
2905     *cvq = CV_NONE;
2906     for (;;) {
2907         if (parser->tok == TOKEN_ATTRIBUTE_OPEN) {
2908             had_attrib = true;
2909             /* parse an attribute */
2910             if (!parser_next(parser)) {
2911                 parseerror(parser, "expected attribute after `[[`");
2912                 *cvq = CV_WRONG;
2913                 return false;
2914             }
2915             if (!strcmp(parser_tokval(parser), "noreturn")) {
2916                 flags |= AST_FLAG_NORETURN;
2917                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2918                     parseerror(parser, "`noreturn` attribute has no parameters, expected `]]`");
2919                     *cvq = CV_WRONG;
2920                     return false;
2921                 }
2922             }
2923             else if (!strcmp(parser_tokval(parser), "noref")) {
2924                 had_noref = true;
2925                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2926                     parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
2927                     *cvq = CV_WRONG;
2928                     return false;
2929                 }
2930             }
2931             else if (!strcmp(parser_tokval(parser), "inline")) {
2932                 flags |= AST_FLAG_INLINE;
2933                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2934                     parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
2935                     *cvq = CV_WRONG;
2936                     return false;
2937                 }
2938             }
2939             else if (!strcmp(parser_tokval(parser), "alias") && !(flags & AST_FLAG_ALIAS)) {
2940                 flags   |= AST_FLAG_ALIAS;
2941                 *message = NULL;
2942
2943                 if (!parser_next(parser)) {
2944                     parseerror(parser, "parse error in attribute");
2945                     goto argerr;
2946                 }
2947
2948                 if (parser->tok == '(') {
2949                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2950                         parseerror(parser, "`alias` attribute missing parameter");
2951                         goto argerr;
2952                     }
2953
2954                     *message = util_strdup(parser_tokval(parser));
2955
2956                     if (!parser_next(parser)) {
2957                         parseerror(parser, "parse error in attribute");
2958                         goto argerr;
2959                     }
2960
2961                     if (parser->tok != ')') {
2962                         parseerror(parser, "`alias` attribute expected `)` after parameter");
2963                         goto argerr;
2964                     }
2965
2966                     if (!parser_next(parser)) {
2967                         parseerror(parser, "parse error in attribute");
2968                         goto argerr;
2969                     }
2970                 }
2971
2972                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2973                     parseerror(parser, "`alias` attribute expected `]]`");
2974                     goto argerr;
2975                 }
2976             }
2977             else if (!strcmp(parser_tokval(parser), "deprecated") && !(flags & AST_FLAG_DEPRECATED)) {
2978                 flags   |= AST_FLAG_DEPRECATED;
2979                 *message = NULL;
2980
2981                 if (!parser_next(parser)) {
2982                     parseerror(parser, "parse error in attribute");
2983                     goto argerr;
2984                 }
2985
2986                 if (parser->tok == '(') {
2987                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2988                         parseerror(parser, "`deprecated` attribute missing parameter");
2989                         goto argerr;
2990                     }
2991
2992                     *message = util_strdup(parser_tokval(parser));
2993
2994                     if (!parser_next(parser)) {
2995                         parseerror(parser, "parse error in attribute");
2996                         goto argerr;
2997                     }
2998
2999                     if(parser->tok != ')') {
3000                         parseerror(parser, "`deprecated` attribute expected `)` after parameter");
3001                         goto argerr;
3002                     }
3003
3004                     if (!parser_next(parser)) {
3005                         parseerror(parser, "parse error in attribute");
3006                         goto argerr;
3007                     }
3008                 }
3009                 /* no message */
3010                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
3011                     parseerror(parser, "`deprecated` attribute expected `]]`");
3012
3013                     argerr: /* ugly */
3014                     if (*message) mem_d(*message);
3015                     *message = NULL;
3016                     *cvq     = CV_WRONG;
3017                     return false;
3018                 }
3019             }
3020             else
3021             {
3022                 /* Skip tokens until we hit a ]] */
3023                 (void)!parsewarning(parser, WARN_UNKNOWN_ATTRIBUTE, "unknown attribute starting with `%s`", parser_tokval(parser));
3024                 while (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
3025                     if (!parser_next(parser)) {
3026                         parseerror(parser, "error inside attribute");
3027                         *cvq = CV_WRONG;
3028                         return false;
3029                     }
3030                 }
3031             }
3032         }
3033         else if (with_local && !strcmp(parser_tokval(parser), "static"))
3034             had_static = true;
3035         else if (!strcmp(parser_tokval(parser), "const"))
3036             had_const = true;
3037         else if (!strcmp(parser_tokval(parser), "var"))
3038             had_var = true;
3039         else if (with_local && !strcmp(parser_tokval(parser), "local"))
3040             had_var = true;
3041         else if (!strcmp(parser_tokval(parser), "noref"))
3042             had_noref = true;
3043         else if (!had_const && !had_var && !had_noref && !had_attrib && !had_static && !flags) {
3044             return false;
3045         }
3046         else
3047             break;
3048         if (!parser_next(parser))
3049             goto onerr;
3050     }
3051     if (had_const)
3052         *cvq = CV_CONST;
3053     else if (had_var)
3054         *cvq = CV_VAR;
3055     else
3056         *cvq = CV_NONE;
3057     *noref     = had_noref;
3058     *is_static = had_static;
3059     *_flags    = flags;
3060     return true;
3061 onerr:
3062     parseerror(parser, "parse error after variable qualifier");
3063     *cvq = CV_WRONG;
3064     return true;
3065 }
3066
3067 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out);
3068 static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **out)
3069 {
3070     bool rv;
3071     char *label = NULL;
3072
3073     /* skip the 'while' and get the body */
3074     if (!parser_next(parser)) {
3075         if (OPTS_FLAG(LOOP_LABELS))
3076             parseerror(parser, "expected loop label or 'switch' operand in parenthesis");
3077         else
3078             parseerror(parser, "expected 'switch' operand in parenthesis");
3079         return false;
3080     }
3081
3082     if (parser->tok == ':') {
3083         if (!OPTS_FLAG(LOOP_LABELS))
3084             parseerror(parser, "labeled loops not activated, try using -floop-labels");
3085         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
3086             parseerror(parser, "expected loop label");
3087             return false;
3088         }
3089         label = util_strdup(parser_tokval(parser));
3090         if (!parser_next(parser)) {
3091             mem_d(label);
3092             parseerror(parser, "expected 'switch' operand in parenthesis");
3093             return false;
3094         }
3095     }
3096
3097     if (parser->tok != '(') {
3098         parseerror(parser, "expected 'switch' operand in parenthesis");
3099         return false;
3100     }
3101
3102     vec_push(parser->breaks, label);
3103
3104     rv = parse_switch_go(parser, block, out);
3105     if (label)
3106         mem_d(label);
3107     if (vec_last(parser->breaks) != label) {
3108         parseerror(parser, "internal error: label stack corrupted");
3109         rv = false;
3110         ast_delete(*out);
3111         *out = NULL;
3112     }
3113     else {
3114         vec_pop(parser->breaks);
3115     }
3116     return rv;
3117 }
3118
3119 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out)
3120 {
3121     ast_expression *operand;
3122     ast_value      *opval;
3123     ast_value      *typevar;
3124     ast_switch     *switchnode;
3125     ast_switch_case swcase;
3126
3127     int  cvq;
3128     bool noref, is_static;
3129     uint32_t qflags = 0;
3130
3131     lex_ctx ctx = parser_ctx(parser);
3132
3133     (void)block; /* not touching */
3134     (void)opval;
3135
3136     /* parse into the expression */
3137     if (!parser_next(parser)) {
3138         parseerror(parser, "expected switch operand");
3139         return false;
3140     }
3141     /* parse the operand */
3142     operand = parse_expression_leave(parser, false, false, false);
3143     if (!operand)
3144         return false;
3145
3146     switchnode = ast_switch_new(ctx, operand);
3147
3148     /* closing paren */
3149     if (parser->tok != ')') {
3150         ast_delete(switchnode);
3151         parseerror(parser, "expected closing paren after 'switch' operand");
3152         return false;
3153     }
3154
3155     /* parse over the opening paren */
3156     if (!parser_next(parser) || parser->tok != '{') {
3157         ast_delete(switchnode);
3158         parseerror(parser, "expected list of cases");
3159         return false;
3160     }
3161
3162     if (!parser_next(parser)) {
3163         ast_delete(switchnode);
3164         parseerror(parser, "expected 'case' or 'default'");
3165         return false;
3166     }
3167
3168     /* new block; allow some variables to be declared here */
3169     parser_enterblock(parser);
3170     while (true) {
3171         typevar = NULL;
3172         if (parser->tok == TOKEN_IDENT)
3173             typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
3174         if (typevar || parser->tok == TOKEN_TYPENAME) {
3175             if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL)) {
3176                 ast_delete(switchnode);
3177                 return false;
3178             }
3179             continue;
3180         }
3181         if (parse_qualifiers(parser, true, &cvq, &noref, &is_static, &qflags, NULL))
3182         {
3183             if (cvq == CV_WRONG) {
3184                 ast_delete(switchnode);
3185                 return false;
3186             }
3187             if (!parse_variable(parser, block, false, cvq, NULL, noref, is_static, qflags, NULL)) {
3188                 ast_delete(switchnode);
3189                 return false;
3190             }
3191             continue;
3192         }
3193         break;
3194     }
3195
3196     /* case list! */
3197     while (parser->tok != '}') {
3198         ast_block *caseblock;
3199
3200         if (!strcmp(parser_tokval(parser), "case")) {
3201             if (!parser_next(parser)) {
3202                 ast_delete(switchnode);
3203                 parseerror(parser, "expected expression for case");
3204                 return false;
3205             }
3206             swcase.value = parse_expression_leave(parser, false, false, false);
3207             if (!swcase.value) {
3208                 ast_delete(switchnode);
3209                 parseerror(parser, "expected expression for case");
3210                 return false;
3211             }
3212             if (!OPTS_FLAG(RELAXED_SWITCH)) {
3213                 if (!ast_istype(swcase.value, ast_value)) { /* || ((ast_value*)swcase.value)->cvq != CV_CONST) { */
3214                     parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch");
3215                     ast_unref(operand);
3216                     return false;
3217                 }
3218             }
3219         }
3220         else if (!strcmp(parser_tokval(parser), "default")) {
3221             swcase.value = NULL;
3222             if (!parser_next(parser)) {
3223                 ast_delete(switchnode);
3224                 parseerror(parser, "expected colon");
3225                 return false;
3226             }
3227         }
3228         else {
3229             ast_delete(switchnode);
3230             parseerror(parser, "expected 'case' or 'default'");
3231             return false;
3232         }
3233
3234         /* Now the colon and body */
3235         if (parser->tok != ':') {
3236             if (swcase.value) ast_unref(swcase.value);
3237             ast_delete(switchnode);
3238             parseerror(parser, "expected colon");
3239             return false;
3240         }
3241
3242         if (!parser_next(parser)) {
3243             if (swcase.value) ast_unref(swcase.value);
3244             ast_delete(switchnode);
3245             parseerror(parser, "expected statements or case");
3246             return false;
3247         }
3248         caseblock = ast_block_new(parser_ctx(parser));
3249         if (!caseblock) {
3250             if (swcase.value) ast_unref(swcase.value);
3251             ast_delete(switchnode);
3252             return false;
3253         }
3254         swcase.code = (ast_expression*)caseblock;
3255         vec_push(switchnode->cases, swcase);
3256         while (true) {
3257             ast_expression *expr;
3258             if (parser->tok == '}')
3259                 break;
3260             if (parser->tok == TOKEN_KEYWORD) {
3261                 if (!strcmp(parser_tokval(parser), "case") ||
3262                     !strcmp(parser_tokval(parser), "default"))
3263                 {
3264                     break;
3265                 }
3266             }
3267             if (!parse_statement(parser, caseblock, &expr, true)) {
3268                 ast_delete(switchnode);
3269                 return false;
3270             }
3271             if (!expr)
3272                 continue;
3273             if (!ast_block_add_expr(caseblock, expr)) {
3274                 ast_delete(switchnode);
3275                 return false;
3276             }
3277         }
3278     }
3279
3280     parser_leaveblock(parser);
3281
3282     /* closing paren */
3283     if (parser->tok != '}') {
3284         ast_delete(switchnode);
3285         parseerror(parser, "expected closing paren of case list");
3286         return false;
3287     }
3288     if (!parser_next(parser)) {
3289         ast_delete(switchnode);
3290         parseerror(parser, "parse error after switch");
3291         return false;
3292     }
3293     *out = (ast_expression*)switchnode;
3294     return true;
3295 }
3296
3297 /* parse computed goto sides */
3298 static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **side) {
3299     ast_expression *on_true;
3300     ast_expression *on_false;
3301     ast_expression *cond;
3302
3303     if (!*side)
3304         return NULL;
3305
3306     if (ast_istype(*side, ast_ternary)) {
3307         ast_ternary *tern = (ast_ternary*)*side;
3308         on_true  = parse_goto_computed(parser, &tern->on_true);
3309         on_false = parse_goto_computed(parser, &tern->on_false);
3310
3311         if (!on_true || !on_false) {
3312             parseerror(parser, "expected label or expression in ternary");
3313             if (on_true) ast_unref(on_true);
3314             if (on_false) ast_unref(on_false);
3315             return NULL;
3316         }
3317
3318         cond = tern->cond;
3319         tern->cond = NULL;
3320         ast_delete(tern);
3321         *side = NULL;
3322         return (ast_expression*)ast_ifthen_new(parser_ctx(parser), cond, on_true, on_false);
3323     } else if (ast_istype(*side, ast_label)) {
3324         ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->name);
3325         ast_goto_set_label(gt, ((ast_label*)*side));
3326         *side = NULL;
3327         return (ast_expression*)gt;
3328     }
3329     return NULL;
3330 }
3331
3332 static bool parse_goto(parser_t *parser, ast_expression **out)
3333 {
3334     ast_goto       *gt = NULL;
3335     ast_expression *lbl;
3336
3337     if (!parser_next(parser))
3338         return false;
3339
3340     if (parser->tok != TOKEN_IDENT) {
3341         ast_expression *expression;
3342
3343         /* could be an expression i.e computed goto :-) */
3344         if (parser->tok != '(') {
3345             parseerror(parser, "expected label name after `goto`");
3346             return false;
3347         }
3348
3349         /* failed to parse expression for goto */
3350         if (!(expression = parse_expression(parser, false, true)) ||
3351             !(*out = parse_goto_computed(parser, &expression))) {
3352             parseerror(parser, "invalid goto expression");
3353             ast_unref(expression);
3354             return false;
3355         }
3356
3357         return true;
3358     }
3359
3360     /* not computed goto */
3361     gt = ast_goto_new(parser_ctx(parser), parser_tokval(parser));
3362     lbl = parser_find_label(parser, gt->name);
3363     if (lbl) {
3364         if (!ast_istype(lbl, ast_label)) {
3365             parseerror(parser, "internal error: label is not an ast_label");
3366             ast_delete(gt);
3367             return false;
3368         }
3369         ast_goto_set_label(gt, (ast_label*)lbl);
3370     }
3371     else
3372         vec_push(parser->gotos, gt);
3373
3374     if (!parser_next(parser) || parser->tok != ';') {
3375         parseerror(parser, "semicolon expected after goto label");
3376         return false;
3377     }
3378     if (!parser_next(parser)) {
3379         parseerror(parser, "parse error after goto");
3380         return false;
3381     }
3382
3383     *out = (ast_expression*)gt;
3384     return true;
3385 }
3386
3387 static bool parse_skipwhite(parser_t *parser)
3388 {
3389     do {
3390         if (!parser_next(parser))
3391             return false;
3392     } while (parser->tok == TOKEN_WHITE && parser->tok < TOKEN_ERROR);
3393     return parser->tok < TOKEN_ERROR;
3394 }
3395
3396 static bool parse_eol(parser_t *parser)
3397 {
3398     if (!parse_skipwhite(parser))
3399         return false;
3400     return parser->tok == TOKEN_EOL;
3401 }
3402
3403 static bool parse_pragma_do(parser_t *parser)
3404 {
3405     if (!parser_next(parser) ||
3406         parser->tok != TOKEN_IDENT ||
3407         strcmp(parser_tokval(parser), "pragma"))
3408     {
3409         parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
3410         return false;
3411     }
3412     if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
3413         parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
3414         return false;
3415     }
3416
3417     if (!strcmp(parser_tokval(parser), "noref")) {
3418         if (!parse_skipwhite(parser) || parser->tok != TOKEN_INTCONST) {
3419             parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
3420             return false;
3421         }
3422         parser->noref = !!parser_token(parser)->constval.i;
3423         if (!parse_eol(parser)) {
3424             parseerror(parser, "parse error after `noref` pragma");
3425             return false;
3426         }
3427     }
3428     else
3429     {
3430         (void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
3431         return false;
3432     }
3433
3434     return true;
3435 }
3436
3437 static bool parse_pragma(parser_t *parser)
3438 {
3439     bool rv;
3440     parser->lex->flags.preprocessing = true;
3441     parser->lex->flags.mergelines = true;
3442     rv = parse_pragma_do(parser);
3443     if (parser->tok != TOKEN_EOL) {
3444         parseerror(parser, "junk after pragma");
3445         rv = false;
3446     }
3447     parser->lex->flags.preprocessing = false;
3448     parser->lex->flags.mergelines = false;
3449     if (!parser_next(parser)) {
3450         parseerror(parser, "parse error after pragma");
3451         rv = false;
3452     }
3453     return rv;
3454 }
3455
3456 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
3457 {
3458     bool       noref, is_static;
3459     int        cvq     = CV_NONE;
3460     uint32_t   qflags  = 0;
3461     ast_value *typevar = NULL;
3462     char      *vstring = NULL;
3463
3464     *out = NULL;
3465
3466     if (parser->tok == TOKEN_IDENT)
3467         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
3468
3469     if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
3470     {
3471         /* local variable */
3472         if (!block) {
3473             parseerror(parser, "cannot declare a variable from here");
3474             return false;
3475         }
3476         if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3477             if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
3478                 return false;
3479         }
3480         if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL))
3481             return false;
3482         return true;
3483     }
3484     else if (parse_qualifiers(parser, !!block, &cvq, &noref, &is_static, &qflags, &vstring))
3485     {
3486         if (cvq == CV_WRONG)
3487             return false;
3488         return parse_variable(parser, block, true, cvq, NULL, noref, is_static, qflags, vstring);
3489     }
3490     else if (parser->tok == TOKEN_KEYWORD)
3491     {
3492         if (!strcmp(parser_tokval(parser), "__builtin_debug_printtype"))
3493         {
3494             char ty[1024];
3495             ast_value *tdef;
3496
3497             if (!parser_next(parser)) {
3498                 parseerror(parser, "parse error after __builtin_debug_printtype");
3499                 return false;
3500             }
3501
3502             if (parser->tok == TOKEN_IDENT && (tdef = parser_find_typedef(parser, parser_tokval(parser), 0)))
3503             {
3504                 ast_type_to_string((ast_expression*)tdef, ty, sizeof(ty));
3505                 con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->name, ty);
3506                 if (!parser_next(parser)) {
3507                     parseerror(parser, "parse error after __builtin_debug_printtype typename argument");
3508                     return false;
3509                 }
3510             }
3511             else
3512             {
3513                 if (!parse_statement(parser, block, out, allow_cases))
3514                     return false;
3515                 if (!*out)
3516                     con_out("__builtin_debug_printtype: got no output node\n");
3517                 else
3518                 {
3519                     ast_type_to_string(*out, ty, sizeof(ty));
3520                     con_out("__builtin_debug_printtype: `%s`\n", ty);
3521                 }
3522             }
3523             return true;
3524         }
3525         else if (!strcmp(parser_tokval(parser), "return"))
3526         {
3527             return parse_return(parser, block, out);
3528         }
3529         else if (!strcmp(parser_tokval(parser), "if"))
3530         {
3531             return parse_if(parser, block, out);
3532         }
3533         else if (!strcmp(parser_tokval(parser), "while"))
3534         {
3535             return parse_while(parser, block, out);
3536         }
3537         else if (!strcmp(parser_tokval(parser), "do"))
3538         {
3539             return parse_dowhile(parser, block, out);
3540         }
3541         else if (!strcmp(parser_tokval(parser), "for"))
3542         {
3543             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3544                 if (parsewarning(parser, WARN_EXTENSIONS, "for loops are not recognized in the original Quake C standard, to enable try an alternate standard --std=?"))
3545                     return false;
3546             }
3547             return parse_for(parser, block, out);
3548         }
3549         else if (!strcmp(parser_tokval(parser), "break"))
3550         {
3551             return parse_break_continue(parser, block, out, false);
3552         }
3553         else if (!strcmp(parser_tokval(parser), "continue"))
3554         {
3555             return parse_break_continue(parser, block, out, true);
3556         }
3557         else if (!strcmp(parser_tokval(parser), "switch"))
3558         {
3559             return parse_switch(parser, block, out);
3560         }
3561         else if (!strcmp(parser_tokval(parser), "case") ||
3562                  !strcmp(parser_tokval(parser), "default"))
3563         {
3564             if (!allow_cases) {
3565                 parseerror(parser, "unexpected 'case' label");
3566                 return false;
3567             }
3568             return true;
3569         }
3570         else if (!strcmp(parser_tokval(parser), "goto"))
3571         {
3572             return parse_goto(parser, out);
3573         }
3574         else if (!strcmp(parser_tokval(parser), "typedef"))
3575         {
3576             if (!parser_next(parser)) {
3577                 parseerror(parser, "expected type definition after 'typedef'");
3578                 return false;
3579             }
3580             return parse_typedef(parser);
3581         }
3582         parseerror(parser, "Unexpected keyword");
3583         return false;
3584     }
3585     else if (parser->tok == '{')
3586     {
3587         ast_block *inner;
3588         inner = parse_block(parser);
3589         if (!inner)
3590             return false;
3591         *out = (ast_expression*)inner;
3592         return true;
3593     }
3594     else if (parser->tok == ':')
3595     {
3596         size_t i;
3597         ast_label *label;
3598         if (!parser_next(parser)) {
3599             parseerror(parser, "expected label name");
3600             return false;
3601         }
3602         if (parser->tok != TOKEN_IDENT) {
3603             parseerror(parser, "label must be an identifier");
3604             return false;
3605         }
3606         label = (ast_label*)parser_find_label(parser, parser_tokval(parser));
3607         if (label) {
3608             if (!label->undefined) {
3609                 parseerror(parser, "label `%s` already defined", label->name);
3610                 return false;
3611             }
3612             label->undefined = false;
3613         }
3614         else {
3615             label = ast_label_new(parser_ctx(parser), parser_tokval(parser), false);
3616             vec_push(parser->labels, label);
3617         }
3618         *out = (ast_expression*)label;
3619         if (!parser_next(parser)) {
3620             parseerror(parser, "parse error after label");
3621             return false;
3622         }
3623         for (i = 0; i < vec_size(parser->gotos); ++i) {
3624             if (!strcmp(parser->gotos[i]->name, label->name)) {
3625                 ast_goto_set_label(parser->gotos[i], label);
3626                 vec_remove(parser->gotos, i, 1);
3627                 --i;
3628             }
3629         }
3630         return true;
3631     }
3632     else if (parser->tok == ';')
3633     {
3634         if (!parser_next(parser)) {
3635             parseerror(parser, "parse error after empty statement");
3636             return false;
3637         }
3638         return true;
3639     }
3640     else
3641     {
3642         lex_ctx ctx = parser_ctx(parser);
3643         ast_expression *exp = parse_expression(parser, false, false);
3644         if (!exp)
3645             return false;
3646         *out = exp;
3647         if (!ast_side_effects(exp)) {
3648             if (compile_warning(ctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
3649                 return false;
3650         }
3651         return true;
3652     }
3653 }
3654
3655 static bool parse_enum(parser_t *parser)
3656 {
3657     qcfloat     num = 0;
3658     ast_value **values = NULL;
3659     ast_value  *var = NULL;
3660     ast_value  *asvalue;
3661
3662     ast_expression *old;
3663
3664     if (!parser_next(parser) || parser->tok != '{') {
3665         parseerror(parser, "expected `{` after `enum` keyword");
3666         return false;
3667     }
3668
3669     while (true) {
3670         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
3671             if (parser->tok == '}') {
3672                 /* allow an empty enum */
3673                 break;
3674             }
3675             parseerror(parser, "expected identifier or `}`");
3676             goto onerror;
3677         }
3678
3679         old = parser_find_field(parser, parser_tokval(parser));
3680         if (!old)
3681             old = parser_find_global(parser, parser_tokval(parser));
3682         if (old) {
3683             parseerror(parser, "value `%s` has already been declared here: %s:%i",
3684                        parser_tokval(parser), ast_ctx(old).file, ast_ctx(old).line);
3685             goto onerror;
3686         }
3687
3688         var = ast_value_new(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT);
3689         vec_push(values, var);
3690         var->cvq             = CV_CONST;
3691         var->hasvalue        = true;
3692         var->constval.vfloat = num++;
3693
3694         parser_addglobal(parser, var->name, (ast_expression*)var);
3695
3696         if (!parser_next(parser)) {
3697             parseerror(parser, "expected `=`, `}` or comma after identifier");
3698             goto onerror;
3699         }
3700
3701         if (parser->tok == ',')
3702             continue;
3703         if (parser->tok == '}')
3704             break;
3705         if (parser->tok != '=') {
3706             parseerror(parser, "expected `=`, `}` or comma after identifier");
3707             goto onerror;
3708         }
3709
3710         if (!parser_next(parser)) {
3711             parseerror(parser, "expected expression after `=`");
3712             goto onerror;
3713         }
3714
3715         /* We got a value! */
3716         old = parse_expression_leave(parser, true, false, false);
3717         asvalue = (ast_value*)old;
3718         if (!ast_istype(old, ast_value) || asvalue->cvq != CV_CONST || !asvalue->hasvalue) {
3719             compile_error(ast_ctx(var), "constant value or expression expected");
3720             goto onerror;
3721         }
3722         num = (var->constval.vfloat = asvalue->constval.vfloat) + 1;
3723
3724         if (parser->tok == '}')
3725             break;
3726         if (parser->tok != ',') {
3727             parseerror(parser, "expected `}` or comma after expression");
3728             goto onerror;
3729         }
3730     }
3731
3732     if (parser->tok != '}') {
3733         parseerror(parser, "internal error: breaking without `}`");
3734         goto onerror;
3735     }
3736
3737     if (!parser_next(parser) || parser->tok != ';') {
3738         parseerror(parser, "expected semicolon after enumeration");
3739         goto onerror;
3740     }
3741
3742     if (!parser_next(parser)) {
3743         parseerror(parser, "parse error after enumeration");
3744         goto onerror;
3745     }
3746
3747     vec_free(values);
3748     return true;
3749
3750 onerror:
3751     vec_free(values);
3752     return false;
3753 }
3754
3755 static bool parse_block_into(parser_t *parser, ast_block *block)
3756 {
3757     bool   retval = true;
3758
3759     parser_enterblock(parser);
3760
3761     if (!parser_next(parser)) { /* skip the '{' */
3762         parseerror(parser, "expected function body");
3763         goto cleanup;
3764     }
3765
3766     while (parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR)
3767     {
3768         ast_expression *expr = NULL;
3769         if (parser->tok == '}')
3770             break;
3771
3772         if (!parse_statement(parser, block, &expr, false)) {
3773             /* parseerror(parser, "parse error"); */
3774             block = NULL;
3775             goto cleanup;
3776         }
3777         if (!expr)
3778             continue;
3779         if (!ast_block_add_expr(block, expr)) {
3780             ast_delete(block);
3781             block = NULL;
3782             goto cleanup;
3783         }
3784     }
3785
3786     if (parser->tok != '}') {
3787         block = NULL;
3788     } else {
3789         (void)parser_next(parser);
3790     }
3791
3792 cleanup:
3793     if (!parser_leaveblock(parser))
3794         retval = false;
3795     return retval && !!block;
3796 }
3797
3798 static ast_block* parse_block(parser_t *parser)
3799 {
3800     ast_block *block;
3801     block = ast_block_new(parser_ctx(parser));
3802     if (!block)
3803         return NULL;
3804     if (!parse_block_into(parser, block)) {
3805         ast_block_delete(block);
3806         return NULL;
3807     }
3808     return block;
3809 }
3810
3811 static bool parse_statement_or_block(parser_t *parser, ast_expression **out)
3812 {
3813     if (parser->tok == '{') {
3814         *out = (ast_expression*)parse_block(parser);
3815         return !!*out;
3816     }
3817     return parse_statement(parser, NULL, out, false);
3818 }
3819
3820 static bool create_vector_members(ast_value *var, ast_member **me)
3821 {
3822     size_t i;
3823     size_t len = strlen(var->name);
3824
3825     for (i = 0; i < 3; ++i) {
3826         char *name = (char*)mem_a(len+3);
3827         memcpy(name, var->name, len);
3828         name[len+0] = '_';
3829         name[len+1] = 'x'+i;
3830         name[len+2] = 0;
3831         me[i] = ast_member_new(ast_ctx(var), (ast_expression*)var, i, name);
3832         mem_d(name);
3833         if (!me[i])
3834             break;
3835     }
3836     if (i == 3)
3837         return true;
3838
3839     /* unroll */
3840     do { ast_member_delete(me[--i]); } while(i);
3841     return false;
3842 }
3843
3844 static bool parse_function_body(parser_t *parser, ast_value *var)
3845 {
3846     ast_block      *block = NULL;
3847     ast_function   *func;
3848     ast_function   *old;
3849     size_t          parami;
3850
3851     ast_expression *framenum  = NULL;
3852     ast_expression *nextthink = NULL;
3853     /* None of the following have to be deleted */
3854     ast_expression *fld_think = NULL, *fld_nextthink = NULL, *fld_frame = NULL;
3855     ast_expression *gbl_time = NULL, *gbl_self = NULL;
3856     bool            has_frame_think;
3857
3858     bool retval = true;
3859
3860     has_frame_think = false;
3861     old = parser->function;
3862
3863     if (var->expression.flags & AST_FLAG_ALIAS) {
3864         parseerror(parser, "function aliases cannot have bodies");
3865         return false;
3866     }
3867
3868     if (vec_size(parser->gotos) || vec_size(parser->labels)) {
3869         parseerror(parser, "gotos/labels leaking");
3870         return false;
3871     }
3872
3873     if (!OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
3874         if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
3875                          "variadic function with implementation will not be able to access additional parameters (try -fvariadic-args)"))
3876         {
3877             return false;
3878         }
3879     }
3880
3881     if (parser->tok == '[') {
3882         /* got a frame definition: [ framenum, nextthink ]
3883          * this translates to:
3884          * self.frame = framenum;
3885          * self.nextthink = time + 0.1;
3886          * self.think = nextthink;
3887          */
3888         nextthink = NULL;
3889
3890         fld_think     = parser_find_field(parser, "think");
3891         fld_nextthink = parser_find_field(parser, "nextthink");
3892         fld_frame     = parser_find_field(parser, "frame");
3893         if (!fld_think || !fld_nextthink || !fld_frame) {
3894             parseerror(parser, "cannot use [frame,think] notation without the required fields");
3895             parseerror(parser, "please declare the following entityfields: `frame`, `think`, `nextthink`");
3896             return false;
3897         }
3898         gbl_time      = parser_find_global(parser, "time");
3899         gbl_self      = parser_find_global(parser, "self");
3900         if (!gbl_time || !gbl_self) {
3901             parseerror(parser, "cannot use [frame,think] notation without the required globals");
3902             parseerror(parser, "please declare the following globals: `time`, `self`");
3903             return false;
3904         }
3905
3906         if (!parser_next(parser))
3907             return false;
3908
3909         framenum = parse_expression_leave(parser, true, false, false);
3910         if (!framenum) {
3911             parseerror(parser, "expected a framenumber constant in[frame,think] notation");
3912             return false;
3913         }
3914         if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->hasvalue) {
3915             ast_unref(framenum);
3916             parseerror(parser, "framenumber in [frame,think] notation must be a constant");
3917             return false;
3918         }
3919
3920         if (parser->tok != ',') {
3921             ast_unref(framenum);
3922             parseerror(parser, "expected comma after frame number in [frame,think] notation");
3923             parseerror(parser, "Got a %i\n", parser->tok);
3924             return false;
3925         }
3926
3927         if (!parser_next(parser)) {
3928             ast_unref(framenum);
3929             return false;
3930         }
3931
3932         if (parser->tok == TOKEN_IDENT && !parser_find_var(parser, parser_tokval(parser)))
3933         {
3934             /* qc allows the use of not-yet-declared functions here
3935              * - this automatically creates a prototype */
3936             ast_value      *thinkfunc;
3937             ast_expression *functype = fld_think->expression.next;
3938
3939             thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype);
3940             if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/
3941                 ast_unref(framenum);
3942                 parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
3943                 return false;
3944             }
3945             ast_type_adopt(thinkfunc, functype);
3946
3947             if (!parser_next(parser)) {
3948                 ast_unref(framenum);
3949                 ast_delete(thinkfunc);
3950                 return false;
3951             }
3952
3953             parser_addglobal(parser, thinkfunc->name, (ast_expression*)thinkfunc);
3954
3955             nextthink = (ast_expression*)thinkfunc;
3956
3957         } else {
3958             nextthink = parse_expression_leave(parser, true, false, false);
3959             if (!nextthink) {
3960                 ast_unref(framenum);
3961                 parseerror(parser, "expected a think-function in [frame,think] notation");
3962                 return false;
3963             }
3964         }
3965
3966         if (!ast_istype(nextthink, ast_value)) {
3967             parseerror(parser, "think-function in [frame,think] notation must be a constant");
3968             retval = false;
3969         }
3970
3971         if (retval && parser->tok != ']') {
3972             parseerror(parser, "expected closing `]` for [frame,think] notation");
3973             retval = false;
3974         }
3975
3976         if (retval && !parser_next(parser)) {
3977             retval = false;
3978         }
3979
3980         if (retval && parser->tok != '{') {
3981             parseerror(parser, "a function body has to be declared after a [frame,think] declaration");
3982             retval = false;
3983         }
3984
3985         if (!retval) {
3986             ast_unref(nextthink);
3987             ast_unref(framenum);
3988             return false;
3989         }
3990
3991         has_frame_think = true;
3992     }
3993
3994     block = ast_block_new(parser_ctx(parser));
3995     if (!block) {
3996         parseerror(parser, "failed to allocate block");
3997         if (has_frame_think) {
3998             ast_unref(nextthink);
3999             ast_unref(framenum);
4000         }
4001         return false;
4002     }
4003
4004     if (has_frame_think) {
4005         lex_ctx ctx;
4006         ast_expression *self_frame;
4007         ast_expression *self_nextthink;
4008         ast_expression *self_think;
4009         ast_expression *time_plus_1;
4010         ast_store *store_frame;
4011         ast_store *store_nextthink;
4012         ast_store *store_think;
4013
4014         ctx = parser_ctx(parser);
4015         self_frame     = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_frame);
4016         self_nextthink = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_nextthink);
4017         self_think     = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_think);
4018
4019         time_plus_1    = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F,
4020                          gbl_time, (ast_expression*)parser_const_float(parser, 0.1));
4021
4022         if (!self_frame || !self_nextthink || !self_think || !time_plus_1) {
4023             if (self_frame)     ast_delete(self_frame);
4024             if (self_nextthink) ast_delete(self_nextthink);
4025             if (self_think)     ast_delete(self_think);
4026             if (time_plus_1)    ast_delete(time_plus_1);
4027             retval = false;
4028         }
4029
4030         if (retval)
4031         {
4032             store_frame     = ast_store_new(ctx, INSTR_STOREP_F,   self_frame,     framenum);
4033             store_nextthink = ast_store_new(ctx, INSTR_STOREP_F,   self_nextthink, time_plus_1);
4034             store_think     = ast_store_new(ctx, INSTR_STOREP_FNC, self_think,     nextthink);
4035
4036             if (!store_frame) {
4037                 ast_delete(self_frame);
4038                 retval = false;
4039             }
4040             if (!store_nextthink) {
4041                 ast_delete(self_nextthink);
4042                 retval = false;
4043             }
4044             if (!store_think) {
4045                 ast_delete(self_think);
4046                 retval = false;
4047             }
4048             if (!retval) {
4049                 if (store_frame)     ast_delete(store_frame);
4050                 if (store_nextthink) ast_delete(store_nextthink);
4051                 if (store_think)     ast_delete(store_think);
4052                 retval = false;
4053             }
4054             if (!ast_block_add_expr(block, (ast_expression*)store_frame) ||
4055                 !ast_block_add_expr(block, (ast_expression*)store_nextthink) ||
4056                 !ast_block_add_expr(block, (ast_expression*)store_think))
4057             {
4058                 retval = false;
4059             }
4060         }
4061
4062         if (!retval) {
4063             parseerror(parser, "failed to generate code for [frame,think]");
4064             ast_unref(nextthink);
4065             ast_unref(framenum);
4066             ast_delete(block);
4067             return false;
4068         }
4069     }
4070
4071     if (var->hasvalue) {
4072         parseerror(parser, "function `%s` declared with multiple bodies", var->name);
4073         ast_block_delete(block);
4074         goto enderr;
4075     }
4076
4077     func = ast_function_new(ast_ctx(var), var->name, var);
4078     if (!func) {
4079         parseerror(parser, "failed to allocate function for `%s`", var->name);
4080         ast_block_delete(block);
4081         goto enderr;
4082     }
4083     vec_push(parser->functions, func);
4084
4085     parser_enterblock(parser);
4086
4087     for (parami = 0; parami < vec_size(var->expression.params); ++parami) {
4088         size_t     e;
4089         ast_value *param = var->expression.params[parami];
4090         ast_member *me[3];
4091
4092         if (param->expression.vtype != TYPE_VECTOR &&
4093             (param->expression.vtype != TYPE_FIELD ||
4094              param->expression.next->expression.vtype != TYPE_VECTOR))
4095         {
4096             continue;
4097         }
4098
4099         if (!create_vector_members(param, me)) {
4100             ast_block_delete(block);
4101             goto enderrfn;
4102         }
4103
4104         for (e = 0; e < 3; ++e) {
4105             parser_addlocal(parser, me[e]->name, (ast_expression*)me[e]);
4106             ast_block_collect(block, (ast_expression*)me[e]);
4107         }
4108     }
4109
4110     if (var->argcounter) {
4111         ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT);
4112         parser_addlocal(parser, argc->name, (ast_expression*)argc);
4113         func->argc = argc;
4114     }
4115
4116     if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
4117         char name[1024];
4118         ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY);
4119         varargs->expression.flags |= AST_FLAG_IS_VARARG;
4120         varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), NULL, TYPE_VECTOR);
4121         varargs->expression.count = 0;
4122         snprintf(name, sizeof(name), "%s##va##SET", var->name);
4123         if (!parser_create_array_setter_proto(parser, varargs, name)) {
4124             ast_delete(varargs);
4125             ast_block_delete(block);
4126             goto enderrfn;
4127         }
4128         snprintf(name, sizeof(name), "%s##va##GET", var->name);
4129         if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) {
4130             ast_delete(varargs);
4131             ast_block_delete(block);
4132             goto enderrfn;
4133         }
4134         func->varargs = varargs;
4135
4136         func->fixedparams = parser_const_float(parser, vec_size(var->expression.params));
4137     }
4138
4139     parser->function = func;
4140     if (!parse_block_into(parser, block)) {
4141         ast_block_delete(block);
4142         goto enderrfn;
4143     }
4144
4145     vec_push(func->blocks, block);
4146
4147     parser->function = old;
4148     if (!parser_leaveblock(parser))
4149         retval = false;
4150     if (vec_size(parser->variables) != PARSER_HT_LOCALS) {
4151         parseerror(parser, "internal error: local scopes left");
4152         retval = false;
4153     }
4154
4155     if (parser->tok == ';')
4156         return parser_next(parser);
4157     else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4158         parseerror(parser, "missing semicolon after function body (mandatory with -std=qcc)");
4159     return retval;
4160
4161 enderrfn:
4162     (void)!parser_leaveblock(parser);
4163     vec_pop(parser->functions);
4164     ast_function_delete(func);
4165     var->constval.vfunc = NULL;
4166
4167 enderr:
4168     parser->function = old;
4169     return false;
4170 }
4171
4172 static ast_expression *array_accessor_split(
4173     parser_t  *parser,
4174     ast_value *array,
4175     ast_value *index,
4176     size_t     middle,
4177     ast_expression *left,
4178     ast_expression *right
4179     )
4180 {
4181     ast_ifthen *ifthen;
4182     ast_binary *cmp;
4183
4184     lex_ctx ctx = ast_ctx(array);
4185
4186     if (!left || !right) {
4187         if (left)  ast_delete(left);
4188         if (right) ast_delete(right);
4189         return NULL;
4190     }
4191
4192     cmp = ast_binary_new(ctx, INSTR_LT,
4193                          (ast_expression*)index,
4194                          (ast_expression*)parser_const_float(parser, middle));
4195     if (!cmp) {
4196         ast_delete(left);
4197         ast_delete(right);
4198         parseerror(parser, "internal error: failed to create comparison for array setter");
4199         return NULL;
4200     }
4201
4202     ifthen = ast_ifthen_new(ctx, (ast_expression*)cmp, left, right);
4203     if (!ifthen) {
4204         ast_delete(cmp); /* will delete left and right */
4205         parseerror(parser, "internal error: failed to create conditional jump for array setter");
4206         return NULL;
4207     }
4208
4209     return (ast_expression*)ifthen;
4210 }
4211
4212 static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast_value *index, ast_value *value, size_t from, size_t afterend)
4213 {
4214     lex_ctx ctx = ast_ctx(array);
4215
4216     if (from+1 == afterend) {
4217         /* set this value */
4218         ast_block       *block;
4219         ast_return      *ret;
4220         ast_array_index *subscript;
4221         ast_store       *st;
4222         int assignop = type_store_instr[value->expression.vtype];
4223
4224         if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
4225             assignop = INSTR_STORE_V;
4226
4227         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
4228         if (!subscript)
4229             return NULL;
4230
4231         st = ast_store_new(ctx, assignop, (ast_expression*)subscript, (ast_expression*)value);
4232         if (!st) {
4233             ast_delete(subscript);
4234             return NULL;
4235         }
4236
4237         block = ast_block_new(ctx);
4238         if (!block) {
4239             ast_delete(st);
4240             return NULL;
4241         }
4242
4243         if (!ast_block_add_expr(block, (ast_expression*)st)) {
4244             ast_delete(block);
4245             return NULL;
4246         }
4247
4248         ret = ast_return_new(ctx, NULL);
4249         if (!ret) {
4250             ast_delete(block);
4251             return NULL;
4252         }
4253
4254         if (!ast_block_add_expr(block, (ast_expression*)ret)) {
4255             ast_delete(block);
4256             return NULL;
4257         }
4258
4259         return (ast_expression*)block;
4260     } else {
4261         ast_expression *left, *right;
4262         size_t diff = afterend - from;
4263         size_t middle = from + diff/2;
4264         left  = array_setter_node(parser, array, index, value, from, middle);
4265         right = array_setter_node(parser, array, index, value, middle, afterend);
4266         return array_accessor_split(parser, array, index, middle, left, right);
4267     }
4268 }
4269
4270 static ast_expression *array_field_setter_node(
4271     parser_t  *parser,
4272     ast_value *array,
4273     ast_value *entity,
4274     ast_value *index,
4275     ast_value *value,
4276     size_t     from,
4277     size_t     afterend)
4278 {
4279     lex_ctx ctx = ast_ctx(array);
4280
4281     if (from+1 == afterend) {
4282         /* set this value */
4283         ast_block       *block;
4284         ast_return      *ret;
4285         ast_entfield    *entfield;
4286         ast_array_index *subscript;
4287         ast_store       *st;
4288         int assignop = type_storep_instr[value->expression.vtype];
4289
4290         if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
4291             assignop = INSTR_STOREP_V;
4292
4293         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
4294         if (!subscript)
4295             return NULL;
4296
4297         subscript->expression.next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript);
4298         subscript->expression.vtype = TYPE_FIELD;
4299
4300         entfield = ast_entfield_new_force(ctx,
4301                                           (ast_expression*)entity,
4302                                           (ast_expression*)subscript,
4303                                           (ast_expression*)subscript);
4304         if (!entfield) {
4305             ast_delete(subscript);
4306             return NULL;
4307         }
4308
4309         st = ast_store_new(ctx, assignop, (ast_expression*)entfield, (ast_expression*)value);
4310         if (!st) {
4311             ast_delete(entfield);
4312             return NULL;
4313         }
4314
4315         block = ast_block_new(ctx);
4316         if (!block) {
4317             ast_delete(st);
4318             return NULL;
4319         }
4320
4321         if (!ast_block_add_expr(block, (ast_expression*)st)) {
4322             ast_delete(block);
4323             return NULL;
4324         }
4325
4326         ret = ast_return_new(ctx, NULL);
4327         if (!ret) {
4328             ast_delete(block);
4329             return NULL;
4330         }
4331
4332         if (!ast_block_add_expr(block, (ast_expression*)ret)) {
4333             ast_delete(block);
4334             return NULL;
4335         }
4336
4337         return (ast_expression*)block;
4338     } else {
4339         ast_expression *left, *right;
4340         size_t diff = afterend - from;
4341         size_t middle = from + diff/2;
4342         left  = array_field_setter_node(parser, array, entity, index, value, from, middle);
4343         right = array_field_setter_node(parser, array, entity, index, value, middle, afterend);
4344         return array_accessor_split(parser, array, index, middle, left, right);
4345     }
4346 }
4347
4348 static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast_value *index, size_t from, size_t afterend)
4349 {
4350     lex_ctx ctx = ast_ctx(array);
4351
4352     if (from+1 == afterend) {
4353         ast_return      *ret;
4354         ast_array_index *subscript;
4355
4356         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
4357         if (!subscript)
4358             return NULL;
4359
4360         ret = ast_return_new(ctx, (ast_expression*)subscript);
4361         if (!ret) {
4362             ast_delete(subscript);
4363             return NULL;
4364         }
4365
4366         return (ast_expression*)ret;
4367     } else {
4368         ast_expression *left, *right;
4369         size_t diff = afterend - from;
4370         size_t middle = from + diff/2;
4371         left  = array_getter_node(parser, array, index, from, middle);
4372         right = array_getter_node(parser, array, index, middle, afterend);
4373         return array_accessor_split(parser, array, index, middle, left, right);
4374     }
4375 }
4376
4377 static bool parser_create_array_accessor(parser_t *parser, ast_value *array, const char *funcname, ast_value **out)
4378 {
4379     ast_function   *func = NULL;
4380     ast_value      *fval = NULL;
4381     ast_block      *body = NULL;
4382
4383     fval = ast_value_new(ast_ctx(array), funcname, TYPE_FUNCTION);
4384     if (!fval) {
4385         parseerror(parser, "failed to create accessor function value");
4386         return false;
4387     }
4388
4389     func = ast_function_new(ast_ctx(array), funcname, fval);
4390     if (!func) {
4391         ast_delete(fval);
4392         parseerror(parser, "failed to create accessor function node");
4393         return false;
4394     }
4395
4396     body = ast_block_new(ast_ctx(array));
4397     if (!body) {
4398         parseerror(parser, "failed to create block for array accessor");
4399         ast_delete(fval);
4400         ast_delete(func);
4401         return false;
4402     }
4403
4404     vec_push(func->blocks, body);
4405     *out = fval;
4406
4407     vec_push(parser->accessors, fval);
4408
4409     return true;
4410 }
4411
4412 static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname)
4413 {
4414     ast_value      *index = NULL;
4415     ast_value      *value = NULL;
4416     ast_function   *func;
4417     ast_value      *fval;
4418
4419     if (!ast_istype(array->expression.next, ast_value)) {
4420         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
4421         return NULL;
4422     }
4423
4424     if (!parser_create_array_accessor(parser, array, funcname, &fval))
4425         return NULL;
4426     func = fval->constval.vfunc;
4427     fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
4428
4429     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
4430     value = ast_value_copy((ast_value*)array->expression.next);
4431
4432     if (!index || !value) {
4433         parseerror(parser, "failed to create locals for array accessor");
4434         goto cleanup;
4435     }
4436     (void)!ast_value_set_name(value, "value"); /* not important */
4437     vec_push(fval->expression.params, index);
4438     vec_push(fval->expression.params, value);
4439
4440     array->setter = fval;
4441     return fval;
4442 cleanup:
4443     if (index) ast_delete(index);
4444     if (value) ast_delete(value);
4445     ast_delete(func);
4446     ast_delete(fval);
4447     return NULL;
4448 }
4449
4450 static bool parser_create_array_setter_impl(parser_t *parser, ast_value *array)
4451 {
4452     ast_expression *root = NULL;
4453     root = array_setter_node(parser, array,
4454                              array->setter->expression.params[0],
4455                              array->setter->expression.params[1],
4456                              0, array->expression.count);
4457     if (!root) {
4458         parseerror(parser, "failed to build accessor search tree");
4459         return false;
4460     }
4461     if (!ast_block_add_expr(array->setter->constval.vfunc->blocks[0], root)) {
4462         ast_delete(root);
4463         return false;
4464     }
4465     return true;
4466 }
4467
4468 static bool parser_create_array_setter(parser_t *parser, ast_value *array, const char *funcname)
4469 {
4470     if (!parser_create_array_setter_proto(parser, array, funcname))
4471         return false;
4472     return parser_create_array_setter_impl(parser, array);
4473 }
4474
4475 static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, const char *funcname)
4476 {
4477     ast_expression *root = NULL;
4478     ast_value      *entity = NULL;
4479     ast_value      *index = NULL;
4480     ast_value      *value = NULL;
4481     ast_function   *func;
4482     ast_value      *fval;
4483
4484     if (!ast_istype(array->expression.next, ast_value)) {
4485         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
4486         return false;
4487     }
4488
4489     if (!parser_create_array_accessor(parser, array, funcname, &fval))
4490         return false;
4491     func = fval->constval.vfunc;
4492     fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
4493
4494     entity = ast_value_new(ast_ctx(array), "entity", TYPE_ENTITY);
4495     index  = ast_value_new(ast_ctx(array), "index",  TYPE_FLOAT);
4496     value  = ast_value_copy((ast_value*)array->expression.next);
4497     if (!entity || !index || !value) {
4498         parseerror(parser, "failed to create locals for array accessor");
4499         goto cleanup;
4500     }
4501     (void)!ast_value_set_name(value, "value"); /* not important */
4502     vec_push(fval->expression.params, entity);
4503     vec_push(fval->expression.params, index);
4504     vec_push(fval->expression.params, value);
4505
4506     root = array_field_setter_node(parser, array, entity, index, value, 0, array->expression.count);
4507     if (!root) {
4508         parseerror(parser, "failed to build accessor search tree");
4509         goto cleanup;
4510     }
4511
4512     array->setter = fval;
4513     return ast_block_add_expr(func->blocks[0], root);
4514 cleanup:
4515     if (entity) ast_delete(entity);
4516     if (index)  ast_delete(index);
4517     if (value)  ast_delete(value);
4518     if (root)   ast_delete(root);
4519     ast_delete(func);
4520     ast_delete(fval);
4521     return false;
4522 }
4523
4524 static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname)
4525 {
4526     ast_value      *index = NULL;
4527     ast_value      *fval;
4528     ast_function   *func;
4529
4530     /* NOTE: checking array->expression.next rather than elemtype since
4531      * for fields elemtype is a temporary fieldtype.
4532      */
4533     if (!ast_istype(array->expression.next, ast_value)) {
4534         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
4535         return NULL;
4536     }
4537
4538     if (!parser_create_array_accessor(parser, array, funcname, &fval))
4539         return NULL;
4540     func = fval->constval.vfunc;
4541     fval->expression.next = ast_type_copy(ast_ctx(array), elemtype);
4542
4543     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
4544
4545     if (!index) {
4546         parseerror(parser, "failed to create locals for array accessor");
4547         goto cleanup;
4548     }
4549     vec_push(fval->expression.params, index);
4550
4551     array->getter = fval;
4552     return fval;
4553 cleanup:
4554     if (index) ast_delete(index);
4555     ast_delete(func);
4556     ast_delete(fval);
4557     return NULL;
4558 }
4559
4560 static bool parser_create_array_getter_impl(parser_t *parser, ast_value *array)
4561 {
4562     ast_expression *root = NULL;
4563
4564     root = array_getter_node(parser, array, array->getter->expression.params[0], 0, array->expression.count);
4565     if (!root) {
4566         parseerror(parser, "failed to build accessor search tree");
4567         return false;
4568     }
4569     if (!ast_block_add_expr(array->getter->constval.vfunc->blocks[0], root)) {
4570         ast_delete(root);
4571         return false;
4572     }
4573     return true;
4574 }
4575
4576 static bool parser_create_array_getter(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname)
4577 {
4578     if (!parser_create_array_getter_proto(parser, array, elemtype, funcname))
4579         return false;
4580     return parser_create_array_getter_impl(parser, array);
4581 }
4582
4583 static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
4584 static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
4585 {
4586     lex_ctx     ctx;
4587     size_t      i;
4588     ast_value **params;
4589     ast_value  *param;
4590     ast_value  *fval;
4591     bool        first = true;
4592     bool        variadic = false;
4593     ast_value  *varparam = NULL;
4594     char       *argcounter = NULL;
4595
4596     ctx = parser_ctx(parser);
4597
4598     /* for the sake of less code we parse-in in this function */
4599     if (!parser_next(parser)) {
4600         parseerror(parser, "expected parameter list");
4601         return NULL;
4602     }
4603
4604     params = NULL;
4605
4606     /* parse variables until we hit a closing paren */
4607     while (parser->tok != ')') {
4608         if (!first) {
4609             /* there must be commas between them */
4610             if (parser->tok != ',') {
4611                 parseerror(parser, "expected comma or end of parameter list");
4612                 goto on_error;
4613             }
4614             if (!parser_next(parser)) {
4615                 parseerror(parser, "expected parameter");
4616                 goto on_error;
4617             }
4618         }
4619         first = false;
4620
4621         if (parser->tok == TOKEN_DOTS) {
4622             /* '...' indicates a varargs function */
4623             variadic = true;
4624             if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) {
4625                 parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4626                 goto on_error;
4627             }
4628             if (parser->tok == TOKEN_IDENT) {
4629                 argcounter = util_strdup(parser_tokval(parser));
4630                 if (!parser_next(parser) || parser->tok != ')') {
4631                     parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4632                     goto on_error;
4633                 }
4634             }
4635         }
4636         else
4637         {
4638             /* for anything else just parse a typename */
4639             param = parse_typename(parser, NULL, NULL);
4640             if (!param)
4641                 goto on_error;
4642             vec_push(params, param);
4643             if (param->expression.vtype >= TYPE_VARIANT) {
4644                 char tname[1024]; /* typename is reserved in C++ */
4645                 ast_type_to_string((ast_expression*)param, tname, sizeof(tname));
4646                 parseerror(parser, "type not supported as part of a parameter list: %s", tname);
4647                 goto on_error;
4648             }
4649             /* type-restricted varargs */
4650             if (parser->tok == TOKEN_DOTS) {
4651                 variadic = true;
4652                 varparam = vec_last(params);
4653                 vec_pop(params);
4654                 if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) {
4655                     parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4656                     goto on_error;
4657                 }
4658                 if (parser->tok == TOKEN_IDENT) {
4659                     argcounter = util_strdup(parser_tokval(parser));
4660                     if (!parser_next(parser) || parser->tok != ')') {
4661                         parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4662                         goto on_error;
4663                     }
4664                 }
4665             }
4666         }
4667     }
4668
4669     if (vec_size(params) == 1 && params[0]->expression.vtype == TYPE_VOID)
4670         vec_free(params);
4671
4672     /* sanity check */
4673     if (vec_size(params) > 8 && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4674         (void)!parsewarning(parser, WARN_EXTENSIONS, "more than 8 parameters are not supported by this standard");
4675
4676     /* parse-out */
4677     if (!parser_next(parser)) {
4678         parseerror(parser, "parse error after typename");
4679         goto on_error;
4680     }
4681
4682     /* now turn 'var' into a function type */
4683     fval = ast_value_new(ctx, "<type()>", TYPE_FUNCTION);
4684     fval->expression.next     = (ast_expression*)var;
4685     if (variadic)
4686         fval->expression.flags |= AST_FLAG_VARIADIC;
4687     var = fval;
4688
4689     var->expression.params   = params;
4690     var->expression.varparam = (ast_expression*)varparam;
4691     var->argcounter          = argcounter;
4692     params = NULL;
4693
4694     return var;
4695
4696 on_error:
4697     if (argcounter)
4698         mem_d(argcounter);
4699     ast_delete(var);
4700     for (i = 0; i < vec_size(params); ++i)
4701         ast_delete(params[i]);
4702     vec_free(params);
4703     return NULL;
4704 }
4705
4706 static ast_value *parse_arraysize(parser_t *parser, ast_value *var)
4707 {
4708     ast_expression *cexp;
4709     ast_value      *cval, *tmp;
4710     lex_ctx ctx;
4711
4712     ctx = parser_ctx(parser);
4713
4714     if (!parser_next(parser)) {
4715         ast_delete(var);
4716         parseerror(parser, "expected array-size");
4717         return NULL;
4718     }
4719
4720     cexp = parse_expression_leave(parser, true, false, false);
4721
4722     if (!cexp || !ast_istype(cexp, ast_value)) {
4723         if (cexp)
4724             ast_unref(cexp);
4725         ast_delete(var);
4726         parseerror(parser, "expected array-size as constant positive integer");
4727         return NULL;
4728     }
4729     cval = (ast_value*)cexp;
4730
4731     tmp = ast_value_new(ctx, "<type[]>", TYPE_ARRAY);
4732     tmp->expression.next = (ast_expression*)var;
4733     var = tmp;
4734
4735     if (cval->expression.vtype == TYPE_INTEGER)
4736         tmp->expression.count = cval->constval.vint;
4737     else if (cval->expression.vtype == TYPE_FLOAT)
4738         tmp->expression.count = cval->constval.vfloat;
4739     else {
4740         ast_unref(cexp);
4741         ast_delete(var);
4742         parseerror(parser, "array-size must be a positive integer constant");
4743         return NULL;
4744     }
4745     ast_unref(cexp);
4746
4747     if (parser->tok != ']') {
4748         ast_delete(var);
4749         parseerror(parser, "expected ']' after array-size");
4750         return NULL;
4751     }
4752     if (!parser_next(parser)) {
4753         ast_delete(var);
4754         parseerror(parser, "error after parsing array size");
4755         return NULL;
4756     }
4757     return var;
4758 }
4759
4760 /* Parse a complete typename.
4761  * for single-variables (ie. function parameters or typedefs) storebase should be NULL
4762  * but when parsing variables separated by comma
4763  * 'storebase' should point to where the base-type should be kept.
4764  * The base type makes up every bit of type information which comes *before* the
4765  * variable name.
4766  *
4767  * The following will be parsed in its entirety:
4768  *     void() foo()
4769  * The 'basetype' in this case is 'void()'
4770  * and if there's a comma after it, say:
4771  *     void() foo(), bar
4772  * then the type-information 'void()' can be stored in 'storebase'
4773  */
4774 static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef)
4775 {
4776     ast_value *var, *tmp;
4777     lex_ctx    ctx;
4778
4779     const char *name = NULL;
4780     bool        isfield  = false;
4781     bool        wasarray = false;
4782     size_t      morefields = 0;
4783
4784     ctx = parser_ctx(parser);
4785
4786     /* types may start with a dot */
4787     if (parser->tok == '.') {
4788         isfield = true;
4789         /* if we parsed a dot we need a typename now */
4790         if (!parser_next(parser)) {
4791             parseerror(parser, "expected typename for field definition");
4792             return NULL;
4793         }
4794
4795         /* Further dots are handled seperately because they won't be part of the
4796          * basetype
4797          */
4798         while (parser->tok == '.') {
4799             ++morefields;
4800             if (!parser_next(parser)) {
4801                 parseerror(parser, "expected typename for field definition");
4802                 return NULL;
4803             }
4804         }
4805     }
4806     if (parser->tok == TOKEN_IDENT)
4807         cached_typedef = parser_find_typedef(parser, parser_tokval(parser), 0);
4808     if (!cached_typedef && parser->tok != TOKEN_TYPENAME) {
4809         parseerror(parser, "expected typename");
4810         return NULL;
4811     }
4812
4813     /* generate the basic type value */
4814     if (cached_typedef) {
4815         var = ast_value_copy(cached_typedef);
4816         ast_value_set_name(var, "<type(from_def)>");
4817     } else
4818         var = ast_value_new(ctx, "<type>", parser_token(parser)->constval.t);
4819
4820     for (; morefields; --morefields) {
4821         tmp = ast_value_new(ctx, "<.type>", TYPE_FIELD);
4822         tmp->expression.next = (ast_expression*)var;
4823         var = tmp;
4824     }
4825
4826     /* do not yet turn into a field - remember:
4827      * .void() foo; is a field too
4828      * .void()() foo; is a function
4829      */
4830
4831     /* parse on */
4832     if (!parser_next(parser)) {
4833         ast_delete(var);
4834         parseerror(parser, "parse error after typename");
4835         return NULL;
4836     }
4837
4838     /* an opening paren now starts the parameter-list of a function
4839      * this is where original-QC has parameter lists.
4840      * We allow a single parameter list here.
4841      * Much like fteqcc we don't allow `float()() x`
4842      */
4843     if (parser->tok == '(') {
4844         var = parse_parameter_list(parser, var);
4845         if (!var)
4846             return NULL;
4847     }
4848
4849     /* store the base if requested */
4850     if (storebase) {
4851         *storebase = ast_value_copy(var);
4852         if (isfield) {
4853             tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
4854             tmp->expression.next = (ast_expression*)*storebase;
4855             *storebase = tmp;
4856         }
4857     }
4858
4859     /* there may be a name now */
4860     if (parser->tok == TOKEN_IDENT) {
4861         name = util_strdup(parser_tokval(parser));
4862         /* parse on */
4863         if (!parser_next(parser)) {
4864             ast_delete(var);
4865             parseerror(parser, "error after variable or field declaration");
4866             return NULL;
4867         }
4868     }
4869
4870     /* now this may be an array */
4871     if (parser->tok == '[') {
4872         wasarray = true;
4873         var = parse_arraysize(parser, var);
4874         if (!var)
4875             return NULL;
4876     }
4877
4878     /* This is the point where we can turn it into a field */
4879     if (isfield) {
4880         /* turn it into a field if desired */
4881         tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
4882         tmp->expression.next = (ast_expression*)var;
4883         var = tmp;
4884     }
4885
4886     /* now there may be function parens again */
4887     if (parser->tok == '(' && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4888         parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
4889     if (parser->tok == '(' && wasarray)
4890         parseerror(parser, "arrays as part of a return type is not supported");
4891     while (parser->tok == '(') {
4892         var = parse_parameter_list(parser, var);
4893         if (!var) {
4894             if (name)
4895                 mem_d((void*)name);
4896             return NULL;
4897         }
4898     }
4899
4900     /* finally name it */
4901     if (name) {
4902         if (!ast_value_set_name(var, name)) {
4903             ast_delete(var);
4904             parseerror(parser, "internal error: failed to set name");
4905             return NULL;
4906         }
4907         /* free the name, ast_value_set_name duplicates */
4908         mem_d((void*)name);
4909     }
4910
4911     return var;
4912 }
4913
4914 static bool parse_typedef(parser_t *parser)
4915 {
4916     ast_value      *typevar, *oldtype;
4917     ast_expression *old;
4918
4919     typevar = parse_typename(parser, NULL, NULL);
4920
4921     if (!typevar)
4922         return false;
4923
4924     if ( (old = parser_find_var(parser, typevar->name)) ) {
4925         parseerror(parser, "cannot define a type with the same name as a variable: %s\n"
4926                    " -> `%s` has been declared here: %s:%i",
4927                    typevar->name, ast_ctx(old).file, ast_ctx(old).line);
4928         ast_delete(typevar);
4929         return false;
4930     }
4931
4932     if ( (oldtype = parser_find_typedef(parser, typevar->name, vec_last(parser->_blocktypedefs))) ) {
4933         parseerror(parser, "type `%s` has already been declared here: %s:%i",
4934                    typevar->name, ast_ctx(oldtype).file, ast_ctx(oldtype).line);
4935         ast_delete(typevar);
4936         return false;
4937     }
4938
4939     vec_push(parser->_typedefs, typevar);
4940     util_htset(vec_last(parser->typedefs), typevar->name, typevar);
4941
4942     if (parser->tok != ';') {
4943         parseerror(parser, "expected semicolon after typedef");
4944         return false;
4945     }
4946     if (!parser_next(parser)) {
4947         parseerror(parser, "parse error after typedef");
4948         return false;
4949     }
4950
4951     return true;
4952 }
4953
4954 static const char *cvq_to_str(int cvq) {
4955     switch (cvq) {
4956         case CV_NONE:  return "none";
4957         case CV_VAR:   return "`var`";
4958         case CV_CONST: return "`const`";
4959         default:       return "<INVALID>";
4960     }
4961 }
4962
4963 static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, const ast_value *proto)
4964 {
4965     bool av, ao;
4966     if (proto->cvq != var->cvq) {
4967         if (!(proto->cvq == CV_CONST && var->cvq == CV_NONE &&
4968               !OPTS_FLAG(INITIALIZED_NONCONSTANTS) &&
4969               parser->tok == '='))
4970         {
4971             return !parsewarning(parser, WARN_DIFFERENT_QUALIFIERS,
4972                                  "`%s` declared with different qualifiers: %s\n"
4973                                  " -> previous declaration here: %s:%i uses %s",
4974                                  var->name, cvq_to_str(var->cvq),
4975                                  ast_ctx(proto).file, ast_ctx(proto).line,
4976                                  cvq_to_str(proto->cvq));
4977         }
4978     }
4979     av = (var  ->expression.flags & AST_FLAG_NORETURN);
4980     ao = (proto->expression.flags & AST_FLAG_NORETURN);
4981     if (!av != !ao) {
4982         return !parsewarning(parser, WARN_DIFFERENT_ATTRIBUTES,
4983                              "`%s` declared with different attributes%s\n"
4984                              " -> previous declaration here: %s:%i",
4985                              var->name, (av ? ": noreturn" : ""),
4986                              ast_ctx(proto).file, ast_ctx(proto).line,
4987                              (ao ? ": noreturn" : ""));
4988     }
4989     return true;
4990 }
4991
4992 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring)
4993 {
4994     ast_value *var;
4995     ast_value *proto;
4996     ast_expression *old;
4997     bool       was_end;
4998     size_t     i;
4999
5000     ast_value *basetype = NULL;
5001     bool      retval    = true;
5002     bool      isparam   = false;
5003     bool      isvector  = false;
5004     bool      cleanvar  = true;
5005     bool      wasarray  = false;
5006
5007     ast_member *me[3];
5008
5009     if (!localblock && is_static)
5010         parseerror(parser, "`static` qualifier is not supported in global scope");
5011
5012     /* get the first complete variable */
5013     var = parse_typename(parser, &basetype, cached_typedef);
5014     if (!var) {
5015         if (basetype)
5016             ast_delete(basetype);
5017         return false;
5018     }
5019
5020     while (true) {
5021         proto = NULL;
5022         wasarray = false;
5023
5024         /* Part 0: finish the type */
5025         if (parser->tok == '(') {
5026             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
5027                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
5028             var = parse_parameter_list(parser, var);
5029             if (!var) {
5030                 retval = false;
5031                 goto cleanup;
5032             }
5033         }
5034         /* we only allow 1-dimensional arrays */
5035         if (parser->tok == '[') {
5036             wasarray = true;
5037             var = parse_arraysize(parser, var);
5038             if (!var) {
5039                 retval = false;
5040                 goto cleanup;
5041             }
5042         }
5043         if (parser->tok == '(' && wasarray) {
5044             parseerror(parser, "arrays as part of a return type is not supported");
5045             /* we'll still parse the type completely for now */
5046         }
5047         /* for functions returning functions */
5048         while (parser->tok == '(') {
5049             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
5050                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
5051             var = parse_parameter_list(parser, var);
5052             if (!var) {
5053                 retval = false;
5054                 goto cleanup;
5055             }
5056         }
5057
5058         var->cvq = qualifier;
5059         var->expression.flags |= qflags;
5060
5061         /*
5062          * store the vstring back to var for alias and
5063          * deprecation messages.
5064          */   
5065         if (var->expression.flags & AST_FLAG_DEPRECATED ||
5066             var->expression.flags & AST_FLAG_ALIAS)
5067             var->desc = vstring;
5068
5069         /* Part 1:
5070          * check for validity: (end_sys_..., multiple-definitions, prototypes, ...)
5071          * Also: if there was a prototype, `var` will be deleted and set to `proto` which
5072          * is then filled with the previous definition and the parameter-names replaced.
5073          */
5074         if (!strcmp(var->name, "nil")) {
5075             if (OPTS_FLAG(UNTYPED_NIL)) {
5076                 if (!localblock || !OPTS_FLAG(PERMISSIVE))
5077                     parseerror(parser, "name `nil` not allowed (try -fpermissive)");
5078             } else
5079                 (void)!parsewarning(parser, WARN_RESERVED_NAMES, "variable name `nil` is reserved");
5080         }
5081         if (!localblock) {
5082             /* Deal with end_sys_ vars */
5083             was_end = false;
5084             if (!strcmp(var->name, "end_sys_globals")) {
5085                 var->uses++;
5086                 parser->crc_globals = vec_size(parser->globals);
5087                 was_end = true;
5088             }
5089             else if (!strcmp(var->name, "end_sys_fields")) {
5090                 var->uses++;
5091                 parser->crc_fields = vec_size(parser->fields);
5092                 was_end = true;
5093             }
5094             if (was_end && var->expression.vtype == TYPE_FIELD) {
5095                 if (parsewarning(parser, WARN_END_SYS_FIELDS,
5096                                  "global '%s' hint should not be a field",
5097                                  parser_tokval(parser)))
5098                 {
5099                     retval = false;
5100                     goto cleanup;
5101                 }
5102             }
5103
5104             if (!nofields && var->expression.vtype == TYPE_FIELD)
5105             {
5106                 /* deal with field declarations */
5107                 old = parser_find_field(parser, var->name);
5108                 if (old) {
5109                     if (parsewarning(parser, WARN_FIELD_REDECLARED, "field `%s` already declared here: %s:%i",
5110                                      var->name, ast_ctx(old).file, (int)ast_ctx(old).line))
5111                     {
5112                         retval = false;
5113                         goto cleanup;
5114                     }
5115                     ast_delete(var);
5116                     var = NULL;
5117                     goto skipvar;
5118                     /*
5119                     parseerror(parser, "field `%s` already declared here: %s:%i",
5120                                var->name, ast_ctx(old).file, ast_ctx(old).line);
5121                     retval = false;
5122                     goto cleanup;
5123                     */
5124                 }
5125                 if ((OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC || OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC) &&
5126                     (old = parser_find_global(parser, var->name)))
5127                 {
5128                     parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
5129                     parseerror(parser, "field `%s` already declared here: %s:%i",
5130                                var->name, ast_ctx(old).file, ast_ctx(old).line);
5131                     retval = false;
5132                     goto cleanup;
5133                 }
5134             }
5135             else
5136             {
5137                 /* deal with other globals */
5138                 old = parser_find_global(parser, var->name);
5139                 if (old && var->expression.vtype == TYPE_FUNCTION && old->expression.vtype == TYPE_FUNCTION)
5140                 {
5141                     /* This is a function which had a prototype */
5142                     if (!ast_istype(old, ast_value)) {
5143                         parseerror(parser, "internal error: prototype is not an ast_value");
5144                         retval = false;
5145                         goto cleanup;
5146                     }
5147                     proto = (ast_value*)old;
5148                     proto->desc = var->desc;
5149                     if (!ast_compare_type((ast_expression*)proto, (ast_expression*)var)) {
5150                         parseerror(parser, "conflicting types for `%s`, previous declaration was here: %s:%i",
5151                                    proto->name,
5152                                    ast_ctx(proto).file, ast_ctx(proto).line);
5153                         retval = false;
5154                         goto cleanup;
5155                     }
5156                     /* we need the new parameter-names */
5157                     for (i = 0; i < vec_size(proto->expression.params); ++i)
5158                         ast_value_set_name(proto->expression.params[i], var->expression.params[i]->name);
5159                     if (!parser_check_qualifiers(parser, var, proto)) {
5160                         retval = false;
5161                         if (proto->desc) 
5162                             mem_d(proto->desc);
5163                         proto = NULL;
5164                         goto cleanup;
5165                     }
5166                     proto->expression.flags |= var->expression.flags;
5167                     ast_delete(var);
5168                     var = proto;
5169                 }
5170                 else
5171                 {
5172                     /* other globals */
5173                     if (old) {
5174                         if (parsewarning(parser, WARN_DOUBLE_DECLARATION,
5175                                          "global `%s` already declared here: %s:%i",
5176                                          var->name, ast_ctx(old).file, ast_ctx(old).line))
5177                         {
5178                             retval = false;
5179                             goto cleanup;
5180                         }
5181                         proto = (ast_value*)old;
5182                         if (!ast_istype(old, ast_value)) {
5183                             parseerror(parser, "internal error: not an ast_value");
5184                             retval = false;
5185                             proto = NULL;
5186                             goto cleanup;
5187                         }
5188                         if (!parser_check_qualifiers(parser, var, proto)) {
5189                             retval = false;
5190                             proto = NULL;
5191                             goto cleanup;
5192                         }
5193                         proto->expression.flags |= var->expression.flags;
5194                         ast_delete(var);
5195                         var = proto;
5196                     }
5197                     if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC &&
5198                         (old = parser_find_field(parser, var->name)))
5199                     {
5200                         parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
5201                         parseerror(parser, "global `%s` already declared here: %s:%i",
5202                                    var->name, ast_ctx(old).file, ast_ctx(old).line);
5203                         retval = false;
5204                         goto cleanup;
5205                     }
5206                 }
5207             }
5208         }
5209         else /* it's not a global */
5210         {
5211             old = parser_find_local(parser, var->name, vec_size(parser->variables)-1, &isparam);
5212             if (old && !isparam) {
5213                 parseerror(parser, "local `%s` already declared here: %s:%i",
5214                            var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
5215                 retval = false;
5216                 goto cleanup;
5217             }
5218             old = parser_find_local(parser, var->name, 0, &isparam);
5219             if (old && isparam) {
5220                 if (parsewarning(parser, WARN_LOCAL_SHADOWS,
5221                                  "local `%s` is shadowing a parameter", var->name))
5222                 {
5223                     parseerror(parser, "local `%s` already declared here: %s:%i",
5224                                var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
5225                     retval = false;
5226                     goto cleanup;
5227                 }
5228                 if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
5229                     ast_delete(var);
5230                     var = NULL;
5231                     goto skipvar;
5232                 }
5233             }
5234         }
5235
5236         /* in a noref section we simply bump the usecount */
5237         if (noref || parser->noref)
5238             var->uses++;
5239
5240         /* Part 2:
5241          * Create the global/local, and deal with vector types.
5242          */
5243         if (!proto) {
5244             if (var->expression.vtype == TYPE_VECTOR)
5245                 isvector = true;
5246             else if (var->expression.vtype == TYPE_FIELD &&
5247                      var->expression.next->expression.vtype == TYPE_VECTOR)
5248                 isvector = true;
5249
5250             if (isvector) {
5251                 if (!create_vector_members(var, me)) {
5252                     retval = false;
5253                     goto cleanup;
5254                 }
5255             }
5256
5257             if (!localblock) {
5258                 /* deal with global variables, fields, functions */
5259                 if (!nofields && var->expression.vtype == TYPE_FIELD && parser->tok != '=') {
5260                     var->isfield = true;
5261                     vec_push(parser->fields, (ast_expression*)var);
5262                     util_htset(parser->htfields, var->name, var);
5263                     if (isvector) {
5264                         for (i = 0; i < 3; ++i) {
5265                             vec_push(parser->fields, (ast_expression*)me[i]);
5266                             util_htset(parser->htfields, me[i]->name, me[i]);
5267                         }
5268                     }
5269                 }
5270                 else {
5271                     if (!(var->expression.flags & AST_FLAG_ALIAS)) {
5272                         parser_addglobal(parser, var->name, (ast_expression*)var);
5273                         if (isvector) {
5274                             for (i = 0; i < 3; ++i) {
5275                                 parser_addglobal(parser, me[i]->name, (ast_expression*)me[i]);
5276                             }
5277                         }
5278                     } else {
5279                         ast_expression *find  = parser_find_global(parser, var->desc);
5280
5281                         if (!find) {
5282                             compile_error(parser_ctx(parser), "undeclared variable `%s` for alias `%s`", var->desc, var->name);
5283                             return false;
5284                         }
5285
5286                         if (var->expression.vtype != find->expression.vtype) {
5287                             char ty1[1024];
5288                             char ty2[1024];
5289
5290                             ast_type_to_string(find,                  ty1, sizeof(ty1));
5291                             ast_type_to_string((ast_expression*)var,  ty2, sizeof(ty2));
5292
5293                             compile_error(parser_ctx(parser), "incompatible types `%s` and `%s` for alias `%s`",
5294                                 ty1, ty2, var->name
5295                             );
5296                             return false;
5297                         }
5298
5299                         /*
5300                          * add alias to aliases table and to corrector
5301                          * so corrections can apply for aliases as well.
5302                          */  
5303                         util_htset(parser->aliases, var->name, find);
5304
5305                         /*
5306                          * add to corrector so corrections can work
5307                          * even for aliases too.
5308                          */ 
5309                         correct_add (
5310                              vec_last(parser->correct_variables),
5311                             &vec_last(parser->correct_variables_score),
5312                             var->name
5313                         );
5314
5315                         /* generate aliases for vector components */
5316                         if (isvector) {
5317                             char *buffer[3];
5318
5319                             util_asprintf(&buffer[0], "%s_x", var->desc);
5320                             util_asprintf(&buffer[1], "%s_y", var->desc);
5321                             util_asprintf(&buffer[2], "%s_z", var->desc);
5322
5323                             util_htset(parser->aliases, me[0]->name, parser_find_global(parser, buffer[0]));
5324                             util_htset(parser->aliases, me[1]->name, parser_find_global(parser, buffer[1]));
5325                             util_htset(parser->aliases, me[2]->name, parser_find_global(parser, buffer[2]));
5326
5327                             mem_d(buffer[0]);
5328                             mem_d(buffer[1]);
5329                             mem_d(buffer[2]);
5330
5331                             /*
5332                              * add to corrector so corrections can work
5333                              * even for aliases too.
5334                              */  
5335                             correct_add (
5336                                  vec_last(parser->correct_variables),
5337                                 &vec_last(parser->correct_variables_score),
5338                                 me[0]->name
5339                             );
5340                             correct_add (
5341                                  vec_last(parser->correct_variables),
5342                                 &vec_last(parser->correct_variables_score),
5343                                 me[1]->name
5344                             );
5345                             correct_add (
5346                                  vec_last(parser->correct_variables),
5347                                 &vec_last(parser->correct_variables_score),
5348                                 me[2]->name
5349                             );
5350                         }
5351                     }
5352                 }
5353             } else {
5354                 if (is_static) {
5355                     /* a static adds itself to be generated like any other global
5356                      * but is added to the local namespace instead
5357                      */
5358                     char   *defname = NULL;
5359                     size_t  prefix_len, ln;
5360
5361                     ln = strlen(parser->function->name);
5362                     vec_append(defname, ln, parser->function->name);
5363
5364                     vec_append(defname, 2, "::");
5365                     /* remember the length up to here */
5366                     prefix_len = vec_size(defname);
5367
5368                     /* Add it to the local scope */
5369                     util_htset(vec_last(parser->variables), var->name, (void*)var);
5370
5371                     /* corrector */
5372                     correct_add (
5373                          vec_last(parser->correct_variables),
5374                         &vec_last(parser->correct_variables_score),
5375                         var->name
5376                     );
5377
5378                     /* now rename the global */
5379                     ln = strlen(var->name);
5380                     vec_append(defname, ln, var->name);
5381                     ast_value_set_name(var, defname);
5382
5383                     /* push it to the to-be-generated globals */
5384                     vec_push(parser->globals, (ast_expression*)var);
5385
5386                     /* same game for the vector members */
5387                     if (isvector) {
5388                         for (i = 0; i < 3; ++i) {
5389                             util_htset(vec_last(parser->variables), me[i]->name, (void*)(me[i]));
5390
5391                             /* corrector */
5392                             correct_add(
5393                                  vec_last(parser->correct_variables),
5394                                 &vec_last(parser->correct_variables_score),
5395                                 me[i]->name
5396                             );
5397
5398                             vec_shrinkto(defname, prefix_len);
5399                             ln = strlen(me[i]->name);
5400                             vec_append(defname, ln, me[i]->name);
5401                             ast_member_set_name(me[i], defname);
5402
5403                             vec_push(parser->globals, (ast_expression*)me[i]);
5404                         }
5405                     }
5406                     vec_free(defname);
5407                 } else {
5408                     vec_push(localblock->locals, var);
5409                     parser_addlocal(parser, var->name, (ast_expression*)var);
5410                     if (isvector) {
5411                         for (i = 0; i < 3; ++i) {
5412                             parser_addlocal(parser, me[i]->name, (ast_expression*)me[i]);
5413                             ast_block_collect(localblock, (ast_expression*)me[i]);
5414                         }
5415                     }
5416                 }
5417             }
5418         }
5419         me[0] = me[1] = me[2] = NULL;
5420         cleanvar = false;
5421         /* Part 2.2
5422          * deal with arrays
5423          */
5424         if (var->expression.vtype == TYPE_ARRAY) {
5425             char name[1024];
5426             snprintf(name, sizeof(name), "%s##SET", var->name);
5427             if (!parser_create_array_setter(parser, var, name))
5428                 goto cleanup;
5429             snprintf(name, sizeof(name), "%s##GET", var->name);
5430             if (!parser_create_array_getter(parser, var, var->expression.next, name))
5431                 goto cleanup;
5432         }
5433         else if (!localblock && !nofields &&
5434                  var->expression.vtype == TYPE_FIELD &&
5435                  var->expression.next->expression.vtype == TYPE_ARRAY)
5436         {
5437             char name[1024];
5438             ast_expression *telem;
5439             ast_value      *tfield;
5440             ast_value      *array = (ast_value*)var->expression.next;
5441
5442             if (!ast_istype(var->expression.next, ast_value)) {
5443                 parseerror(parser, "internal error: field element type must be an ast_value");
5444                 goto cleanup;
5445             }
5446
5447             snprintf(name, sizeof(name), "%s##SETF", var->name);
5448             if (!parser_create_array_field_setter(parser, array, name))
5449                 goto cleanup;
5450
5451             telem = ast_type_copy(ast_ctx(var), array->expression.next);
5452             tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD);
5453             tfield->expression.next = telem;
5454             snprintf(name, sizeof(name), "%s##GETFP", var->name);
5455             if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) {
5456                 ast_delete(tfield);
5457                 goto cleanup;
5458             }
5459             ast_delete(tfield);
5460         }
5461
5462 skipvar:
5463         if (parser->tok == ';') {
5464             ast_delete(basetype);
5465             if (!parser_next(parser)) {
5466                 parseerror(parser, "error after variable declaration");
5467                 return false;
5468             }
5469             return true;
5470         }
5471
5472         if (parser->tok == ',')
5473             goto another;
5474
5475         /*
5476         if (!var || (!localblock && !nofields && basetype->expression.vtype == TYPE_FIELD)) {
5477         */
5478         if (!var) {
5479             parseerror(parser, "missing comma or semicolon while parsing variables");
5480             break;
5481         }
5482
5483         if (localblock && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
5484             if (parsewarning(parser, WARN_LOCAL_CONSTANTS,
5485                              "initializing expression turns variable `%s` into a constant in this standard",
5486                              var->name) )
5487             {
5488                 break;
5489             }
5490         }
5491
5492         if (parser->tok != '{') {
5493             if (parser->tok != '=') {
5494                 parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser));
5495                 break;
5496             }
5497
5498             if (!parser_next(parser)) {
5499                 parseerror(parser, "error parsing initializer");
5500                 break;
5501             }
5502         }
5503         else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
5504             parseerror(parser, "expected '=' before function body in this standard");
5505         }
5506
5507         if (parser->tok == '#') {
5508             ast_function *func = NULL;
5509
5510             if (localblock) {
5511                 parseerror(parser, "cannot declare builtins within functions");
5512                 break;
5513             }
5514             if (var->expression.vtype != TYPE_FUNCTION) {
5515                 parseerror(parser, "unexpected builtin number, '%s' is not a function", var->name);
5516                 break;
5517             }
5518             if (!parser_next(parser)) {
5519                 parseerror(parser, "expected builtin number");
5520                 break;
5521             }
5522             if (parser->tok != TOKEN_INTCONST) {
5523                 parseerror(parser, "builtin number must be an integer constant");
5524                 break;
5525             }
5526             if (parser_token(parser)->constval.i < 0) {
5527                 parseerror(parser, "builtin number must be an integer greater than zero");
5528                 break;
5529             }
5530
5531             if (var->hasvalue) {
5532                 (void)!parsewarning(parser, WARN_DOUBLE_DECLARATION,
5533                                     "builtin `%s` has already been defined\n"
5534                                     " -> previous declaration here: %s:%i",
5535                                     var->name, ast_ctx(var).file, (int)ast_ctx(var).line);
5536             }
5537             else
5538             {
5539                 func = ast_function_new(ast_ctx(var), var->name, var);
5540                 if (!func) {
5541                     parseerror(parser, "failed to allocate function for `%s`", var->name);
5542                     break;
5543                 }
5544                 vec_push(parser->functions, func);
5545
5546                 func->builtin = -parser_token(parser)->constval.i-1;
5547             }
5548
5549             if (!parser_next(parser)) {
5550                 parseerror(parser, "expected comma or semicolon");
5551                 if (func)
5552                     ast_function_delete(func);
5553                 var->constval.vfunc = NULL;
5554                 break;
5555             }
5556         }
5557         else if (parser->tok == '{' || parser->tok == '[')
5558         {
5559             if (localblock) {
5560                 parseerror(parser, "cannot declare functions within functions");
5561                 break;
5562             }
5563
5564             if (proto)
5565                 ast_ctx(proto) = parser_ctx(parser);
5566
5567             if (!parse_function_body(parser, var))
5568                 break;
5569             ast_delete(basetype);
5570             for (i = 0; i < vec_size(parser->gotos); ++i)
5571                 parseerror(parser, "undefined label: `%s`", parser->gotos[i]->name);
5572             vec_free(parser->gotos);
5573             vec_free(parser->labels);
5574             return true;
5575         } else {
5576             ast_expression *cexp;
5577             ast_value      *cval;
5578
5579             cexp = parse_expression_leave(parser, true, false, false);
5580             if (!cexp)
5581                 break;
5582
5583             if (!localblock) {
5584                 cval = (ast_value*)cexp;
5585                 if (cval != parser->nil &&
5586                     (!ast_istype(cval, ast_value) || ((!cval->hasvalue || cval->cvq != CV_CONST) && !cval->isfield))
5587                    )
5588                 {
5589                     parseerror(parser, "cannot initialize a global constant variable with a non-constant expression");
5590                 }
5591                 else
5592                 {
5593                     if (!OPTS_FLAG(INITIALIZED_NONCONSTANTS) &&
5594                         qualifier != CV_VAR)
5595                     {
5596                         var->cvq = CV_CONST;
5597                     }
5598                     if (cval == parser->nil)
5599                         var->expression.flags |= AST_FLAG_INITIALIZED;
5600                     else
5601                     {
5602                         var->hasvalue = true;
5603                         if (cval->expression.vtype == TYPE_STRING)
5604                             var->constval.vstring = parser_strdup(cval->constval.vstring);
5605                         else if (cval->expression.vtype == TYPE_FIELD)
5606                             var->constval.vfield = cval;
5607                         else
5608                             memcpy(&var->constval, &cval->constval, sizeof(var->constval));
5609                         ast_unref(cval);
5610                     }
5611                 }
5612             } else {
5613                 int cvq;
5614                 shunt sy = { NULL, NULL, NULL, NULL };
5615                 cvq = var->cvq;
5616                 var->cvq = CV_NONE;
5617                 vec_push(sy.out, syexp(ast_ctx(var), (ast_expression*)var));
5618                 vec_push(sy.out, syexp(ast_ctx(cexp), (ast_expression*)cexp));
5619                 vec_push(sy.ops, syop(ast_ctx(var), parser->assign_op));
5620                 if (!parser_sy_apply_operator(parser, &sy))
5621                     ast_unref(cexp);
5622                 else {
5623                     if (vec_size(sy.out) != 1 && vec_size(sy.ops) != 0)
5624                         parseerror(parser, "internal error: leaked operands");
5625                     if (!ast_block_add_expr(localblock, (ast_expression*)sy.out[0].out))
5626                         break;
5627                 }
5628                 vec_free(sy.out);
5629                 vec_free(sy.ops);
5630                 var->cvq = cvq;
5631             }
5632         }
5633
5634 another:
5635         if (parser->tok == ',') {
5636             if (!parser_next(parser)) {
5637                 parseerror(parser, "expected another variable");
5638                 break;
5639             }
5640
5641             if (parser->tok != TOKEN_IDENT) {
5642                 parseerror(parser, "expected another variable");
5643                 break;
5644             }
5645             var = ast_value_copy(basetype);
5646             cleanvar = true;
5647             ast_value_set_name(var, parser_tokval(parser));
5648             if (!parser_next(parser)) {
5649                 parseerror(parser, "error parsing variable declaration");
5650                 break;
5651             }
5652             continue;
5653         }
5654
5655         if (parser->tok != ';') {
5656             parseerror(parser, "missing semicolon after variables");
5657             break;
5658         }
5659
5660         if (!parser_next(parser)) {
5661             parseerror(parser, "parse error after variable declaration");
5662             break;
5663         }
5664
5665         ast_delete(basetype);
5666         return true;
5667     }
5668
5669     if (cleanvar && var)
5670         ast_delete(var);
5671     ast_delete(basetype);
5672     return false;
5673
5674 cleanup:
5675     ast_delete(basetype);
5676     if (cleanvar && var)
5677         ast_delete(var);
5678     if (me[0]) ast_member_delete(me[0]);
5679     if (me[1]) ast_member_delete(me[1]);
5680     if (me[2]) ast_member_delete(me[2]);
5681     return retval;
5682 }
5683
5684 static bool parser_global_statement(parser_t *parser)
5685 {
5686     int        cvq       = CV_WRONG;
5687     bool       noref     = false;
5688     bool       is_static = false;
5689     uint32_t   qflags    = 0;
5690     ast_value *istype    = NULL;
5691     char      *vstring   = NULL;
5692
5693     if (parser->tok == TOKEN_IDENT)
5694         istype = parser_find_typedef(parser, parser_tokval(parser), 0);
5695
5696     if (istype || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
5697     {
5698         return parse_variable(parser, NULL, false, CV_NONE, istype, false, false, 0, NULL);
5699     }
5700     else if (parse_qualifiers(parser, false, &cvq, &noref, &is_static, &qflags, &vstring))
5701     {
5702         if (cvq == CV_WRONG)
5703             return false;
5704         return parse_variable(parser, NULL, true, cvq, NULL, noref, is_static, qflags, vstring);
5705     }
5706     else if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "enum"))
5707     {
5708         return parse_enum(parser);
5709     }
5710     else if (parser->tok == TOKEN_KEYWORD)
5711     {
5712         if (!strcmp(parser_tokval(parser), "typedef")) {
5713             if (!parser_next(parser)) {
5714                 parseerror(parser, "expected type definition after 'typedef'");
5715                 return false;
5716             }
5717             return parse_typedef(parser);
5718         }
5719         parseerror(parser, "unrecognized keyword `%s`", parser_tokval(parser));
5720         return false;
5721     }
5722     else if (parser->tok == '#')
5723     {
5724         return parse_pragma(parser);
5725     }
5726     else if (parser->tok == '$')
5727     {
5728         if (!parser_next(parser)) {
5729             parseerror(parser, "parse error");
5730             return false;
5731         }
5732     }
5733     else
5734     {
5735         parseerror(parser, "unexpected token: `%s`", parser->lex->tok.value);
5736         return false;
5737     }
5738     return true;
5739 }
5740
5741 static uint16_t progdefs_crc_sum(uint16_t old, const char *str)
5742 {
5743     return util_crc16(old, str, strlen(str));
5744 }
5745
5746 static void progdefs_crc_file(const char *str)
5747 {
5748     /* write to progdefs.h here */
5749     (void)str;
5750 }
5751
5752 static uint16_t progdefs_crc_both(uint16_t old, const char *str)
5753 {
5754     old = progdefs_crc_sum(old, str);
5755     progdefs_crc_file(str);
5756     return old;
5757 }
5758
5759 static void generate_checksum(parser_t *parser)
5760 {
5761     uint16_t   crc = 0xFFFF;
5762     size_t     i;
5763     ast_value *value;
5764
5765     crc = progdefs_crc_both(crc, "\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{");
5766     crc = progdefs_crc_sum(crc, "\tint\tpad[28];\n");
5767     /*
5768     progdefs_crc_file("\tint\tpad;\n");
5769     progdefs_crc_file("\tint\tofs_return[3];\n");
5770     progdefs_crc_file("\tint\tofs_parm0[3];\n");
5771     progdefs_crc_file("\tint\tofs_parm1[3];\n");
5772     progdefs_crc_file("\tint\tofs_parm2[3];\n");
5773     progdefs_crc_file("\tint\tofs_parm3[3];\n");
5774     progdefs_crc_file("\tint\tofs_parm4[3];\n");
5775     progdefs_crc_file("\tint\tofs_parm5[3];\n");
5776     progdefs_crc_file("\tint\tofs_parm6[3];\n");
5777     progdefs_crc_file("\tint\tofs_parm7[3];\n");
5778     */
5779     for (i = 0; i < parser->crc_globals; ++i) {
5780         if (!ast_istype(parser->globals[i], ast_value))
5781             continue;
5782         value = (ast_value*)(parser->globals[i]);
5783         switch (value->expression.vtype) {
5784             case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
5785             case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
5786             case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
5787             case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break;
5788             default:
5789                 crc = progdefs_crc_both(crc, "\tint\t");
5790                 break;
5791         }
5792         crc = progdefs_crc_both(crc, value->name);
5793         crc = progdefs_crc_both(crc, ";\n");
5794     }
5795     crc = progdefs_crc_both(crc, "} globalvars_t;\n\ntypedef struct\n{\n");
5796     for (i = 0; i < parser->crc_fields; ++i) {
5797         if (!ast_istype(parser->fields[i], ast_value))
5798             continue;
5799         value = (ast_value*)(parser->fields[i]);
5800         switch (value->expression.next->expression.vtype) {
5801             case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
5802             case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
5803             case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
5804             case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break;
5805             default:
5806                 crc = progdefs_crc_both(crc, "\tint\t");
5807                 break;
5808         }
5809         crc = progdefs_crc_both(crc, value->name);
5810         crc = progdefs_crc_both(crc, ";\n");
5811     }
5812     crc = progdefs_crc_both(crc, "} entvars_t;\n\n");
5813
5814     code_crc = crc;
5815 }
5816
5817 static parser_t *parser;
5818
5819 bool parser_init()
5820 {
5821     lex_ctx empty_ctx;
5822     size_t i;
5823
5824     parser = (parser_t*)mem_a(sizeof(parser_t));
5825     if (!parser)
5826         return false;
5827
5828     memset(parser, 0, sizeof(*parser));
5829
5830     for (i = 0; i < operator_count; ++i) {
5831         if (operators[i].id == opid1('=')) {
5832             parser->assign_op = operators+i;
5833             break;
5834         }
5835     }
5836     if (!parser->assign_op) {
5837         printf("internal error: initializing parser: failed to find assign operator\n");
5838         mem_d(parser);
5839         return false;
5840     }
5841
5842     vec_push(parser->variables, parser->htfields  = util_htnew(PARSER_HT_SIZE));
5843     vec_push(parser->variables, parser->htglobals = util_htnew(PARSER_HT_SIZE));
5844     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
5845     vec_push(parser->_blocktypedefs, 0);
5846
5847     parser->aliases = util_htnew(PARSER_HT_SIZE);
5848
5849     /* corrector */
5850     vec_push(parser->correct_variables, correct_trie_new());
5851     vec_push(parser->correct_variables_score, NULL);
5852
5853     empty_ctx.file = "<internal>";
5854     empty_ctx.line = 0;
5855     parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL);
5856     parser->nil->cvq = CV_CONST;
5857     if (OPTS_FLAG(UNTYPED_NIL))
5858         util_htset(parser->htglobals, "nil", (void*)parser->nil);
5859
5860     parser->max_param_count = 1;
5861
5862     parser->const_vec[0] = ast_value_new(empty_ctx, "<vector.x>", TYPE_NOEXPR);
5863     parser->const_vec[1] = ast_value_new(empty_ctx, "<vector.y>", TYPE_NOEXPR);
5864     parser->const_vec[2] = ast_value_new(empty_ctx, "<vector.z>", TYPE_NOEXPR);
5865
5866     if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) {
5867         parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING);
5868         parser->reserved_version->cvq = CV_CONST;
5869         parser->reserved_version->hasvalue = true;
5870         parser->reserved_version->expression.flags |= AST_FLAG_INCLUDE_DEF;
5871         parser->reserved_version->constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
5872     } else {
5873         parser->reserved_version = NULL;
5874     }
5875     return true;
5876 }
5877
5878 bool parser_compile()
5879 {
5880     /* initial lexer/parser state */
5881     parser->lex->flags.noops = true;
5882
5883     if (parser_next(parser))
5884     {
5885         while (parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR)
5886         {
5887             if (!parser_global_statement(parser)) {
5888                 if (parser->tok == TOKEN_EOF)
5889                     parseerror(parser, "unexpected eof");
5890                 else if (compile_errors)
5891                     parseerror(parser, "there have been errors, bailing out");
5892                 lex_close(parser->lex);
5893                 parser->lex = NULL;
5894                 return false;
5895             }
5896         }
5897     } else {
5898         parseerror(parser, "parse error");
5899         lex_close(parser->lex);
5900         parser->lex = NULL;
5901         return false;
5902     }
5903
5904     lex_close(parser->lex);
5905     parser->lex = NULL;
5906
5907     return !compile_errors;
5908 }
5909
5910 bool parser_compile_file(const char *filename)
5911 {
5912     parser->lex = lex_open(filename);
5913     if (!parser->lex) {
5914         con_err("failed to open file \"%s\"\n", filename);
5915         return false;
5916     }
5917     return parser_compile();
5918 }
5919
5920 bool parser_compile_string(const char *name, const char *str, size_t len)
5921 {
5922     parser->lex = lex_open_string(str, len, name);
5923     if (!parser->lex) {
5924         con_err("failed to create lexer for string \"%s\"\n", name);
5925         return false;
5926     }
5927     return parser_compile();
5928 }
5929
5930 void parser_cleanup()
5931 {
5932     size_t i;
5933     for (i = 0; i < vec_size(parser->accessors); ++i) {
5934         ast_delete(parser->accessors[i]->constval.vfunc);
5935         parser->accessors[i]->constval.vfunc = NULL;
5936         ast_delete(parser->accessors[i]);
5937     }
5938     for (i = 0; i < vec_size(parser->functions); ++i) {
5939         ast_delete(parser->functions[i]);
5940     }
5941     for (i = 0; i < vec_size(parser->imm_vector); ++i) {
5942         ast_delete(parser->imm_vector[i]);
5943     }
5944     for (i = 0; i < vec_size(parser->imm_string); ++i) {
5945         ast_delete(parser->imm_string[i]);
5946     }
5947     for (i = 0; i < vec_size(parser->imm_float); ++i) {
5948         ast_delete(parser->imm_float[i]);
5949     }
5950     for (i = 0; i < vec_size(parser->fields); ++i) {
5951         ast_delete(parser->fields[i]);
5952     }
5953     for (i = 0; i < vec_size(parser->globals); ++i) {
5954         ast_delete(parser->globals[i]);
5955     }
5956     vec_free(parser->accessors);
5957     vec_free(parser->functions);
5958     vec_free(parser->imm_vector);
5959     vec_free(parser->imm_string);
5960     vec_free(parser->imm_float);
5961     vec_free(parser->globals);
5962     vec_free(parser->fields);
5963
5964     for (i = 0; i < vec_size(parser->variables); ++i)
5965         util_htdel(parser->variables[i]);
5966     vec_free(parser->variables);
5967     vec_free(parser->_blocklocals);
5968     vec_free(parser->_locals);
5969
5970     /* corrector */
5971     for (i = 0; i < vec_size(parser->correct_variables); ++i) {
5972         correct_del(parser->correct_variables[i], parser->correct_variables_score[i]);
5973     }
5974     vec_free(parser->correct_variables);
5975     vec_free(parser->correct_variables_score);
5976
5977
5978     for (i = 0; i < vec_size(parser->_typedefs); ++i)
5979         ast_delete(parser->_typedefs[i]);
5980     vec_free(parser->_typedefs);
5981     for (i = 0; i < vec_size(parser->typedefs); ++i)
5982         util_htdel(parser->typedefs[i]);
5983     vec_free(parser->typedefs);
5984     vec_free(parser->_blocktypedefs);
5985
5986     vec_free(parser->_block_ctx);
5987
5988     vec_free(parser->labels);
5989     vec_free(parser->gotos);
5990     vec_free(parser->breaks);
5991     vec_free(parser->continues);
5992
5993     ast_value_delete(parser->nil);
5994
5995     ast_value_delete(parser->const_vec[0]);
5996     ast_value_delete(parser->const_vec[1]);
5997     ast_value_delete(parser->const_vec[2]);
5998
5999     util_htdel(parser->aliases);
6000
6001     mem_d(parser);
6002 }
6003
6004 bool parser_finish(const char *output)
6005 {
6006     size_t i;
6007     ir_builder *ir;
6008     bool retval = true;
6009
6010     if (compile_errors) {
6011         con_out("*** there were compile errors\n");
6012         return false;
6013     }
6014
6015     ir = ir_builder_new("gmqcc_out");
6016     if (!ir) {
6017         con_out("failed to allocate builder\n");
6018         return false;
6019     }
6020
6021     for (i = 0; i < vec_size(parser->fields); ++i) {
6022         ast_value *field;
6023         bool hasvalue;
6024         if (!ast_istype(parser->fields[i], ast_value))
6025             continue;
6026         field = (ast_value*)parser->fields[i];
6027         hasvalue = field->hasvalue;
6028         field->hasvalue = false;
6029         if (!ast_global_codegen((ast_value*)field, ir, true)) {
6030             con_out("failed to generate field %s\n", field->name);
6031             ir_builder_delete(ir);
6032             return false;
6033         }
6034         if (hasvalue) {
6035             ir_value *ifld;
6036             ast_expression *subtype;
6037             field->hasvalue = true;
6038             subtype = field->expression.next;
6039             ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
6040             if (subtype->expression.vtype == TYPE_FIELD)
6041                 ifld->fieldtype = subtype->expression.next->expression.vtype;
6042             else if (subtype->expression.vtype == TYPE_FUNCTION)
6043                 ifld->outtype = subtype->expression.next->expression.vtype;
6044             (void)!ir_value_set_field(field->ir_v, ifld);
6045         }
6046     }
6047     for (i = 0; i < vec_size(parser->globals); ++i) {
6048         ast_value *asvalue;
6049         if (!ast_istype(parser->globals[i], ast_value))
6050             continue;
6051         asvalue = (ast_value*)(parser->globals[i]);
6052         if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) {
6053             retval = retval && !compile_warning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE,
6054                                                 "unused global: `%s`", asvalue->name);
6055         }
6056         if (!ast_global_codegen(asvalue, ir, false)) {
6057             con_out("failed to generate global %s\n", asvalue->name);
6058             ir_builder_delete(ir);
6059             return false;
6060         }
6061     }
6062     /* Build function vararg accessor ast tree now before generating
6063      * immediates, because the accessors may add new immediates
6064      */
6065     for (i = 0; i < vec_size(parser->functions); ++i) {
6066         ast_function *f = parser->functions[i];
6067         if (f->varargs) {
6068             if (parser->max_param_count > vec_size(f->vtype->expression.params)) {
6069                 f->varargs->expression.count = parser->max_param_count - vec_size(f->vtype->expression.params);
6070                 if (!parser_create_array_setter_impl(parser, f->varargs)) {
6071                     con_out("failed to generate vararg setter for %s\n", f->name);
6072                     ir_builder_delete(ir);
6073                     return false;
6074                 }
6075                 if (!parser_create_array_getter_impl(parser, f->varargs)) {
6076                     con_out("failed to generate vararg getter for %s\n", f->name);
6077                     ir_builder_delete(ir);
6078                     return false;
6079                 }
6080             } else {
6081                 ast_delete(f->varargs);
6082                 f->varargs = NULL;
6083             }
6084         }
6085     }
6086     /* Now we can generate immediates */
6087     for (i = 0; i < vec_size(parser->imm_float); ++i) {
6088         if (!ast_global_codegen(parser->imm_float[i], ir, false)) {
6089             con_out("failed to generate global %s\n", parser->imm_float[i]->name);
6090             ir_builder_delete(ir);
6091             return false;
6092         }
6093     }
6094     for (i = 0; i < vec_size(parser->imm_string); ++i) {
6095         if (!ast_global_codegen(parser->imm_string[i], ir, false)) {
6096             con_out("failed to generate global %s\n", parser->imm_string[i]->name);
6097             ir_builder_delete(ir);
6098             return false;
6099         }
6100     }
6101     for (i = 0; i < vec_size(parser->imm_vector); ++i) {
6102         if (!ast_global_codegen(parser->imm_vector[i], ir, false)) {
6103             con_out("failed to generate global %s\n", parser->imm_vector[i]->name);
6104             ir_builder_delete(ir);
6105             return false;
6106         }
6107     }
6108     for (i = 0; i < vec_size(parser->globals); ++i) {
6109         ast_value *asvalue;
6110         if (!ast_istype(parser->globals[i], ast_value))
6111             continue;
6112         asvalue = (ast_value*)(parser->globals[i]);
6113         if (!(asvalue->expression.flags & AST_FLAG_INITIALIZED))
6114         {
6115             if (asvalue->cvq == CV_CONST && !asvalue->hasvalue)
6116                 (void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_CONSTANT,
6117                                        "uninitialized constant: `%s`",
6118                                        asvalue->name);
6119             else if ((asvalue->cvq == CV_NONE || asvalue->cvq == CV_CONST) && !asvalue->hasvalue)
6120                 (void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_GLOBAL,
6121                                        "uninitialized global: `%s`",
6122                                        asvalue->name);
6123         }
6124         if (!ast_generate_accessors(asvalue, ir)) {
6125             ir_builder_delete(ir);
6126             return false;
6127         }
6128     }
6129     for (i = 0; i < vec_size(parser->fields); ++i) {
6130         ast_value *asvalue;
6131         asvalue = (ast_value*)(parser->fields[i]->expression.next);
6132
6133         if (!ast_istype((ast_expression*)asvalue, ast_value))
6134             continue;
6135         if (asvalue->expression.vtype != TYPE_ARRAY)
6136             continue;
6137         if (!ast_generate_accessors(asvalue, ir)) {
6138             ir_builder_delete(ir);
6139             return false;
6140         }
6141     }
6142     if (parser->reserved_version &&
6143         !ast_global_codegen(parser->reserved_version, ir, false))
6144     {
6145         con_out("failed to generate reserved::version");
6146         ir_builder_delete(ir);
6147         return false;
6148     }
6149     for (i = 0; i < vec_size(parser->functions); ++i) {
6150         ast_function *f = parser->functions[i];
6151         if (!ast_function_codegen(f, ir)) {
6152             con_out("failed to generate function %s\n", f->name);
6153             ir_builder_delete(ir);
6154             return false;
6155         }
6156     }
6157     if (OPTS_OPTION_BOOL(OPTION_DUMP))
6158         ir_builder_dump(ir, con_out);
6159     for (i = 0; i < vec_size(parser->functions); ++i) {
6160         if (!ir_function_finalize(parser->functions[i]->ir_func)) {
6161             con_out("failed to finalize function %s\n", parser->functions[i]->name);
6162             ir_builder_delete(ir);
6163             return false;
6164         }
6165     }
6166
6167     if (compile_Werrors) {
6168         con_out("*** there were warnings treated as errors\n");
6169         compile_show_werrors();
6170         retval = false;
6171     }
6172
6173     if (retval) {
6174         if (OPTS_OPTION_BOOL(OPTION_DUMPFIN))
6175             ir_builder_dump(ir, con_out);
6176
6177         generate_checksum(parser);
6178
6179         if (!ir_builder_generate(ir, output)) {
6180             con_out("*** failed to generate output file\n");
6181             ir_builder_delete(ir);
6182             return false;
6183         }
6184     }
6185
6186     ir_builder_delete(ir);
6187     return retval;
6188 }