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