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