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