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