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