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