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