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