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