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