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