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