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