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