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