The problem was so subtle
[xonotic/gmqcc.git] / parser.c
1 /*
2  * Copyright (C) 2012, 2013
3  *     Wolfgang Bumiller
4  *     Dale Weiler
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy of
7  * this software and associated documentation files (the "Software"), to deal in
8  * the Software without restriction, including without limitation the rights to
9  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is furnished to do
11  * so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include <string.h>
25 #include <math.h>
26 #include "parser.h"
27
28 #define PARSER_HT_LOCALS  2
29 #define PARSER_HT_SIZE    512
30 #define TYPEDEF_HT_SIZE   512
31
32 static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1;
33
34 static void parser_enterblock(parser_t *parser);
35 static bool parser_leaveblock(parser_t *parser);
36 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
37 static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e);
38 static bool parse_typedef(parser_t *parser);
39 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
40 static ast_block* parse_block(parser_t *parser);
41 static bool parse_block_into(parser_t *parser, ast_block *block);
42 static bool parse_statement_or_block(parser_t *parser, ast_expression **out);
43 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases);
44 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels);
45 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels);
46 static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname);
47 static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname);
48 static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
49
50 static void parseerror(parser_t *parser, const char *fmt, ...)
51 {
52     va_list ap;
53     va_start(ap, fmt);
54     vcompile_error(parser->lex->tok.ctx, fmt, ap);
55     va_end(ap);
56 }
57
58 /* returns true if it counts as an error */
59 static bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, ...)
60 {
61     bool    r;
62     va_list ap;
63     va_start(ap, fmt);
64     r = vcompile_warning(parser->lex->tok.ctx, warntype, fmt, ap);
65     va_end(ap);
66     return r;
67 }
68
69 /**********************************************************************
70  * parsing
71  */
72
73 static bool parser_next(parser_t *parser)
74 {
75     /* lex_do kills the previous token */
76     parser->tok = lex_do(parser->lex);
77     if (parser->tok == TOKEN_EOF)
78         return true;
79     if (parser->tok >= TOKEN_ERROR) {
80         parseerror(parser, "lex error");
81         return false;
82     }
83     return true;
84 }
85
86 #define parser_tokval(p) ((p)->lex->tok.value)
87 #define parser_token(p)  (&((p)->lex->tok))
88
89 char *parser_strdup(const char *str)
90 {
91     if (str && !*str) {
92         /* actually dup empty strings */
93         char *out = (char*)mem_a(1);
94         *out = 0;
95         return out;
96     }
97     return util_strdup(str);
98 }
99
100 static ast_expression* parser_find_field(parser_t *parser, const char *name)
101 {
102     return ( ast_expression*)util_htget(parser->htfields, name);
103 }
104
105 static ast_expression* parser_find_label(parser_t *parser, const char *name)
106 {
107     size_t i;
108     for(i = 0; i < vec_size(parser->labels); i++)
109         if (!strcmp(parser->labels[i]->name, name))
110             return (ast_expression*)parser->labels[i];
111     return NULL;
112 }
113
114 static ast_expression* parser_find_global(parser_t *parser, const char *name)
115 {
116     ast_expression *var = (ast_expression*)util_htget(parser->aliases, parser_tokval(parser));
117     if (var)
118         return var;
119     return (ast_expression*)util_htget(parser->htglobals, name);
120 }
121
122 static ast_expression* parser_find_param(parser_t *parser, const char *name)
123 {
124     size_t i;
125     ast_value *fun;
126     if (!parser->function)
127         return NULL;
128     fun = parser->function->vtype;
129     for (i = 0; i < vec_size(fun->expression.params); ++i) {
130         if (!strcmp(fun->expression.params[i]->name, name))
131             return (ast_expression*)(fun->expression.params[i]);
132     }
133     return NULL;
134 }
135
136 static ast_expression* parser_find_local(parser_t *parser, const char *name, size_t upto, bool *isparam)
137 {
138     size_t          i, hash;
139     ast_expression *e;
140
141     hash = util_hthash(parser->htglobals, name);
142
143     *isparam = false;
144     for (i = vec_size(parser->variables); i > upto;) {
145         --i;
146         if ( (e = (ast_expression*)util_htgeth(parser->variables[i], name, hash)) )
147             return e;
148     }
149     *isparam = true;
150     return parser_find_param(parser, name);
151 }
152
153 static ast_expression* parser_find_var(parser_t *parser, const char *name)
154 {
155     bool dummy;
156     ast_expression *v;
157     v         = parser_find_local(parser, name, 0, &dummy);
158     if (!v) v = parser_find_global(parser, name);
159     return v;
160 }
161
162 static ast_value* parser_find_typedef(parser_t *parser, const char *name, size_t upto)
163 {
164     size_t     i, hash;
165     ast_value *e;
166     hash = util_hthash(parser->typedefs[0], name);
167
168     for (i = vec_size(parser->typedefs); i > upto;) {
169         --i;
170         if ( (e = (ast_value*)util_htgeth(parser->typedefs[i], name, hash)) )
171             return e;
172     }
173     return NULL;
174 }
175
176 /* include intrinsics */
177 #include "intrin.h"
178
179 typedef struct
180 {
181     size_t etype; /* 0 = expression, others are operators */
182     bool            isparen;
183     size_t          off;
184     ast_expression *out;
185     ast_block      *block; /* for commas and function calls */
186     lex_ctx_t ctx;
187 } sy_elem;
188
189 enum {
190     PAREN_EXPR,
191     PAREN_FUNC,
192     PAREN_INDEX,
193     PAREN_TERNARY1,
194     PAREN_TERNARY2
195 };
196 typedef struct
197 {
198     sy_elem        *out;
199     sy_elem        *ops;
200     size_t         *argc;
201     unsigned int   *paren;
202 } shunt;
203
204 static sy_elem syexp(lex_ctx_t ctx, ast_expression *v) {
205     sy_elem e;
206     e.etype = 0;
207     e.off   = 0;
208     e.out   = v;
209     e.block = NULL;
210     e.ctx   = ctx;
211     e.isparen = false;
212     return e;
213 }
214
215 static sy_elem syblock(lex_ctx_t ctx, ast_block *v) {
216     sy_elem e;
217     e.etype = 0;
218     e.off   = 0;
219     e.out   = (ast_expression*)v;
220     e.block = v;
221     e.ctx   = ctx;
222     e.isparen = false;
223     return e;
224 }
225
226 static sy_elem syop(lex_ctx_t ctx, const oper_info *op) {
227     sy_elem e;
228     e.etype = 1 + (op - operators);
229     e.off   = 0;
230     e.out   = NULL;
231     e.block = NULL;
232     e.ctx   = ctx;
233     e.isparen = false;
234     return e;
235 }
236
237 static sy_elem syparen(lex_ctx_t ctx, size_t off) {
238     sy_elem e;
239     e.etype = 0;
240     e.off   = off;
241     e.out   = NULL;
242     e.block = NULL;
243     e.ctx   = ctx;
244     e.isparen = true;
245     return e;
246 }
247
248 /* With regular precedence rules, ent.foo[n] is the same as (ent.foo)[n],
249  * so we need to rotate it to become ent.(foo[n]).
250  */
251 static bool rotate_entfield_array_index_nodes(ast_expression **out)
252 {
253     ast_array_index *index, *oldindex;
254     ast_entfield    *entfield;
255
256     ast_value       *field;
257     ast_expression  *sub;
258     ast_expression  *entity;
259
260     lex_ctx_t ctx = ast_ctx(*out);
261
262     if (!ast_istype(*out, ast_array_index))
263         return false;
264     index = (ast_array_index*)*out;
265
266     if (!ast_istype(index->array, ast_entfield))
267         return false;
268     entfield = (ast_entfield*)index->array;
269
270     if (!ast_istype(entfield->field, ast_value))
271         return false;
272     field = (ast_value*)entfield->field;
273
274     sub    = index->index;
275     entity = entfield->entity;
276
277     oldindex = index;
278
279     index = ast_array_index_new(ctx, (ast_expression*)field, sub);
280     entfield = ast_entfield_new(ctx, entity, (ast_expression*)index);
281     *out = (ast_expression*)entfield;
282
283     oldindex->array = NULL;
284     oldindex->index = NULL;
285     ast_delete(oldindex);
286
287     return true;
288 }
289
290 static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
291 {
292     const oper_info *op;
293     lex_ctx_t ctx;
294     ast_expression *out = NULL;
295     ast_expression *exprs[3];
296     ast_block      *blocks[3];
297     ast_value      *asvalue[3];
298     ast_binstore   *asbinstore;
299     size_t i, assignop, addop, subop;
300     qcint_t  generated_op = 0;
301
302     char ty1[1024];
303     char ty2[1024];
304
305     if (!vec_size(sy->ops)) {
306         parseerror(parser, "internal error: missing operator");
307         return false;
308     }
309
310     if (vec_last(sy->ops).isparen) {
311         parseerror(parser, "unmatched parenthesis");
312         return false;
313     }
314
315     op = &operators[vec_last(sy->ops).etype - 1];
316     ctx = vec_last(sy->ops).ctx;
317
318     if (vec_size(sy->out) < op->operands) {
319         compile_error(ctx, "internal error: not enough operands: %i (operator %s (%i))", vec_size(sy->out),
320                       op->op, (int)op->id);
321         return false;
322     }
323
324     vec_shrinkby(sy->ops, 1);
325
326     /* op(:?) has no input and no output */
327     if (!op->operands)
328         return true;
329
330     vec_shrinkby(sy->out, op->operands);
331     for (i = 0; i < op->operands; ++i) {
332         exprs[i]  = sy->out[vec_size(sy->out)+i].out;
333         blocks[i] = sy->out[vec_size(sy->out)+i].block;
334         asvalue[i] = (ast_value*)exprs[i];
335
336         if (exprs[i]->vtype == TYPE_NOEXPR &&
337             !(i != 0 && op->id == opid2('?',':')) &&
338             !(i == 1 && op->id == opid1('.')))
339         {
340             if (ast_istype(exprs[i], ast_label))
341                 compile_error(ast_ctx(exprs[i]), "expected expression, got an unknown identifier");
342             else
343                 compile_error(ast_ctx(exprs[i]), "not an expression");
344             (void)!compile_warning(ast_ctx(exprs[i]), WARN_DEBUG, "expression %u\n", (unsigned int)i);
345         }
346     }
347
348     if (blocks[0] && !vec_size(blocks[0]->exprs) && op->id != opid1(',')) {
349         compile_error(ctx, "internal error: operator cannot be applied on empty blocks");
350         return false;
351     }
352
353 #define NotSameType(T) \
354              (exprs[0]->vtype != exprs[1]->vtype || \
355               exprs[0]->vtype != T)
356
357     /* preform any constant folding on operator usage first */
358     /*if ((out = fold_op(parser->fold, op, exprs)))*/
359     /*goto complete;*/
360
361     switch (op->id)
362     {
363         default:
364             compile_error(ctx, "internal error: unhandled operator: %s (%i)", op->op, (int)op->id);
365             return false;
366
367         case opid1('.'):
368             if (exprs[0]->vtype == TYPE_VECTOR &&
369                 exprs[1]->vtype == TYPE_NOEXPR)
370             {
371                 if      (exprs[1] == (ast_expression*)parser->const_vec[0])
372                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
373                 else if (exprs[1] == (ast_expression*)parser->const_vec[1])
374                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
375                 else if (exprs[1] == (ast_expression*)parser->const_vec[2])
376                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
377                 else {
378                     compile_error(ctx, "access to invalid vector component");
379                     return false;
380                 }
381             }
382             else if (exprs[0]->vtype == TYPE_ENTITY) {
383                 if (exprs[1]->vtype != TYPE_FIELD) {
384                     compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
385                     return false;
386                 }
387                 out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
388             }
389             else if (exprs[0]->vtype == TYPE_VECTOR) {
390                 compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
391                 return false;
392             }
393             else {
394                 compile_error(ast_ctx(exprs[1]), "type error: member-of operator on something that is not an entity or vector");
395                 return false;
396             }
397             break;
398
399         case opid1('['):
400             if (exprs[0]->vtype != TYPE_ARRAY &&
401                 !(exprs[0]->vtype == TYPE_FIELD &&
402                   exprs[0]->next->vtype == TYPE_ARRAY))
403             {
404                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
405                 compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
406                 return false;
407             }
408             if (exprs[1]->vtype != TYPE_FLOAT) {
409                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
410                 compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
411                 return false;
412             }
413             out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]);
414             if (rotate_entfield_array_index_nodes(&out))
415             {
416 #if 0
417                 /* This is not broken in fteqcc anymore */
418                 if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
419                     /* this error doesn't need to make us bail out */
420                     (void)!parsewarning(parser, WARN_EXTENSIONS,
421                                         "accessing array-field members of an entity without parenthesis\n"
422                                         " -> this is an extension from -std=gmqcc");
423                 }
424 #endif
425             }
426             break;
427
428         case opid1(','):
429             if (vec_size(sy->paren) && vec_last(sy->paren) == PAREN_FUNC) {
430                 vec_push(sy->out, syexp(ctx, exprs[0]));
431                 vec_push(sy->out, syexp(ctx, exprs[1]));
432                 vec_last(sy->argc)++;
433                 return true;
434             }
435             if (blocks[0]) {
436                 if (!ast_block_add_expr(blocks[0], exprs[1]))
437                     return false;
438             } else {
439                 blocks[0] = ast_block_new(ctx);
440                 if (!ast_block_add_expr(blocks[0], exprs[0]) ||
441                     !ast_block_add_expr(blocks[0], exprs[1]))
442                 {
443                     return false;
444                 }
445             }
446             ast_block_set_type(blocks[0], exprs[1]);
447
448             vec_push(sy->out, syblock(ctx, blocks[0]));
449             return true;
450
451         case opid2('+','P'):
452             out = exprs[0];
453             break;
454         case opid2('-','P'):
455             if (!(out = fold_op(parser->fold, op, exprs))) {
456                 switch (exprs[0]->vtype) {
457                     case TYPE_FLOAT:
458                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F,
459                                                                   (ast_expression*)parser->fold->imm_float[0],
460                                                                   exprs[0]);
461                         break;
462                     case TYPE_VECTOR:
463                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V,
464                                                                   (ast_expression*)parser->fold->imm_vector[0],
465                                                                   exprs[0]);
466                         break;
467                     default:
468                     compile_error(ctx, "invalid types used in expression: cannot negate type %s",
469                                   type_name[exprs[0]->vtype]);
470                     return false;
471                 }
472             }
473             break;
474
475         case opid2('!','P'):
476             if (!(out = fold_op(parser->fold, op, exprs))) {
477                 switch (exprs[0]->vtype) {
478                     case TYPE_FLOAT:
479                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
480                         break;
481                     case TYPE_VECTOR:
482                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]);
483                         break;
484                     case TYPE_STRING:
485                         if (OPTS_FLAG(TRUE_EMPTY_STRINGS))
486                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
487                         else
488                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]);
489                         break;
490                     /* we don't constant-fold NOT for these types */
491                     case TYPE_ENTITY:
492                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_ENT, exprs[0]);
493                         break;
494                     case TYPE_FUNCTION:
495                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_FNC, exprs[0]);
496                         break;
497                     default:
498                     compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
499                                   type_name[exprs[0]->vtype]);
500                     return false;
501                 }
502             }
503             break;
504
505         case opid1('+'):
506             if (exprs[0]->vtype != exprs[1]->vtype ||
507                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
508             {
509                 compile_error(ctx, "invalid types used in expression: cannot add type %s and %s (%s %s)",
510                               type_name[exprs[0]->vtype],
511                               type_name[exprs[1]->vtype],
512                               asvalue[0]->name,
513                               asvalue[1]->name);
514                 return false;
515             }
516             if (!(out = fold_op(parser->fold, op, exprs))) {
517                 switch (exprs[0]->vtype) {
518                     case TYPE_FLOAT:
519                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
520                         break;
521                     case TYPE_VECTOR:
522                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
523                         break;
524                     default:
525                         compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
526                                       type_name[exprs[0]->vtype],
527                                       type_name[exprs[1]->vtype]);
528                         return false;
529                 }
530             }
531             break;
532         case opid1('-'):
533             if  (exprs[0]->vtype != exprs[1]->vtype ||
534                 (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT))
535             {
536                 compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
537                               type_name[exprs[1]->vtype],
538                               type_name[exprs[0]->vtype]);
539                 return false;
540             }
541             if (!(out = fold_op(parser->fold, op, exprs))) {
542                 switch (exprs[0]->vtype) {
543                     case TYPE_FLOAT:
544                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
545                         break;
546                     case TYPE_VECTOR:
547                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
548                         break;
549                     default:
550                         compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
551                                       type_name[exprs[1]->vtype],
552                                       type_name[exprs[0]->vtype]);
553                         return false;
554                 }
555             }
556             break;
557         case opid1('*'):
558             if (exprs[0]->vtype != exprs[1]->vtype &&
559                 !(exprs[0]->vtype == TYPE_VECTOR &&
560                   exprs[1]->vtype == TYPE_FLOAT) &&
561                 !(exprs[1]->vtype == TYPE_VECTOR &&
562                   exprs[0]->vtype == TYPE_FLOAT)
563                 )
564             {
565                 compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
566                               type_name[exprs[1]->vtype],
567                               type_name[exprs[0]->vtype]);
568                 return false;
569             }
570             if (!(out = fold_op(parser->fold, op, exprs))) {
571                 switch (exprs[0]->vtype) {
572                     case TYPE_FLOAT:
573                         if (exprs[1]->vtype == TYPE_VECTOR)
574                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
575                         else
576                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
577                         break;
578                     case TYPE_VECTOR:
579                         if (exprs[1]->vtype == TYPE_FLOAT)
580                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
581                         else
582                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
583                         break;
584                     default:
585                         compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
586                                       type_name[exprs[1]->vtype],
587                                       type_name[exprs[0]->vtype]);
588                         return false;
589                 }
590             }
591             break;
592
593         case opid1('/'):
594             if (exprs[1]->vtype != TYPE_FLOAT) {
595                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
596                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
597                 compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2);
598                 return false;
599             }
600             if (!(out = fold_op(parser->fold, op, exprs))) {
601                 if (exprs[0]->vtype == TYPE_FLOAT)
602                     out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
603                 else {
604                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
605                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
606                     compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2);
607                     return false;
608                 }
609             }
610             break;
611
612         case opid1('%'):
613             if (NotSameType(TYPE_FLOAT)) {
614                 compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s",
615                     type_name[exprs[0]->vtype],
616                     type_name[exprs[1]->vtype]);
617                 return false;
618             } else if (!(out = fold_op(parser->fold, op, exprs))) {
619                 /* generate a call to __builtin_mod */
620                 ast_expression *mod  = intrin_func(parser, "mod");
621                 ast_call       *call = NULL;
622                 if (!mod) return false; /* can return null for missing floor */
623
624                 call = ast_call_new(parser_ctx(parser), mod);
625                 vec_push(call->params, exprs[0]);
626                 vec_push(call->params, exprs[1]);
627
628                 out = (ast_expression*)call;
629             }
630             break;
631
632         case opid2('%','='):
633             compile_error(ctx, "%= is unimplemented");
634             return false;
635
636         case opid1('|'):
637         case opid1('&'):
638             if (NotSameType(TYPE_FLOAT)) {
639                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
640                               type_name[exprs[0]->vtype],
641                               type_name[exprs[1]->vtype]);
642                 return false;
643             }
644             if (!(out = fold_op(parser->fold, op, exprs)))
645                 out = (ast_expression*)ast_binary_new(ctx,
646                     (op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND),
647                     exprs[0], exprs[1]);
648             break;
649         case opid1('^'):
650             /*
651              * Okay lets designate what the hell is an acceptable use
652              * of the ^ operator. In many vector processing units, XOR
653              * is allowed to be used on vectors, but only if the first
654              * operand is a vector, the second operand can be a float
655              * or vector. It's never legal for the first operand to be
656              * a float, and then the following operand to be a vector.
657              * Further more, the only time it is legal to do XOR otherwise
658              * is when both operand are floats. This nicely crafted if
659              * statement catches them all.
660              *
661              * In the event that the first operand is a vector, two
662              * possible situations can arise, thus, each element of
663              * vector A (operand A) is exclusive-ORed with the corresponding
664              * element of vector B (operand B), If B is scalar, the
665              * scalar value is first replicated for each element.
666              *
667              * The QCVM itself lacks a BITXOR instruction. Thus emulating
668              * the mathematics of it is required. The following equation
669              * is used: (LHS | RHS) & ~(LHS & RHS). However, due to the
670              * QCVM also lacking a BITNEG instruction, we need to emulate
671              * ~FOO with -1 - FOO, the whole process becoming this nicely
672              * crafted expression: (LHS | RHS) & (-1 - (LHS & RHS)).
673              *
674              * When A is not scalar, this process is repeated for all
675              * components of vector A with the value in operand B,
676              * only if operand B is scalar. When A is not scalar, and B
677              * is also not scalar, this process is repeated for all
678              * components of the vector A with the components of vector B.
679              * Finally when A is scalar and B is scalar, this process is
680              * simply used once for A and B being LHS and RHS respectfully.
681              *
682              * Yes the semantics are a bit strange (no pun intended).
683              * But then again BITXOR is strange itself, consdering it's
684              * commutative, assocative, and elements of the BITXOR operation
685              * are their own inverse.
686              */
687             if ( !(exprs[0]->vtype == TYPE_FLOAT  && exprs[1]->vtype == TYPE_FLOAT) &&
688                  !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_FLOAT) &&
689                  !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_VECTOR))
690             {
691                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
692                               type_name[exprs[0]->vtype],
693                               type_name[exprs[1]->vtype]);
694                 return false;
695             }
696
697             if (!(out = fold_op(parser->fold, op, exprs))) {
698                 /*
699                  * IF the first expression is float, the following will be too
700                  * since scalar ^ vector is not allowed.
701                  */
702                 if (exprs[0]->vtype == TYPE_FLOAT) {
703                     ast_binary *expr = ast_binary_new(
704                         ctx,
705                         INSTR_SUB_F,
706                         (ast_expression*)parser->fold->imm_float[2],
707                         (ast_expression*)ast_binary_new(
708                             ctx,
709                             INSTR_BITAND,
710                             exprs[0],
711                             exprs[1]
712                         )
713                     );
714                     expr->refs = AST_REF_NONE;
715
716                     out = (ast_expression*)
717                         ast_binary_new(
718                             ctx,
719                             INSTR_BITAND,
720                             (ast_expression*)ast_binary_new(
721                                 ctx,
722                                 INSTR_BITOR,
723                                 exprs[0],
724                                 exprs[1]
725                             ),
726                             (ast_expression*)expr
727                         );
728                 } else {
729                     /*
730                      * The first is a vector: vector is allowed to xor with vector and
731                      * with scalar, branch here for the second operand.
732                      */
733                     if (exprs[1]->vtype == TYPE_VECTOR) {
734                         /*
735                          * Xor all the values of the vector components against the
736                          * vectors components in question.
737                          */
738                         compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against vector");
739                         return false;
740                     } else {
741                         compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against float");
742                         return false;
743                     }
744                 }
745             }
746             break;
747
748         case opid2('<','<'):
749         case opid2('>','>'):
750         case opid3('<','<','='):
751         case opid3('>','>','='):
752             if(!(out = fold_op(parser->fold, op, exprs))) {
753                 compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts");
754                 return false;
755             }
756
757         case opid2('|','|'):
758             generated_op += 1; /* INSTR_OR */
759         case opid2('&','&'):
760             generated_op += INSTR_AND;
761             if (!(out = fold_op(parser->fold, op, exprs))) {
762                 if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) {
763                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
764                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
765                     compile_error(ctx, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2);
766                     return false;
767                 }
768                 for (i = 0; i < 2; ++i) {
769                     if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) {
770                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
771                         if (!out) break;
772                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
773                         if (!out) break;
774                         exprs[i] = out; out = NULL;
775                         if (OPTS_FLAG(PERL_LOGIC)) {
776                             /* here we want to keep the right expressions' type */
777                             break;
778                         }
779                     }
780                     else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) {
781                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
782                         if (!out) break;
783                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
784                         if (!out) break;
785                         exprs[i] = out; out = NULL;
786                         if (OPTS_FLAG(PERL_LOGIC)) {
787                             /* here we want to keep the right expressions' type */
788                             break;
789                         }
790                     }
791                 }
792                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
793             }
794             break;
795
796         case opid2('?',':'):
797             if (vec_last(sy->paren) != PAREN_TERNARY2) {
798                 compile_error(ctx, "mismatched parenthesis/ternary");
799                 return false;
800             }
801             vec_pop(sy->paren);
802             if (!ast_compare_type(exprs[1], exprs[2])) {
803                 ast_type_to_string(exprs[1], ty1, sizeof(ty1));
804                 ast_type_to_string(exprs[2], ty2, sizeof(ty2));
805                 compile_error(ctx, "operands of ternary expression must have the same type, got %s and %s", ty1, ty2);
806                 return false;
807             }
808             if (!(out = fold_op(parser->fold, op, exprs)))
809                 out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]);
810             break;
811
812         case opid2('*', '*'):
813             if (NotSameType(TYPE_FLOAT)) {
814                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
815                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
816                 compile_error(ctx, "invalid types used in exponentiation: %s and %s",
817                     ty1, ty2);
818                 return false;
819             }
820             
821             if (!(out = fold_op(parser->fold, op, exprs))) {
822                 ast_call *gencall = ast_call_new(parser_ctx(parser), intrin_func(parser, "pow"));
823                 vec_push(gencall->params, exprs[0]);
824                 vec_push(gencall->params, exprs[1]);
825                 out = (ast_expression*)gencall;
826             }
827             break;
828
829         case opid3('<','=','>'): /* -1, 0, or 1 */
830             if (NotSameType(TYPE_FLOAT)) {
831                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
832                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
833                 compile_error(ctx, "invalid types used in comparision: %s and %s",
834                     ty1, ty2);
835
836                 return false;
837             } 
838
839             if (!(out = fold_op(parser->fold, op, exprs))) {
840                 ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
841
842                 eq->refs = AST_REF_NONE;
843
844                     /* if (lt) { */
845                 out = (ast_expression*)ast_ternary_new(ctx,
846                         (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]),
847                         /* out = -1 */
848                         (ast_expression*)parser->fold->imm_float[2],
849                     /* } else { */
850                         /* if (eq) { */
851                         (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq,
852                             /* out = 0 */
853                             (ast_expression*)parser->fold->imm_float[0],
854                         /* } else { */
855                             /* out = 1 */
856                             (ast_expression*)parser->fold->imm_float[1]
857                         /* } */
858                         )
859                     /* } */
860                     );
861
862             }
863             break;
864
865         case opid1('>'):
866             generated_op += 1; /* INSTR_GT */
867         case opid1('<'):
868             generated_op += 1; /* INSTR_LT */
869         case opid2('>', '='):
870             generated_op += 1; /* INSTR_GE */
871         case opid2('<', '='):
872             generated_op += INSTR_LE;
873             if (NotSameType(TYPE_FLOAT)) {
874                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
875                               type_name[exprs[0]->vtype],
876                               type_name[exprs[1]->vtype]);
877                 return false;
878             }
879             if (!(out = fold_op(parser->fold, op, exprs)))
880                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
881             break;
882         case opid2('!', '='):
883             if (exprs[0]->vtype != exprs[1]->vtype) {
884                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
885                               type_name[exprs[0]->vtype],
886                               type_name[exprs[1]->vtype]);
887                 return false;
888             }
889             if (!(out = fold_op(parser->fold, op, exprs)))
890                 out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
891             break;
892         case opid2('=', '='):
893             if (exprs[0]->vtype != exprs[1]->vtype) {
894                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
895                               type_name[exprs[0]->vtype],
896                               type_name[exprs[1]->vtype]);
897                 return false;
898             }
899             if (!(out = fold_op(parser->fold, op, exprs)))
900                 out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
901             break;
902
903         case opid1('='):
904             if (ast_istype(exprs[0], ast_entfield)) {
905                 ast_expression *field = ((ast_entfield*)exprs[0])->field;
906                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
907                     exprs[0]->vtype == TYPE_FIELD &&
908                     exprs[0]->next->vtype == TYPE_VECTOR)
909                 {
910                     assignop = type_storep_instr[TYPE_VECTOR];
911                 }
912                 else
913                     assignop = type_storep_instr[exprs[0]->vtype];
914                 if (assignop == VINSTR_END || !ast_compare_type(field->next, exprs[1]))
915                 {
916                     ast_type_to_string(field->next, ty1, sizeof(ty1));
917                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
918                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
919                         field->next->vtype == TYPE_FUNCTION &&
920                         exprs[1]->vtype == TYPE_FUNCTION)
921                     {
922                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
923                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
924                     }
925                     else
926                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
927                 }
928             }
929             else
930             {
931                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
932                     exprs[0]->vtype == TYPE_FIELD &&
933                     exprs[0]->next->vtype == TYPE_VECTOR)
934                 {
935                     assignop = type_store_instr[TYPE_VECTOR];
936                 }
937                 else {
938                     assignop = type_store_instr[exprs[0]->vtype];
939                 }
940
941                 if (assignop == VINSTR_END) {
942                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
943                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
944                     compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
945                 }
946                 else if (!ast_compare_type(exprs[0], exprs[1]))
947                 {
948                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
949                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
950                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
951                         exprs[0]->vtype == TYPE_FUNCTION &&
952                         exprs[1]->vtype == TYPE_FUNCTION)
953                     {
954                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
955                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
956                     }
957                     else
958                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
959                 }
960             }
961             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
962                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
963             }
964             out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]);
965             break;
966         case opid3('+','+','P'):
967         case opid3('-','-','P'):
968             /* prefix ++ */
969             if (exprs[0]->vtype != TYPE_FLOAT) {
970                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
971                 compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
972                 return false;
973             }
974             if (op->id == opid3('+','+','P'))
975                 addop = INSTR_ADD_F;
976             else
977                 addop = INSTR_SUB_F;
978             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
979                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
980             }
981             if (ast_istype(exprs[0], ast_entfield)) {
982                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
983                                                         exprs[0],
984                                                         (ast_expression*)parser->fold->imm_float[1]);
985             } else {
986                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
987                                                         exprs[0],
988                                                         (ast_expression*)parser->fold->imm_float[1]);
989             }
990             break;
991         case opid3('S','+','+'):
992         case opid3('S','-','-'):
993             /* prefix ++ */
994             if (exprs[0]->vtype != TYPE_FLOAT) {
995                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
996                 compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
997                 return false;
998             }
999             if (op->id == opid3('S','+','+')) {
1000                 addop = INSTR_ADD_F;
1001                 subop = INSTR_SUB_F;
1002             } else {
1003                 addop = INSTR_SUB_F;
1004                 subop = INSTR_ADD_F;
1005             }
1006             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1007                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
1008             }
1009             if (ast_istype(exprs[0], ast_entfield)) {
1010                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
1011                                                         exprs[0],
1012                                                         (ast_expression*)parser->fold->imm_float[1]);
1013             } else {
1014                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
1015                                                         exprs[0],
1016                                                         (ast_expression*)parser->fold->imm_float[1]);
1017             }
1018             if (!out)
1019                 return false;
1020             out = (ast_expression*)ast_binary_new(ctx, subop,
1021                                                   out,
1022                                                   (ast_expression*)parser->fold->imm_float[1]);
1023             break;
1024         case opid2('+','='):
1025         case opid2('-','='):
1026             if (exprs[0]->vtype != exprs[1]->vtype ||
1027                 (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
1028             {
1029                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1030                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1031                 compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1032                               ty1, ty2);
1033                 return false;
1034             }
1035             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1036                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1037             }
1038             if (ast_istype(exprs[0], ast_entfield))
1039                 assignop = type_storep_instr[exprs[0]->vtype];
1040             else
1041                 assignop = type_store_instr[exprs[0]->vtype];
1042             switch (exprs[0]->vtype) {
1043                 case TYPE_FLOAT:
1044                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1045                                                             (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
1046                                                             exprs[0], exprs[1]);
1047                     break;
1048                 case TYPE_VECTOR:
1049                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1050                                                             (op->id == opid2('+','=') ? INSTR_ADD_V : INSTR_SUB_V),
1051                                                             exprs[0], exprs[1]);
1052                     break;
1053                 default:
1054                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1055                                   type_name[exprs[0]->vtype],
1056                                   type_name[exprs[1]->vtype]);
1057                     return false;
1058             };
1059             break;
1060         case opid2('*','='):
1061         case opid2('/','='):
1062             if (exprs[1]->vtype != TYPE_FLOAT ||
1063                 !(exprs[0]->vtype == TYPE_FLOAT ||
1064                   exprs[0]->vtype == TYPE_VECTOR))
1065             {
1066                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1067                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1068                 compile_error(ctx, "invalid types used in expression: %s and %s",
1069                               ty1, ty2);
1070                 return false;
1071             }
1072             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1073                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1074             }
1075             if (ast_istype(exprs[0], ast_entfield))
1076                 assignop = type_storep_instr[exprs[0]->vtype];
1077             else
1078                 assignop = type_store_instr[exprs[0]->vtype];
1079             switch (exprs[0]->vtype) {
1080                 case TYPE_FLOAT:
1081                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1082                                                             (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
1083                                                             exprs[0], exprs[1]);
1084                     break;
1085                 case TYPE_VECTOR:
1086                     if (op->id == opid2('*','=')) {
1087                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1088                                                                 exprs[0], exprs[1]);
1089                     } else {
1090                         out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
1091                                                                   (ast_expression*)parser->fold->imm_float[1],
1092                                                                   exprs[1]);
1093                         if (!out) {
1094                             compile_error(ctx, "internal error: failed to generate division");
1095                             return false;
1096                         }
1097                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1098                                                                 exprs[0], out);
1099                     }
1100                     break;
1101                 default:
1102                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1103                                   type_name[exprs[0]->vtype],
1104                                   type_name[exprs[1]->vtype]);
1105                     return false;
1106             };
1107             break;
1108         case opid2('&','='):
1109         case opid2('|','='):
1110             if (NotSameType(TYPE_FLOAT)) {
1111                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1112                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1113                 compile_error(ctx, "invalid types used in expression: %s and %s",
1114                               ty1, ty2);
1115                 return false;
1116             }
1117             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1118                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1119             }
1120             if (ast_istype(exprs[0], ast_entfield))
1121                 assignop = type_storep_instr[exprs[0]->vtype];
1122             else
1123                 assignop = type_store_instr[exprs[0]->vtype];
1124             out = (ast_expression*)ast_binstore_new(ctx, assignop,
1125                                                     (op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
1126                                                     exprs[0], exprs[1]);
1127             break;
1128         case opid3('&','~','='):
1129             /* This is like: a &= ~(b);
1130              * But QC has no bitwise-not, so we implement it as
1131              * a -= a & (b);
1132              */
1133             if (NotSameType(TYPE_FLOAT)) {
1134                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1135                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1136                 compile_error(ctx, "invalid types used in expression: %s and %s",
1137                               ty1, ty2);
1138                 return false;
1139             }
1140             if (ast_istype(exprs[0], ast_entfield))
1141                 assignop = type_storep_instr[exprs[0]->vtype];
1142             else
1143                 assignop = type_store_instr[exprs[0]->vtype];
1144             out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
1145             if (!out)
1146                 return false;
1147             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1148                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1149             }
1150             asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out);
1151             asbinstore->keep_dest = true;
1152             out = (ast_expression*)asbinstore;
1153             break;
1154
1155         case opid2('~', 'P'):
1156             if (exprs[0]->vtype != TYPE_FLOAT) {
1157                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1158                 compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
1159                 return false;
1160             }
1161             if (!(out = fold_op(parser->fold, op, exprs)))
1162                 out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]);
1163             break;
1164     }
1165 #undef NotSameType
1166 /*complete:*/
1167     if (!out) {
1168         compile_error(ctx, "failed to apply operator %s", op->op);
1169         return false;
1170     }
1171
1172     vec_push(sy->out, syexp(ctx, out));
1173     return true;
1174 }
1175
1176 static bool parser_close_call(parser_t *parser, shunt *sy)
1177 {
1178     /* was a function call */
1179     ast_expression *fun;
1180     ast_value      *funval = NULL;
1181     ast_call       *call;
1182
1183     size_t          fid;
1184     size_t          paramcount, i;
1185
1186     fid = vec_last(sy->ops).off;
1187     vec_shrinkby(sy->ops, 1);
1188
1189     /* out[fid] is the function
1190      * everything above is parameters...
1191      */
1192     if (!vec_size(sy->argc)) {
1193         parseerror(parser, "internal error: no argument counter available");
1194         return false;
1195     }
1196
1197     paramcount = vec_last(sy->argc);
1198     vec_pop(sy->argc);
1199
1200     if (vec_size(sy->out) < fid) {
1201         parseerror(parser, "internal error: broken function call%lu < %lu+%lu\n",
1202                    (unsigned long)vec_size(sy->out),
1203                    (unsigned long)fid,
1204                    (unsigned long)paramcount);
1205         return false;
1206     }
1207
1208     fun = sy->out[fid].out;
1209
1210     if (fun == intrinsic_debug_typestring) {
1211         char ty[1024];
1212         if (fid+2 != vec_size(sy->out) ||
1213             vec_last(sy->out).block)
1214         {
1215             parseerror(parser, "intrinsic __builtin_debug_typestring requires exactly 1 parameter");
1216             return false;
1217         }
1218         ast_type_to_string(vec_last(sy->out).out, ty, sizeof(ty));
1219         ast_unref(vec_last(sy->out).out);
1220         sy->out[fid] = syexp(ast_ctx(vec_last(sy->out).out),
1221                              (ast_expression*)fold_constgen_string(parser->fold, ty, false));
1222         vec_shrinkby(sy->out, 1);
1223         return true;
1224     }
1225
1226     call = ast_call_new(sy->ops[vec_size(sy->ops)].ctx, fun);
1227     if (!call)
1228         return false;
1229
1230     if (fid+1 < vec_size(sy->out))
1231         ++paramcount;
1232
1233     if (fid+1 + paramcount != vec_size(sy->out)) {
1234         parseerror(parser, "internal error: parameter count mismatch: (%lu+1+%lu), %lu",
1235                    (unsigned long)fid, (unsigned long)paramcount, (unsigned long)vec_size(sy->out));
1236         return false;
1237     }
1238
1239     for (i = 0; i < paramcount; ++i)
1240         vec_push(call->params, sy->out[fid+1 + i].out);
1241     vec_shrinkby(sy->out, paramcount);
1242     (void)!ast_call_check_types(call, parser->function->vtype->expression.varparam);
1243     if (parser->max_param_count < paramcount)
1244         parser->max_param_count = paramcount;
1245
1246     if (ast_istype(fun, ast_value)) {
1247         funval = (ast_value*)fun;
1248         if ((fun->flags & AST_FLAG_VARIADIC) &&
1249             !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
1250         {
1251             call->va_count = (ast_expression*)fold_constgen_float(parser->fold, (qcfloat_t)paramcount);
1252         }
1253     }
1254
1255     /* overwrite fid, the function, with a call */
1256     sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
1257
1258     if (fun->vtype != TYPE_FUNCTION) {
1259         parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
1260         return false;
1261     }
1262
1263     if (!fun->next) {
1264         parseerror(parser, "could not determine function return type");
1265         return false;
1266     } else {
1267         ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
1268
1269         if (fun->flags & AST_FLAG_DEPRECATED) {
1270             if (!fval) {
1271                 return !parsewarning(parser, WARN_DEPRECATED,
1272                         "call to function (which is marked deprecated)\n",
1273                         "-> it has been declared here: %s:%i",
1274                         ast_ctx(fun).file, ast_ctx(fun).line);
1275             }
1276             if (!fval->desc) {
1277                 return !parsewarning(parser, WARN_DEPRECATED,
1278                         "call to `%s` (which is marked deprecated)\n"
1279                         "-> `%s` declared here: %s:%i",
1280                         fval->name, fval->name, ast_ctx(fun).file, ast_ctx(fun).line);
1281             }
1282             return !parsewarning(parser, WARN_DEPRECATED,
1283                     "call to `%s` (deprecated: %s)\n"
1284                     "-> `%s` declared here: %s:%i",
1285                     fval->name, fval->desc, fval->name, ast_ctx(fun).file,
1286                     ast_ctx(fun).line);
1287         }
1288
1289         if (vec_size(fun->params) != paramcount &&
1290             !((fun->flags & AST_FLAG_VARIADIC) &&
1291               vec_size(fun->params) < paramcount))
1292         {
1293             const char *fewmany = (vec_size(fun->params) > paramcount) ? "few" : "many";
1294             if (fval)
1295                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1296                                      "too %s parameters for call to %s: expected %i, got %i\n"
1297                                      " -> `%s` has been declared here: %s:%i",
1298                                      fewmany, fval->name, (int)vec_size(fun->params), (int)paramcount,
1299                                      fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1300             else
1301                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1302                                      "too %s parameters for function call: expected %i, got %i\n"
1303                                      " -> it has been declared here: %s:%i",
1304                                      fewmany, (int)vec_size(fun->params), (int)paramcount,
1305                                      ast_ctx(fun).file, (int)ast_ctx(fun).line);
1306         }
1307     }
1308
1309     return true;
1310 }
1311
1312 static bool parser_close_paren(parser_t *parser, shunt *sy)
1313 {
1314     if (!vec_size(sy->ops)) {
1315         parseerror(parser, "unmatched closing paren");
1316         return false;
1317     }
1318
1319     while (vec_size(sy->ops)) {
1320         if (vec_last(sy->ops).isparen) {
1321             if (vec_last(sy->paren) == PAREN_FUNC) {
1322                 vec_pop(sy->paren);
1323                 if (!parser_close_call(parser, sy))
1324                     return false;
1325                 break;
1326             }
1327             if (vec_last(sy->paren) == PAREN_EXPR) {
1328                 vec_pop(sy->paren);
1329                 if (!vec_size(sy->out)) {
1330                     compile_error(vec_last(sy->ops).ctx, "empty paren expression");
1331                     vec_shrinkby(sy->ops, 1);
1332                     return false;
1333                 }
1334                 vec_shrinkby(sy->ops, 1);
1335                 break;
1336             }
1337             if (vec_last(sy->paren) == PAREN_INDEX) {
1338                 vec_pop(sy->paren);
1339                 /* pop off the parenthesis */
1340                 vec_shrinkby(sy->ops, 1);
1341                 /* then apply the index operator */
1342                 if (!parser_sy_apply_operator(parser, sy))
1343                     return false;
1344                 break;
1345             }
1346             if (vec_last(sy->paren) == PAREN_TERNARY1) {
1347                 vec_last(sy->paren) = PAREN_TERNARY2;
1348                 /* pop off the parenthesis */
1349                 vec_shrinkby(sy->ops, 1);
1350                 break;
1351             }
1352             compile_error(vec_last(sy->ops).ctx, "invalid parenthesis");
1353             return false;
1354         }
1355         if (!parser_sy_apply_operator(parser, sy))
1356             return false;
1357     }
1358     return true;
1359 }
1360
1361 static void parser_reclassify_token(parser_t *parser)
1362 {
1363     size_t i;
1364     if (parser->tok >= TOKEN_START)
1365         return;
1366     for (i = 0; i < operator_count; ++i) {
1367         if (!strcmp(parser_tokval(parser), operators[i].op)) {
1368             parser->tok = TOKEN_OPERATOR;
1369             return;
1370         }
1371     }
1372 }
1373
1374 static ast_expression* parse_vararg_do(parser_t *parser)
1375 {
1376     ast_expression *idx, *out;
1377     ast_value      *typevar;
1378     ast_value      *funtype = parser->function->vtype;
1379     lex_ctx_t         ctx     = parser_ctx(parser);
1380
1381     if (!parser->function->varargs) {
1382         parseerror(parser, "function has no variable argument list");
1383         return NULL;
1384     }
1385
1386     if (!parser_next(parser) || parser->tok != '(') {
1387         parseerror(parser, "expected parameter index and type in parenthesis");
1388         return NULL;
1389     }
1390     if (!parser_next(parser)) {
1391         parseerror(parser, "error parsing parameter index");
1392         return NULL;
1393     }
1394
1395     idx = parse_expression_leave(parser, true, false, false);
1396     if (!idx)
1397         return NULL;
1398
1399     if (parser->tok != ',') {
1400         if (parser->tok != ')') {
1401             ast_unref(idx);
1402             parseerror(parser, "expected comma after parameter index");
1403             return NULL;
1404         }
1405         /* vararg piping: ...(start) */
1406         out = (ast_expression*)ast_argpipe_new(ctx, idx);
1407         return out;
1408     }
1409
1410     if (!parser_next(parser) || (parser->tok != TOKEN_IDENT && parser->tok != TOKEN_TYPENAME)) {
1411         ast_unref(idx);
1412         parseerror(parser, "expected typename for vararg");
1413         return NULL;
1414     }
1415
1416     typevar = parse_typename(parser, NULL, NULL);
1417     if (!typevar) {
1418         ast_unref(idx);
1419         return NULL;
1420     }
1421
1422     if (parser->tok != ')') {
1423         ast_unref(idx);
1424         ast_delete(typevar);
1425         parseerror(parser, "expected closing paren");
1426         return NULL;
1427     }
1428
1429     if (funtype->expression.varparam &&
1430         !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
1431     {
1432         char ty1[1024];
1433         char ty2[1024];
1434         ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1));
1435         ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2));
1436         compile_error(ast_ctx(typevar),
1437                       "function was declared to take varargs of type `%s`, requested type is: %s",
1438                       ty2, ty1);
1439     }
1440
1441     out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->varargs), idx);
1442     ast_type_adopt(out, typevar);
1443     ast_delete(typevar);
1444     return out;
1445 }
1446
1447 static ast_expression* parse_vararg(parser_t *parser)
1448 {
1449     bool           old_noops = parser->lex->flags.noops;
1450
1451     ast_expression *out;
1452
1453     parser->lex->flags.noops = true;
1454     out = parse_vararg_do(parser);
1455
1456     parser->lex->flags.noops = old_noops;
1457     return out;
1458 }
1459
1460 /* not to be exposed */
1461 extern bool ftepp_predef_exists(const char *name);
1462
1463 static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
1464 {
1465     if (OPTS_FLAG(TRANSLATABLE_STRINGS) &&
1466         parser->tok == TOKEN_IDENT &&
1467         !strcmp(parser_tokval(parser), "_"))
1468     {
1469         /* a translatable string */
1470         ast_value *val;
1471
1472         parser->lex->flags.noops = true;
1473         if (!parser_next(parser) || parser->tok != '(') {
1474             parseerror(parser, "use _(\"string\") to create a translatable string constant");
1475             return false;
1476         }
1477         parser->lex->flags.noops = false;
1478         if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
1479             parseerror(parser, "expected a constant string in translatable-string extension");
1480             return false;
1481         }
1482         val = (ast_value*)fold_constgen_string(parser->fold, parser_tokval(parser), true);
1483         if (!val)
1484             return false;
1485         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1486
1487         if (!parser_next(parser) || parser->tok != ')') {
1488             parseerror(parser, "expected closing paren after translatable string");
1489             return false;
1490         }
1491         return true;
1492     }
1493     else if (parser->tok == TOKEN_DOTS)
1494     {
1495         ast_expression *va;
1496         if (!OPTS_FLAG(VARIADIC_ARGS)) {
1497             parseerror(parser, "cannot access varargs (try -fvariadic-args)");
1498             return false;
1499         }
1500         va = parse_vararg(parser);
1501         if (!va)
1502             return false;
1503         vec_push(sy->out, syexp(parser_ctx(parser), va));
1504         return true;
1505     }
1506     else if (parser->tok == TOKEN_FLOATCONST) {
1507         ast_expression *val = fold_constgen_float(parser->fold, (parser_token(parser)->constval.f));
1508         if (!val)
1509             return false;
1510         vec_push(sy->out, syexp(parser_ctx(parser), val));
1511         return true;
1512     }
1513     else if (parser->tok == TOKEN_INTCONST || parser->tok == TOKEN_CHARCONST) {
1514         ast_expression *val = fold_constgen_float(parser->fold, (qcfloat_t)(parser_token(parser)->constval.i));
1515         if (!val)
1516             return false;
1517         vec_push(sy->out, syexp(parser_ctx(parser), val));
1518         return true;
1519     }
1520     else if (parser->tok == TOKEN_STRINGCONST) {
1521         ast_expression *val = fold_constgen_string(parser->fold, parser_tokval(parser), false);
1522         if (!val)
1523             return false;
1524         vec_push(sy->out, syexp(parser_ctx(parser), val));
1525         return true;
1526     }
1527     else if (parser->tok == TOKEN_VECTORCONST) {
1528         ast_expression *val = fold_constgen_vector(parser->fold, parser_token(parser)->constval.v);
1529         if (!val)
1530             return false;
1531         vec_push(sy->out, syexp(parser_ctx(parser), val));
1532         return true;
1533     }
1534     else if (parser->tok == TOKEN_IDENT)
1535     {
1536         const char     *ctoken = parser_tokval(parser);
1537         ast_expression *prev = vec_size(sy->out) ? vec_last(sy->out).out : NULL;
1538         ast_expression *var;
1539         /* a_vector.{x,y,z} */
1540         if (!vec_size(sy->ops) ||
1541             !vec_last(sy->ops).etype ||
1542             operators[vec_last(sy->ops).etype-1].id != opid1('.') ||
1543             (prev >= intrinsic_debug_typestring &&
1544              prev <= intrinsic_debug_typestring))
1545         {
1546             /* When adding more intrinsics, fix the above condition */
1547             prev = NULL;
1548         }
1549         if (prev && prev->vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
1550         {
1551             var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
1552         } else {
1553             var = parser_find_var(parser, parser_tokval(parser));
1554             if (!var)
1555                 var = parser_find_field(parser, parser_tokval(parser));
1556         }
1557         if (!var && with_labels) {
1558             var = (ast_expression*)parser_find_label(parser, parser_tokval(parser));
1559             if (!with_labels) {
1560                 ast_label *lbl = ast_label_new(parser_ctx(parser), parser_tokval(parser), true);
1561                 var = (ast_expression*)lbl;
1562                 vec_push(parser->labels, lbl);
1563             }
1564         }
1565         if (!var && !strcmp(parser_tokval(parser), "__FUNC__"))
1566             var = (ast_expression*)fold_constgen_string(parser->fold, parser->function->name, false);
1567         if (!var) {
1568             /* intrinsics */
1569             if (!strcmp(parser_tokval(parser), "__builtin_debug_typestring")) {
1570                 var = (ast_expression*)intrinsic_debug_typestring;
1571             }
1572             /* now we try for the real intrinsic hashtable. If the string
1573              * begins with __builtin, we simply skip past it, otherwise we
1574              * use the identifier as is.
1575              */
1576             else if (!strncmp(parser_tokval(parser), "__builtin_", 10)) {
1577                 var = intrin_func(parser, parser_tokval(parser) + 10 /* skip __builtin */);
1578             }
1579
1580             if (!var) {
1581                 char *correct = NULL;
1582                 size_t i;
1583
1584                 /*
1585                  * sometimes people use preprocessing predefs without enabling them
1586                  * i've done this thousands of times already myself.  Lets check for
1587                  * it in the predef table.  And diagnose it better :)
1588                  */
1589                 if (!OPTS_FLAG(FTEPP_PREDEFS) && ftepp_predef_exists(parser_tokval(parser))) {
1590                     parseerror(parser, "unexpected identifier: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
1591                     return false;
1592                 }
1593
1594                 /*
1595                  * TODO: determine the best score for the identifier: be it
1596                  * a variable, a field.
1597                  *
1598                  * We should also consider adding correction tables for
1599                  * other things as well.
1600                  */
1601                 if (OPTS_OPTION_BOOL(OPTION_CORRECTION) && strlen(parser_tokval(parser)) <= 16) {
1602                     correction_t corr;
1603                     correct_init(&corr);
1604
1605                     for (i = 0; i < vec_size(parser->correct_variables); i++) {
1606                         correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser));
1607                         if (strcmp(correct, parser_tokval(parser))) {
1608                             break;
1609                         } else  {
1610                             mem_d(correct);
1611                             correct = NULL;
1612                         }
1613                     }
1614                     correct_free(&corr);
1615
1616                     if (correct) {
1617                         parseerror(parser, "unexpected identifier: %s (did you mean %s?)", parser_tokval(parser), correct);
1618                         mem_d(correct);
1619                         return false;
1620                     }
1621                 }
1622                 parseerror(parser, "unexpected identifier: %s", parser_tokval(parser));
1623                 return false;
1624             }
1625         }
1626         else
1627         {
1628             if (ast_istype(var, ast_value)) {
1629                 ((ast_value*)var)->uses++;
1630             }
1631             else if (ast_istype(var, ast_member)) {
1632                 ast_member *mem = (ast_member*)var;
1633                 if (ast_istype(mem->owner, ast_value))
1634                     ((ast_value*)(mem->owner))->uses++;
1635             }
1636         }
1637         vec_push(sy->out, syexp(parser_ctx(parser), var));
1638         return true;
1639     }
1640     parseerror(parser, "unexpected token `%s`", parser_tokval(parser));
1641     return false;
1642 }
1643
1644 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels)
1645 {
1646     ast_expression *expr = NULL;
1647     shunt sy;
1648     size_t i;
1649     bool wantop = false;
1650     /* only warn once about an assignment in a truth value because the current code
1651      * would trigger twice on: if(a = b && ...), once for the if-truth-value, once for the && part
1652      */
1653     bool warn_truthvalue = true;
1654
1655     /* count the parens because an if starts with one, so the
1656      * end of a condition is an unmatched closing paren
1657      */
1658     int ternaries = 0;
1659
1660     memset(&sy, 0, sizeof(sy));
1661
1662     parser->lex->flags.noops = false;
1663
1664     parser_reclassify_token(parser);
1665
1666     while (true)
1667     {
1668         if (parser->tok == TOKEN_TYPENAME) {
1669             parseerror(parser, "unexpected typename `%s`", parser_tokval(parser));
1670             goto onerr;
1671         }
1672
1673         if (parser->tok == TOKEN_OPERATOR)
1674         {
1675             /* classify the operator */
1676             const oper_info *op;
1677             const oper_info *olast = NULL;
1678             size_t o;
1679             for (o = 0; o < operator_count; ++o) {
1680                 if (((!(operators[o].flags & OP_PREFIX) == !!wantop)) &&
1681                     /* !(operators[o].flags & OP_SUFFIX) && / * remove this */
1682                     !strcmp(parser_tokval(parser), operators[o].op))
1683                 {
1684                     break;
1685                 }
1686             }
1687             if (o == operator_count) {
1688                 compile_error(parser_ctx(parser), "unknown operator: %s", parser_tokval(parser));
1689                 goto onerr;
1690             }
1691             /* found an operator */
1692             op = &operators[o];
1693
1694             /* when declaring variables, a comma starts a new variable */
1695             if (op->id == opid1(',') && !vec_size(sy.paren) && stopatcomma) {
1696                 /* fixup the token */
1697                 parser->tok = ',';
1698                 break;
1699             }
1700
1701             /* a colon without a pervious question mark cannot be a ternary */
1702             if (!ternaries && op->id == opid2(':','?')) {
1703                 parser->tok = ':';
1704                 break;
1705             }
1706
1707             if (op->id == opid1(',')) {
1708                 if (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1709                     (void)!parsewarning(parser, WARN_TERNARY_PRECEDENCE, "suggesting parenthesis around ternary expression");
1710                 }
1711             }
1712
1713             if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
1714                 olast = &operators[vec_last(sy.ops).etype-1];
1715
1716 #define IsAssignOp(x) (\
1717                 (x) == opid1('=') || \
1718                 (x) == opid2('+','=') || \
1719                 (x) == opid2('-','=') || \
1720                 (x) == opid2('*','=') || \
1721                 (x) == opid2('/','=') || \
1722                 (x) == opid2('%','=') || \
1723                 (x) == opid2('&','=') || \
1724                 (x) == opid2('|','=') || \
1725                 (x) == opid3('&','~','=') \
1726                 )
1727             if (warn_truthvalue) {
1728                 if ( (olast && IsAssignOp(olast->id) && (op->id == opid2('&','&') || op->id == opid2('|','|'))) ||
1729                      (olast && IsAssignOp(op->id) && (olast->id == opid2('&','&') || olast->id == opid2('|','|'))) ||
1730                      (truthvalue && !vec_size(sy.paren) && IsAssignOp(op->id))
1731                    )
1732                 {
1733                     (void)!parsewarning(parser, WARN_PARENTHESIS, "suggesting parenthesis around assignment used as truth value");
1734                     warn_truthvalue = false;
1735                 }
1736             }
1737
1738             while (olast && (
1739                     (op->prec < olast->prec) ||
1740                     (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
1741             {
1742                 if (!parser_sy_apply_operator(parser, &sy))
1743                     goto onerr;
1744                 if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
1745                     olast = &operators[vec_last(sy.ops).etype-1];
1746                 else
1747                     olast = NULL;
1748             }
1749
1750             if (op->id == opid1('(')) {
1751                 if (wantop) {
1752                     size_t sycount = vec_size(sy.out);
1753                     /* we expected an operator, this is the function-call operator */
1754                     vec_push(sy.paren, PAREN_FUNC);
1755                     vec_push(sy.ops, syparen(parser_ctx(parser), sycount-1));
1756                     vec_push(sy.argc, 0);
1757                 } else {
1758                     vec_push(sy.paren, PAREN_EXPR);
1759                     vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1760                 }
1761                 wantop = false;
1762             } else if (op->id == opid1('[')) {
1763                 if (!wantop) {
1764                     parseerror(parser, "unexpected array subscript");
1765                     goto onerr;
1766                 }
1767                 vec_push(sy.paren, PAREN_INDEX);
1768                 /* push both the operator and the paren, this makes life easier */
1769                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1770                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1771                 wantop = false;
1772             } else if (op->id == opid2('?',':')) {
1773                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1774                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1775                 wantop = false;
1776                 ++ternaries;
1777                 vec_push(sy.paren, PAREN_TERNARY1);
1778             } else if (op->id == opid2(':','?')) {
1779                 if (!vec_size(sy.paren)) {
1780                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
1781                     goto onerr;
1782                 }
1783                 if (vec_last(sy.paren) != PAREN_TERNARY1) {
1784                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
1785                     goto onerr;
1786                 }
1787                 if (!parser_close_paren(parser, &sy))
1788                     goto onerr;
1789                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1790                 wantop = false;
1791                 --ternaries;
1792             } else {
1793                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1794                 wantop = !!(op->flags & OP_SUFFIX);
1795             }
1796         }
1797         else if (parser->tok == ')') {
1798             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1799                 if (!parser_sy_apply_operator(parser, &sy))
1800                     goto onerr;
1801             }
1802             if (!vec_size(sy.paren))
1803                 break;
1804             if (wantop) {
1805                 if (vec_last(sy.paren) == PAREN_TERNARY1) {
1806                     parseerror(parser, "mismatched parentheses (closing paren in ternary expression?)");
1807                     goto onerr;
1808                 }
1809                 if (!parser_close_paren(parser, &sy))
1810                     goto onerr;
1811             } else {
1812                 /* must be a function call without parameters */
1813                 if (vec_last(sy.paren) != PAREN_FUNC) {
1814                     parseerror(parser, "closing paren in invalid position");
1815                     goto onerr;
1816                 }
1817                 if (!parser_close_paren(parser, &sy))
1818                     goto onerr;
1819             }
1820             wantop = true;
1821         }
1822         else if (parser->tok == '(') {
1823             parseerror(parser, "internal error: '(' should be classified as operator");
1824             goto onerr;
1825         }
1826         else if (parser->tok == '[') {
1827             parseerror(parser, "internal error: '[' should be classified as operator");
1828             goto onerr;
1829         }
1830         else if (parser->tok == ']') {
1831             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1832                 if (!parser_sy_apply_operator(parser, &sy))
1833                     goto onerr;
1834             }
1835             if (!vec_size(sy.paren))
1836                 break;
1837             if (vec_last(sy.paren) != PAREN_INDEX) {
1838                 parseerror(parser, "mismatched parentheses, unexpected ']'");
1839                 goto onerr;
1840             }
1841             if (!parser_close_paren(parser, &sy))
1842                 goto onerr;
1843             wantop = true;
1844         }
1845         else if (!wantop) {
1846             if (!parse_sya_operand(parser, &sy, with_labels))
1847                 goto onerr;
1848 #if 0
1849             if (vec_size(sy.paren) && vec_last(sy.ops).isparen && vec_last(sy.paren) == PAREN_FUNC)
1850                 vec_last(sy.argc)++;
1851 #endif
1852             wantop = true;
1853         }
1854         else {
1855             /* in this case we might want to allow constant string concatenation */
1856             bool concatenated = false;
1857             if (parser->tok == TOKEN_STRINGCONST && vec_size(sy.out)) {
1858                 ast_expression *lexpr = vec_last(sy.out).out;
1859                 if (ast_istype(lexpr, ast_value)) {
1860                     ast_value *last = (ast_value*)lexpr;
1861                     if (last->isimm == true && last->cvq == CV_CONST &&
1862                         last->hasvalue && last->expression.vtype == TYPE_STRING)
1863                     {
1864                         char *newstr = NULL;
1865                         util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser));
1866                         vec_last(sy.out).out = (ast_expression*)fold_constgen_string(parser->fold, newstr, false);
1867                         mem_d(newstr);
1868                         concatenated = true;
1869                     }
1870                 }
1871             }
1872             if (!concatenated) {
1873                 parseerror(parser, "expected operator or end of statement");
1874                 goto onerr;
1875             }
1876         }
1877
1878         if (!parser_next(parser)) {
1879             goto onerr;
1880         }
1881         if (parser->tok == ';' ||
1882             ((!vec_size(sy.paren) || (vec_size(sy.paren) == 1 && vec_last(sy.paren) == PAREN_TERNARY2)) &&
1883             (parser->tok == ']' || parser->tok == ')' || parser->tok == '}')))
1884         {
1885             break;
1886         }
1887     }
1888
1889     while (vec_size(sy.ops)) {
1890         if (!parser_sy_apply_operator(parser, &sy))
1891             goto onerr;
1892     }
1893
1894     parser->lex->flags.noops = true;
1895     if (vec_size(sy.out) != 1) {
1896         parseerror(parser, "expression with not 1 but %lu output values...", (unsigned long) vec_size(sy.out));
1897         expr = NULL;
1898     } else
1899         expr = sy.out[0].out;
1900     vec_free(sy.out);
1901     vec_free(sy.ops);
1902     if (vec_size(sy.paren)) {
1903         parseerror(parser, "internal error: vec_size(sy.paren) = %lu", (unsigned long)vec_size(sy.paren));
1904         return NULL;
1905     }
1906     vec_free(sy.paren);
1907     vec_free(sy.argc);
1908     return expr;
1909
1910 onerr:
1911     parser->lex->flags.noops = true;
1912     for (i = 0; i < vec_size(sy.out); ++i) {
1913         if (sy.out[i].out)
1914             ast_unref(sy.out[i].out);
1915     }
1916     vec_free(sy.out);
1917     vec_free(sy.ops);
1918     vec_free(sy.paren);
1919     vec_free(sy.argc);
1920     return NULL;
1921 }
1922
1923 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels)
1924 {
1925     ast_expression *e = parse_expression_leave(parser, stopatcomma, false, with_labels);
1926     if (!e)
1927         return NULL;
1928     if (parser->tok != ';') {
1929         parseerror(parser, "semicolon expected after expression");
1930         ast_unref(e);
1931         return NULL;
1932     }
1933     if (!parser_next(parser)) {
1934         ast_unref(e);
1935         return NULL;
1936     }
1937     return e;
1938 }
1939
1940 static void parser_enterblock(parser_t *parser)
1941 {
1942     vec_push(parser->variables, util_htnew(PARSER_HT_SIZE));
1943     vec_push(parser->_blocklocals, vec_size(parser->_locals));
1944     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
1945     vec_push(parser->_blocktypedefs, vec_size(parser->_typedefs));
1946     vec_push(parser->_block_ctx, parser_ctx(parser));
1947
1948     /* corrector */
1949     vec_push(parser->correct_variables, correct_trie_new());
1950     vec_push(parser->correct_variables_score, NULL);
1951 }
1952
1953 static bool parser_leaveblock(parser_t *parser)
1954 {
1955     bool   rv = true;
1956     size_t locals, typedefs;
1957
1958     if (vec_size(parser->variables) <= PARSER_HT_LOCALS) {
1959         parseerror(parser, "internal error: parser_leaveblock with no block");
1960         return false;
1961     }
1962
1963     util_htdel(vec_last(parser->variables));
1964     correct_del(vec_last(parser->correct_variables), vec_last(parser->correct_variables_score));
1965
1966     vec_pop(parser->variables);
1967     vec_pop(parser->correct_variables);
1968     vec_pop(parser->correct_variables_score);
1969     if (!vec_size(parser->_blocklocals)) {
1970         parseerror(parser, "internal error: parser_leaveblock with no block (2)");
1971         return false;
1972     }
1973
1974     locals = vec_last(parser->_blocklocals);
1975     vec_pop(parser->_blocklocals);
1976     while (vec_size(parser->_locals) != locals) {
1977         ast_expression *e = vec_last(parser->_locals);
1978         ast_value      *v = (ast_value*)e;
1979         vec_pop(parser->_locals);
1980         if (ast_istype(e, ast_value) && !v->uses) {
1981             if (compile_warning(ast_ctx(v), WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name))
1982                 rv = false;
1983         }
1984     }
1985
1986     typedefs = vec_last(parser->_blocktypedefs);
1987     while (vec_size(parser->_typedefs) != typedefs) {
1988         ast_delete(vec_last(parser->_typedefs));
1989         vec_pop(parser->_typedefs);
1990     }
1991     util_htdel(vec_last(parser->typedefs));
1992     vec_pop(parser->typedefs);
1993
1994     vec_pop(parser->_block_ctx);
1995
1996     return rv;
1997 }
1998
1999 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e)
2000 {
2001     vec_push(parser->_locals, e);
2002     util_htset(vec_last(parser->variables), name, (void*)e);
2003
2004     /* corrector */
2005     correct_add (
2006          vec_last(parser->correct_variables),
2007         &vec_last(parser->correct_variables_score),
2008         name
2009     );
2010 }
2011
2012 static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e)
2013 {
2014     vec_push(parser->globals, e);
2015     util_htset(parser->htglobals, name, e);
2016
2017     /* corrector */
2018     correct_add (
2019          parser->correct_variables[0],
2020         &parser->correct_variables_score[0],
2021         name
2022     );
2023 }
2024
2025 static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
2026 {
2027     bool       ifnot = false;
2028     ast_unary *unary;
2029     ast_expression *prev;
2030
2031     if (cond->vtype == TYPE_VOID || cond->vtype >= TYPE_VARIANT) {
2032         char ty[1024];
2033         ast_type_to_string(cond, ty, sizeof(ty));
2034         compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty);
2035     }
2036
2037     if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->vtype == TYPE_STRING)
2038     {
2039         prev = cond;
2040         cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
2041         if (!cond) {
2042             ast_unref(prev);
2043             parseerror(parser, "internal error: failed to process condition");
2044             return NULL;
2045         }
2046         ifnot = !ifnot;
2047     }
2048     else if (OPTS_FLAG(CORRECT_LOGIC) && cond->vtype == TYPE_VECTOR)
2049     {
2050         /* vector types need to be cast to true booleans */
2051         ast_binary *bin = (ast_binary*)cond;
2052         if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR))
2053         {
2054             /* in perl-logic, AND and OR take care of the -fcorrect-logic */
2055             prev = cond;
2056             cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond);
2057             if (!cond) {
2058                 ast_unref(prev);
2059                 parseerror(parser, "internal error: failed to process condition");
2060                 return NULL;
2061             }
2062             ifnot = !ifnot;
2063         }
2064     }
2065
2066     unary = (ast_unary*)cond;
2067     /* ast_istype dereferences cond, should test here for safety */
2068     while (cond && ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F)
2069     {
2070         cond = unary->operand;
2071         unary->operand = NULL;
2072         ast_delete(unary);
2073         ifnot = !ifnot;
2074         unary = (ast_unary*)cond;
2075     }
2076
2077     if (!cond)
2078         parseerror(parser, "internal error: failed to process condition");
2079
2080     if (ifnot) *_ifnot = !*_ifnot;
2081     return cond;
2082 }
2083
2084 static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
2085 {
2086     ast_ifthen *ifthen;
2087     ast_expression *cond, *ontrue = NULL, *onfalse = NULL;
2088     bool ifnot = false;
2089
2090     lex_ctx_t ctx = parser_ctx(parser);
2091
2092     (void)block; /* not touching */
2093
2094     /* skip the 'if', parse an optional 'not' and check for an opening paren */
2095     if (!parser_next(parser)) {
2096         parseerror(parser, "expected condition or 'not'");
2097         return false;
2098     }
2099     if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "not")) {
2100         ifnot = true;
2101         if (!parser_next(parser)) {
2102             parseerror(parser, "expected condition in parenthesis");
2103             return false;
2104         }
2105     }
2106     if (parser->tok != '(') {
2107         parseerror(parser, "expected 'if' condition in parenthesis");
2108         return false;
2109     }
2110     /* parse into the expression */
2111     if (!parser_next(parser)) {
2112         parseerror(parser, "expected 'if' condition after opening paren");
2113         return false;
2114     }
2115     /* parse the condition */
2116     cond = parse_expression_leave(parser, false, true, false);
2117     if (!cond)
2118         return false;
2119     /* closing paren */
2120     if (parser->tok != ')') {
2121         parseerror(parser, "expected closing paren after 'if' condition");
2122         ast_unref(cond);
2123         return false;
2124     }
2125     /* parse into the 'then' branch */
2126     if (!parser_next(parser)) {
2127         parseerror(parser, "expected statement for on-true branch of 'if'");
2128         ast_unref(cond);
2129         return false;
2130     }
2131     if (!parse_statement_or_block(parser, &ontrue)) {
2132         ast_unref(cond);
2133         return false;
2134     }
2135     if (!ontrue)
2136         ontrue = (ast_expression*)ast_block_new(parser_ctx(parser));
2137     /* check for an else */
2138     if (!strcmp(parser_tokval(parser), "else")) {
2139         /* parse into the 'else' branch */
2140         if (!parser_next(parser)) {
2141             parseerror(parser, "expected on-false branch after 'else'");
2142             ast_delete(ontrue);
2143             ast_unref(cond);
2144             return false;
2145         }
2146         if (!parse_statement_or_block(parser, &onfalse)) {
2147             ast_delete(ontrue);
2148             ast_unref(cond);
2149             return false;
2150         }
2151     }
2152
2153     cond = process_condition(parser, cond, &ifnot);
2154     if (!cond) {
2155         if (ontrue)  ast_delete(ontrue);
2156         if (onfalse) ast_delete(onfalse);
2157         return false;
2158     }
2159
2160     if (ifnot)
2161         ifthen = ast_ifthen_new(ctx, cond, onfalse, ontrue);
2162     else
2163         ifthen = ast_ifthen_new(ctx, cond, ontrue, onfalse);
2164     *out = (ast_expression*)ifthen;
2165     return true;
2166 }
2167
2168 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out);
2169 static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out)
2170 {
2171     bool rv;
2172     char *label = NULL;
2173
2174     /* skip the 'while' and get the body */
2175     if (!parser_next(parser)) {
2176         if (OPTS_FLAG(LOOP_LABELS))
2177             parseerror(parser, "expected loop label or 'while' condition in parenthesis");
2178         else
2179             parseerror(parser, "expected 'while' condition in parenthesis");
2180         return false;
2181     }
2182
2183     if (parser->tok == ':') {
2184         if (!OPTS_FLAG(LOOP_LABELS))
2185             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2186         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2187             parseerror(parser, "expected loop label");
2188             return false;
2189         }
2190         label = util_strdup(parser_tokval(parser));
2191         if (!parser_next(parser)) {
2192             mem_d(label);
2193             parseerror(parser, "expected 'while' condition in parenthesis");
2194             return false;
2195         }
2196     }
2197
2198     if (parser->tok != '(') {
2199         parseerror(parser, "expected 'while' condition in parenthesis");
2200         return false;
2201     }
2202
2203     vec_push(parser->breaks, label);
2204     vec_push(parser->continues, label);
2205
2206     rv = parse_while_go(parser, block, out);
2207     if (label)
2208         mem_d(label);
2209     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2210         parseerror(parser, "internal error: label stack corrupted");
2211         rv = false;
2212         ast_delete(*out);
2213         *out = NULL;
2214     }
2215     else {
2216         vec_pop(parser->breaks);
2217         vec_pop(parser->continues);
2218     }
2219     return rv;
2220 }
2221
2222 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out)
2223 {
2224     ast_loop *aloop;
2225     ast_expression *cond, *ontrue;
2226
2227     bool ifnot = false;
2228
2229     lex_ctx_t ctx = parser_ctx(parser);
2230
2231     (void)block; /* not touching */
2232
2233     /* parse into the expression */
2234     if (!parser_next(parser)) {
2235         parseerror(parser, "expected 'while' condition after opening paren");
2236         return false;
2237     }
2238     /* parse the condition */
2239     cond = parse_expression_leave(parser, false, true, false);
2240     if (!cond)
2241         return false;
2242     /* closing paren */
2243     if (parser->tok != ')') {
2244         parseerror(parser, "expected closing paren after 'while' condition");
2245         ast_unref(cond);
2246         return false;
2247     }
2248     /* parse into the 'then' branch */
2249     if (!parser_next(parser)) {
2250         parseerror(parser, "expected while-loop body");
2251         ast_unref(cond);
2252         return false;
2253     }
2254     if (!parse_statement_or_block(parser, &ontrue)) {
2255         ast_unref(cond);
2256         return false;
2257     }
2258
2259     cond = process_condition(parser, cond, &ifnot);
2260     if (!cond) {
2261         ast_unref(ontrue);
2262         return false;
2263     }
2264     aloop = ast_loop_new(ctx, NULL, cond, ifnot, NULL, false, NULL, ontrue);
2265     *out = (ast_expression*)aloop;
2266     return true;
2267 }
2268
2269 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out);
2270 static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **out)
2271 {
2272     bool rv;
2273     char *label = NULL;
2274
2275     /* skip the 'do' and get the body */
2276     if (!parser_next(parser)) {
2277         if (OPTS_FLAG(LOOP_LABELS))
2278             parseerror(parser, "expected loop label or body");
2279         else
2280             parseerror(parser, "expected loop body");
2281         return false;
2282     }
2283
2284     if (parser->tok == ':') {
2285         if (!OPTS_FLAG(LOOP_LABELS))
2286             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2287         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2288             parseerror(parser, "expected loop label");
2289             return false;
2290         }
2291         label = util_strdup(parser_tokval(parser));
2292         if (!parser_next(parser)) {
2293             mem_d(label);
2294             parseerror(parser, "expected loop body");
2295             return false;
2296         }
2297     }
2298
2299     vec_push(parser->breaks, label);
2300     vec_push(parser->continues, label);
2301
2302     rv = parse_dowhile_go(parser, block, out);
2303     if (label)
2304         mem_d(label);
2305     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2306         parseerror(parser, "internal error: label stack corrupted");
2307         rv = false;
2308         /*
2309          * Test for NULL otherwise ast_delete dereferences null pointer
2310          * and boom.
2311          */
2312         if (*out)
2313             ast_delete(*out);
2314         *out = NULL;
2315     }
2316     else {
2317         vec_pop(parser->breaks);
2318         vec_pop(parser->continues);
2319     }
2320     return rv;
2321 }
2322
2323 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out)
2324 {
2325     ast_loop *aloop;
2326     ast_expression *cond, *ontrue;
2327
2328     bool ifnot = false;
2329
2330     lex_ctx_t ctx = parser_ctx(parser);
2331
2332     (void)block; /* not touching */
2333
2334     if (!parse_statement_or_block(parser, &ontrue))
2335         return false;
2336
2337     /* expect the "while" */
2338     if (parser->tok != TOKEN_KEYWORD ||
2339         strcmp(parser_tokval(parser), "while"))
2340     {
2341         parseerror(parser, "expected 'while' and condition");
2342         ast_delete(ontrue);
2343         return false;
2344     }
2345
2346     /* skip the 'while' and check for opening paren */
2347     if (!parser_next(parser) || parser->tok != '(') {
2348         parseerror(parser, "expected 'while' condition in parenthesis");
2349         ast_delete(ontrue);
2350         return false;
2351     }
2352     /* parse into the expression */
2353     if (!parser_next(parser)) {
2354         parseerror(parser, "expected 'while' condition after opening paren");
2355         ast_delete(ontrue);
2356         return false;
2357     }
2358     /* parse the condition */
2359     cond = parse_expression_leave(parser, false, true, false);
2360     if (!cond)
2361         return false;
2362     /* closing paren */
2363     if (parser->tok != ')') {
2364         parseerror(parser, "expected closing paren after 'while' condition");
2365         ast_delete(ontrue);
2366         ast_unref(cond);
2367         return false;
2368     }
2369     /* parse on */
2370     if (!parser_next(parser) || parser->tok != ';') {
2371         parseerror(parser, "expected semicolon after condition");
2372         ast_delete(ontrue);
2373         ast_unref(cond);
2374         return false;
2375     }
2376
2377     if (!parser_next(parser)) {
2378         parseerror(parser, "parse error");
2379         ast_delete(ontrue);
2380         ast_unref(cond);
2381         return false;
2382     }
2383
2384     cond = process_condition(parser, cond, &ifnot);
2385     if (!cond) {
2386         ast_delete(ontrue);
2387         return false;
2388     }
2389     aloop = ast_loop_new(ctx, NULL, NULL, false, cond, ifnot, NULL, ontrue);
2390     *out = (ast_expression*)aloop;
2391     return true;
2392 }
2393
2394 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out);
2395 static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
2396 {
2397     bool rv;
2398     char *label = NULL;
2399
2400     /* skip the 'for' and check for opening paren */
2401     if (!parser_next(parser)) {
2402         if (OPTS_FLAG(LOOP_LABELS))
2403             parseerror(parser, "expected loop label or 'for' expressions in parenthesis");
2404         else
2405             parseerror(parser, "expected 'for' expressions in parenthesis");
2406         return false;
2407     }
2408
2409     if (parser->tok == ':') {
2410         if (!OPTS_FLAG(LOOP_LABELS))
2411             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2412         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2413             parseerror(parser, "expected loop label");
2414             return false;
2415         }
2416         label = util_strdup(parser_tokval(parser));
2417         if (!parser_next(parser)) {
2418             mem_d(label);
2419             parseerror(parser, "expected 'for' expressions in parenthesis");
2420             return false;
2421         }
2422     }
2423
2424     if (parser->tok != '(') {
2425         parseerror(parser, "expected 'for' expressions in parenthesis");
2426         return false;
2427     }
2428
2429     vec_push(parser->breaks, label);
2430     vec_push(parser->continues, label);
2431
2432     rv = parse_for_go(parser, block, out);
2433     if (label)
2434         mem_d(label);
2435     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2436         parseerror(parser, "internal error: label stack corrupted");
2437         rv = false;
2438         ast_delete(*out);
2439         *out = NULL;
2440     }
2441     else {
2442         vec_pop(parser->breaks);
2443         vec_pop(parser->continues);
2444     }
2445     return rv;
2446 }
2447 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out)
2448 {
2449     ast_loop       *aloop;
2450     ast_expression *initexpr, *cond, *increment, *ontrue;
2451     ast_value      *typevar;
2452
2453     bool ifnot  = false;
2454
2455     lex_ctx_t ctx = parser_ctx(parser);
2456
2457     parser_enterblock(parser);
2458
2459     initexpr  = NULL;
2460     cond      = NULL;
2461     increment = NULL;
2462     ontrue    = NULL;
2463
2464     /* parse into the expression */
2465     if (!parser_next(parser)) {
2466         parseerror(parser, "expected 'for' initializer after opening paren");
2467         goto onerr;
2468     }
2469
2470     typevar = NULL;
2471     if (parser->tok == TOKEN_IDENT)
2472         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
2473
2474     if (typevar || parser->tok == TOKEN_TYPENAME) {
2475 #if 0
2476         if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
2477             if (parsewarning(parser, WARN_EXTENSIONS,
2478                              "current standard does not allow variable declarations in for-loop initializers"))
2479                 goto onerr;
2480         }
2481 #endif
2482         if (!parse_variable(parser, block, true, CV_VAR, typevar, false, false, 0, NULL))
2483             goto onerr;
2484     }
2485     else if (parser->tok != ';')
2486     {
2487         initexpr = parse_expression_leave(parser, false, false, false);
2488         if (!initexpr)
2489             goto onerr;
2490     }
2491
2492     /* move on to condition */
2493     if (parser->tok != ';') {
2494         parseerror(parser, "expected semicolon after for-loop initializer");
2495         goto onerr;
2496     }
2497     if (!parser_next(parser)) {
2498         parseerror(parser, "expected for-loop condition");
2499         goto onerr;
2500     }
2501
2502     /* parse the condition */
2503     if (parser->tok != ';') {
2504         cond = parse_expression_leave(parser, false, true, false);
2505         if (!cond)
2506             goto onerr;
2507     }
2508
2509     /* move on to incrementor */
2510     if (parser->tok != ';') {
2511         parseerror(parser, "expected semicolon after for-loop initializer");
2512         goto onerr;
2513     }
2514     if (!parser_next(parser)) {
2515         parseerror(parser, "expected for-loop condition");
2516         goto onerr;
2517     }
2518
2519     /* parse the incrementor */
2520     if (parser->tok != ')') {
2521         lex_ctx_t condctx = parser_ctx(parser);
2522         increment = parse_expression_leave(parser, false, false, false);
2523         if (!increment)
2524             goto onerr;
2525         if (!ast_side_effects(increment)) {
2526             if (compile_warning(condctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
2527                 goto onerr;
2528         }
2529     }
2530
2531     /* closing paren */
2532     if (parser->tok != ')') {
2533         parseerror(parser, "expected closing paren after 'for-loop' incrementor");
2534         goto onerr;
2535     }
2536     /* parse into the 'then' branch */
2537     if (!parser_next(parser)) {
2538         parseerror(parser, "expected for-loop body");
2539         goto onerr;
2540     }
2541     if (!parse_statement_or_block(parser, &ontrue))
2542         goto onerr;
2543
2544     if (cond) {
2545         cond = process_condition(parser, cond, &ifnot);
2546         if (!cond)
2547             goto onerr;
2548     }
2549     aloop = ast_loop_new(ctx, initexpr, cond, ifnot, NULL, false, increment, ontrue);
2550     *out = (ast_expression*)aloop;
2551
2552     if (!parser_leaveblock(parser)) {
2553         ast_delete(aloop);
2554         return false;
2555     }
2556     return true;
2557 onerr:
2558     if (initexpr)  ast_unref(initexpr);
2559     if (cond)      ast_unref(cond);
2560     if (increment) ast_unref(increment);
2561     (void)!parser_leaveblock(parser);
2562     return false;
2563 }
2564
2565 static bool parse_return(parser_t *parser, ast_block *block, ast_expression **out)
2566 {
2567     ast_expression *exp      = NULL;
2568     ast_expression *var      = NULL;
2569     ast_return     *ret      = NULL;
2570     ast_value      *retval   = parser->function->return_value;
2571     ast_value      *expected = parser->function->vtype;
2572
2573     lex_ctx_t ctx = parser_ctx(parser);
2574
2575     (void)block; /* not touching */
2576
2577     if (!parser_next(parser)) {
2578         parseerror(parser, "expected return expression");
2579         return false;
2580     }
2581
2582     /* return assignments */
2583     if (parser->tok == '=') {
2584         if (!OPTS_FLAG(RETURN_ASSIGNMENTS)) {
2585             parseerror(parser, "return assignments not activated, try using -freturn-assigments");
2586             return false;
2587         }
2588
2589         if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) {
2590             char ty1[1024];
2591             ast_type_to_string(expected->expression.next, ty1, sizeof(ty1));
2592             parseerror(parser, "invalid return type: `%s'", ty1);
2593             return false;
2594         }
2595
2596         if (!parser_next(parser)) {
2597             parseerror(parser, "expected return assignment expression");
2598             return false;
2599         }
2600
2601         if (!(exp = parse_expression_leave(parser, false, false, false)))
2602             return false;
2603
2604         /* prepare the return value */
2605         if (!retval) {
2606             retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID);
2607             ast_type_adopt(retval, expected->expression.next);
2608             parser->function->return_value = retval;
2609         }
2610
2611         if (!ast_compare_type(exp, (ast_expression*)retval)) {
2612             char ty1[1024], ty2[1024];
2613             ast_type_to_string(exp, ty1, sizeof(ty1));
2614             ast_type_to_string(&retval->expression, ty2, sizeof(ty2));
2615             parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2);
2616         }
2617
2618         /* store to 'return' local variable */
2619         var = (ast_expression*)ast_store_new(
2620             ctx,
2621             type_store_instr[expected->expression.next->vtype],
2622             (ast_expression*)retval, exp);
2623
2624         if (!var) {
2625             ast_unref(exp);
2626             return false;
2627         }
2628
2629         if (parser->tok != ';')
2630             parseerror(parser, "missing semicolon after return assignment");
2631         else if (!parser_next(parser))
2632             parseerror(parser, "parse error after return assignment");
2633
2634         *out = var;
2635         return true;
2636     }
2637
2638     if (parser->tok != ';') {
2639         exp = parse_expression(parser, false, false);
2640         if (!exp)
2641             return false;
2642
2643         if (exp->vtype != TYPE_NIL &&
2644             exp->vtype != ((ast_expression*)expected)->next->vtype)
2645         {
2646             parseerror(parser, "return with invalid expression");
2647         }
2648
2649         ret = ast_return_new(ctx, exp);
2650         if (!ret) {
2651             ast_unref(exp);
2652             return false;
2653         }
2654     } else {
2655         if (!parser_next(parser))
2656             parseerror(parser, "parse error");
2657
2658         if (!retval && expected->expression.next->vtype != TYPE_VOID)
2659         {
2660             (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
2661         }
2662         ret = ast_return_new(ctx, (ast_expression*)retval);
2663     }
2664     *out = (ast_expression*)ret;
2665     return true;
2666 }
2667
2668 static bool parse_break_continue(parser_t *parser, ast_block *block, ast_expression **out, bool is_continue)
2669 {
2670     size_t       i;
2671     unsigned int levels = 0;
2672     lex_ctx_t      ctx = parser_ctx(parser);
2673     const char **loops = (is_continue ? parser->continues : parser->breaks);
2674
2675     (void)block; /* not touching */
2676     if (!parser_next(parser)) {
2677         parseerror(parser, "expected semicolon or loop label");
2678         return false;
2679     }
2680
2681     if (!vec_size(loops)) {
2682         if (is_continue)
2683             parseerror(parser, "`continue` can only be used inside loops");
2684         else
2685             parseerror(parser, "`break` can only be used inside loops or switches");
2686     }
2687
2688     if (parser->tok == TOKEN_IDENT) {
2689         if (!OPTS_FLAG(LOOP_LABELS))
2690             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2691         i = vec_size(loops);
2692         while (i--) {
2693             if (loops[i] && !strcmp(loops[i], parser_tokval(parser)))
2694                 break;
2695             if (!i) {
2696                 parseerror(parser, "no such loop to %s: `%s`",
2697                            (is_continue ? "continue" : "break out of"),
2698                            parser_tokval(parser));
2699                 return false;
2700             }
2701             ++levels;
2702         }
2703         if (!parser_next(parser)) {
2704             parseerror(parser, "expected semicolon");
2705             return false;
2706         }
2707     }
2708
2709     if (parser->tok != ';') {
2710         parseerror(parser, "expected semicolon");
2711         return false;
2712     }
2713
2714     if (!parser_next(parser))
2715         parseerror(parser, "parse error");
2716
2717     *out = (ast_expression*)ast_breakcont_new(ctx, is_continue, levels);
2718     return true;
2719 }
2720
2721 /* returns true when it was a variable qualifier, false otherwise!
2722  * on error, cvq is set to CV_WRONG
2723  */
2724 static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *noref, bool *is_static, uint32_t *_flags, char **message)
2725 {
2726     bool had_const    = false;
2727     bool had_var      = false;
2728     bool had_noref    = false;
2729     bool had_attrib   = false;
2730     bool had_static   = false;
2731     uint32_t flags    = 0;
2732
2733     *cvq = CV_NONE;
2734     for (;;) {
2735         if (parser->tok == TOKEN_ATTRIBUTE_OPEN) {
2736             had_attrib = true;
2737             /* parse an attribute */
2738             if (!parser_next(parser)) {
2739                 parseerror(parser, "expected attribute after `[[`");
2740                 *cvq = CV_WRONG;
2741                 return false;
2742             }
2743             if (!strcmp(parser_tokval(parser), "noreturn")) {
2744                 flags |= AST_FLAG_NORETURN;
2745                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2746                     parseerror(parser, "`noreturn` attribute has no parameters, expected `]]`");
2747                     *cvq = CV_WRONG;
2748                     return false;
2749                 }
2750             }
2751             else if (!strcmp(parser_tokval(parser), "noref")) {
2752                 had_noref = true;
2753                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2754                     parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
2755                     *cvq = CV_WRONG;
2756                     return false;
2757                 }
2758             }
2759             else if (!strcmp(parser_tokval(parser), "inline")) {
2760                 flags |= AST_FLAG_INLINE;
2761                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2762                     parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
2763                     *cvq = CV_WRONG;
2764                     return false;
2765                 }
2766             }
2767             else if (!strcmp(parser_tokval(parser), "alias") && !(flags & AST_FLAG_ALIAS)) {
2768                 flags   |= AST_FLAG_ALIAS;
2769                 *message = NULL;
2770
2771                 if (!parser_next(parser)) {
2772                     parseerror(parser, "parse error in attribute");
2773                     goto argerr;
2774                 }
2775
2776                 if (parser->tok == '(') {
2777                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2778                         parseerror(parser, "`alias` attribute missing parameter");
2779                         goto argerr;
2780                     }
2781
2782                     *message = util_strdup(parser_tokval(parser));
2783
2784                     if (!parser_next(parser)) {
2785                         parseerror(parser, "parse error in attribute");
2786                         goto argerr;
2787                     }
2788
2789                     if (parser->tok != ')') {
2790                         parseerror(parser, "`alias` attribute expected `)` after parameter");
2791                         goto argerr;
2792                     }
2793
2794                     if (!parser_next(parser)) {
2795                         parseerror(parser, "parse error in attribute");
2796                         goto argerr;
2797                     }
2798                 }
2799
2800                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2801                     parseerror(parser, "`alias` attribute expected `]]`");
2802                     goto argerr;
2803                 }
2804             }
2805             else if (!strcmp(parser_tokval(parser), "deprecated") && !(flags & AST_FLAG_DEPRECATED)) {
2806                 flags   |= AST_FLAG_DEPRECATED;
2807                 *message = NULL;
2808
2809                 if (!parser_next(parser)) {
2810                     parseerror(parser, "parse error in attribute");
2811                     goto argerr;
2812                 }
2813
2814                 if (parser->tok == '(') {
2815                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2816                         parseerror(parser, "`deprecated` attribute missing parameter");
2817                         goto argerr;
2818                     }
2819
2820                     *message = util_strdup(parser_tokval(parser));
2821
2822                     if (!parser_next(parser)) {
2823                         parseerror(parser, "parse error in attribute");
2824                         goto argerr;
2825                     }
2826
2827                     if(parser->tok != ')') {
2828                         parseerror(parser, "`deprecated` attribute expected `)` after parameter");
2829                         goto argerr;
2830                     }
2831
2832                     if (!parser_next(parser)) {
2833                         parseerror(parser, "parse error in attribute");
2834                         goto argerr;
2835                     }
2836                 }
2837                 /* no message */
2838                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2839                     parseerror(parser, "`deprecated` attribute expected `]]`");
2840
2841                     argerr: /* ugly */
2842                     if (*message) mem_d(*message);
2843                     *message = NULL;
2844                     *cvq     = CV_WRONG;
2845                     return false;
2846                 }
2847             }
2848             else
2849             {
2850                 /* Skip tokens until we hit a ]] */
2851                 (void)!parsewarning(parser, WARN_UNKNOWN_ATTRIBUTE, "unknown attribute starting with `%s`", parser_tokval(parser));
2852                 while (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2853                     if (!parser_next(parser)) {
2854                         parseerror(parser, "error inside attribute");
2855                         *cvq = CV_WRONG;
2856                         return false;
2857                     }
2858                 }
2859             }
2860         }
2861         else if (with_local && !strcmp(parser_tokval(parser), "static"))
2862             had_static = true;
2863         else if (!strcmp(parser_tokval(parser), "const"))
2864             had_const = true;
2865         else if (!strcmp(parser_tokval(parser), "var"))
2866             had_var = true;
2867         else if (with_local && !strcmp(parser_tokval(parser), "local"))
2868             had_var = true;
2869         else if (!strcmp(parser_tokval(parser), "noref"))
2870             had_noref = true;
2871         else if (!had_const && !had_var && !had_noref && !had_attrib && !had_static && !flags) {
2872             return false;
2873         }
2874         else
2875             break;
2876         if (!parser_next(parser))
2877             goto onerr;
2878     }
2879     if (had_const)
2880         *cvq = CV_CONST;
2881     else if (had_var)
2882         *cvq = CV_VAR;
2883     else
2884         *cvq = CV_NONE;
2885     *noref     = had_noref;
2886     *is_static = had_static;
2887     *_flags    = flags;
2888     return true;
2889 onerr:
2890     parseerror(parser, "parse error after variable qualifier");
2891     *cvq = CV_WRONG;
2892     return true;
2893 }
2894
2895 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out);
2896 static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **out)
2897 {
2898     bool rv;
2899     char *label = NULL;
2900
2901     /* skip the 'while' and get the body */
2902     if (!parser_next(parser)) {
2903         if (OPTS_FLAG(LOOP_LABELS))
2904             parseerror(parser, "expected loop label or 'switch' operand in parenthesis");
2905         else
2906             parseerror(parser, "expected 'switch' operand in parenthesis");
2907         return false;
2908     }
2909
2910     if (parser->tok == ':') {
2911         if (!OPTS_FLAG(LOOP_LABELS))
2912             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2913         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2914             parseerror(parser, "expected loop label");
2915             return false;
2916         }
2917         label = util_strdup(parser_tokval(parser));
2918         if (!parser_next(parser)) {
2919             mem_d(label);
2920             parseerror(parser, "expected 'switch' operand in parenthesis");
2921             return false;
2922         }
2923     }
2924
2925     if (parser->tok != '(') {
2926         parseerror(parser, "expected 'switch' operand in parenthesis");
2927         return false;
2928     }
2929
2930     vec_push(parser->breaks, label);
2931
2932     rv = parse_switch_go(parser, block, out);
2933     if (label)
2934         mem_d(label);
2935     if (vec_last(parser->breaks) != label) {
2936         parseerror(parser, "internal error: label stack corrupted");
2937         rv = false;
2938         ast_delete(*out);
2939         *out = NULL;
2940     }
2941     else {
2942         vec_pop(parser->breaks);
2943     }
2944     return rv;
2945 }
2946
2947 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out)
2948 {
2949     ast_expression *operand;
2950     ast_value      *opval;
2951     ast_value      *typevar;
2952     ast_switch     *switchnode;
2953     ast_switch_case swcase;
2954
2955     int  cvq;
2956     bool noref, is_static;
2957     uint32_t qflags = 0;
2958
2959     lex_ctx_t ctx = parser_ctx(parser);
2960
2961     (void)block; /* not touching */
2962     (void)opval;
2963
2964     /* parse into the expression */
2965     if (!parser_next(parser)) {
2966         parseerror(parser, "expected switch operand");
2967         return false;
2968     }
2969     /* parse the operand */
2970     operand = parse_expression_leave(parser, false, false, false);
2971     if (!operand)
2972         return false;
2973
2974     switchnode = ast_switch_new(ctx, operand);
2975
2976     /* closing paren */
2977     if (parser->tok != ')') {
2978         ast_delete(switchnode);
2979         parseerror(parser, "expected closing paren after 'switch' operand");
2980         return false;
2981     }
2982
2983     /* parse over the opening paren */
2984     if (!parser_next(parser) || parser->tok != '{') {
2985         ast_delete(switchnode);
2986         parseerror(parser, "expected list of cases");
2987         return false;
2988     }
2989
2990     if (!parser_next(parser)) {
2991         ast_delete(switchnode);
2992         parseerror(parser, "expected 'case' or 'default'");
2993         return false;
2994     }
2995
2996     /* new block; allow some variables to be declared here */
2997     parser_enterblock(parser);
2998     while (true) {
2999         typevar = NULL;
3000         if (parser->tok == TOKEN_IDENT)
3001             typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
3002         if (typevar || parser->tok == TOKEN_TYPENAME) {
3003             if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL)) {
3004                 ast_delete(switchnode);
3005                 return false;
3006             }
3007             continue;
3008         }
3009         if (parse_qualifiers(parser, true, &cvq, &noref, &is_static, &qflags, NULL))
3010         {
3011             if (cvq == CV_WRONG) {
3012                 ast_delete(switchnode);
3013                 return false;
3014             }
3015             if (!parse_variable(parser, block, false, cvq, NULL, noref, is_static, qflags, NULL)) {
3016                 ast_delete(switchnode);
3017                 return false;
3018             }
3019             continue;
3020         }
3021         break;
3022     }
3023
3024     /* case list! */
3025     while (parser->tok != '}') {
3026         ast_block *caseblock;
3027
3028         if (!strcmp(parser_tokval(parser), "case")) {
3029             if (!parser_next(parser)) {
3030                 ast_delete(switchnode);
3031                 parseerror(parser, "expected expression for case");
3032                 return false;
3033             }
3034             swcase.value = parse_expression_leave(parser, false, false, false);
3035             if (!swcase.value) {
3036                 ast_delete(switchnode);
3037                 parseerror(parser, "expected expression for case");
3038                 return false;
3039             }
3040             if (!OPTS_FLAG(RELAXED_SWITCH)) {
3041                 if (!ast_istype(swcase.value, ast_value)) { /* || ((ast_value*)swcase.value)->cvq != CV_CONST) { */
3042                     parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch");
3043                     ast_unref(operand);
3044                     return false;
3045                 }
3046             }
3047         }
3048         else if (!strcmp(parser_tokval(parser), "default")) {
3049             swcase.value = NULL;
3050             if (!parser_next(parser)) {
3051                 ast_delete(switchnode);
3052                 parseerror(parser, "expected colon");
3053                 return false;
3054             }
3055         }
3056         else {
3057             ast_delete(switchnode);
3058             parseerror(parser, "expected 'case' or 'default'");
3059             return false;
3060         }
3061
3062         /* Now the colon and body */
3063         if (parser->tok != ':') {
3064             if (swcase.value) ast_unref(swcase.value);
3065             ast_delete(switchnode);
3066             parseerror(parser, "expected colon");
3067             return false;
3068         }
3069
3070         if (!parser_next(parser)) {
3071             if (swcase.value) ast_unref(swcase.value);
3072             ast_delete(switchnode);
3073             parseerror(parser, "expected statements or case");
3074             return false;
3075         }
3076         caseblock = ast_block_new(parser_ctx(parser));
3077         if (!caseblock) {
3078             if (swcase.value) ast_unref(swcase.value);
3079             ast_delete(switchnode);
3080             return false;
3081         }
3082         swcase.code = (ast_expression*)caseblock;
3083         vec_push(switchnode->cases, swcase);
3084         while (true) {
3085             ast_expression *expr;
3086             if (parser->tok == '}')
3087                 break;
3088             if (parser->tok == TOKEN_KEYWORD) {
3089                 if (!strcmp(parser_tokval(parser), "case") ||
3090                     !strcmp(parser_tokval(parser), "default"))
3091                 {
3092                     break;
3093                 }
3094             }
3095             if (!parse_statement(parser, caseblock, &expr, true)) {
3096                 ast_delete(switchnode);
3097                 return false;
3098             }
3099             if (!expr)
3100                 continue;
3101             if (!ast_block_add_expr(caseblock, expr)) {
3102                 ast_delete(switchnode);
3103                 return false;
3104             }
3105         }
3106     }
3107
3108     parser_leaveblock(parser);
3109
3110     /* closing paren */
3111     if (parser->tok != '}') {
3112         ast_delete(switchnode);
3113         parseerror(parser, "expected closing paren of case list");
3114         return false;
3115     }
3116     if (!parser_next(parser)) {
3117         ast_delete(switchnode);
3118         parseerror(parser, "parse error after switch");
3119         return false;
3120     }
3121     *out = (ast_expression*)switchnode;
3122     return true;
3123 }
3124
3125 /* parse computed goto sides */
3126 static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **side) {
3127     ast_expression *on_true;
3128     ast_expression *on_false;
3129     ast_expression *cond;
3130
3131     if (!*side)
3132         return NULL;
3133
3134     if (ast_istype(*side, ast_ternary)) {
3135         ast_ternary *tern = (ast_ternary*)*side;
3136         on_true  = parse_goto_computed(parser, &tern->on_true);
3137         on_false = parse_goto_computed(parser, &tern->on_false);
3138
3139         if (!on_true || !on_false) {
3140             parseerror(parser, "expected label or expression in ternary");
3141             if (on_true) ast_unref(on_true);
3142             if (on_false) ast_unref(on_false);
3143             return NULL;
3144         }
3145
3146         cond = tern->cond;
3147         tern->cond = NULL;
3148         ast_delete(tern);
3149         *side = NULL;
3150         return (ast_expression*)ast_ifthen_new(parser_ctx(parser), cond, on_true, on_false);
3151     } else if (ast_istype(*side, ast_label)) {
3152         ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->name);
3153         ast_goto_set_label(gt, ((ast_label*)*side));
3154         *side = NULL;
3155         return (ast_expression*)gt;
3156     }
3157     return NULL;
3158 }
3159
3160 static bool parse_goto(parser_t *parser, ast_expression **out)
3161 {
3162     ast_goto       *gt = NULL;
3163     ast_expression *lbl;
3164
3165     if (!parser_next(parser))
3166         return false;
3167
3168     if (parser->tok != TOKEN_IDENT) {
3169         ast_expression *expression;
3170
3171         /* could be an expression i.e computed goto :-) */
3172         if (parser->tok != '(') {
3173             parseerror(parser, "expected label name after `goto`");
3174             return false;
3175         }
3176
3177         /* failed to parse expression for goto */
3178         if (!(expression = parse_expression(parser, false, true)) ||
3179             !(*out = parse_goto_computed(parser, &expression))) {
3180             parseerror(parser, "invalid goto expression");
3181             if(expression)
3182                 ast_unref(expression);
3183             return false;
3184         }
3185
3186         return true;
3187     }
3188
3189     /* not computed goto */
3190     gt = ast_goto_new(parser_ctx(parser), parser_tokval(parser));
3191     lbl = parser_find_label(parser, gt->name);
3192     if (lbl) {
3193         if (!ast_istype(lbl, ast_label)) {
3194             parseerror(parser, "internal error: label is not an ast_label");
3195             ast_delete(gt);
3196             return false;
3197         }
3198         ast_goto_set_label(gt, (ast_label*)lbl);
3199     }
3200     else
3201         vec_push(parser->gotos, gt);
3202
3203     if (!parser_next(parser) || parser->tok != ';') {
3204         parseerror(parser, "semicolon expected after goto label");
3205         return false;
3206     }
3207     if (!parser_next(parser)) {
3208         parseerror(parser, "parse error after goto");
3209         return false;
3210     }
3211
3212     *out = (ast_expression*)gt;
3213     return true;
3214 }
3215
3216 static bool parse_skipwhite(parser_t *parser)
3217 {
3218     do {
3219         if (!parser_next(parser))
3220             return false;
3221     } while (parser->tok == TOKEN_WHITE && parser->tok < TOKEN_ERROR);
3222     return parser->tok < TOKEN_ERROR;
3223 }
3224
3225 static bool parse_eol(parser_t *parser)
3226 {
3227     if (!parse_skipwhite(parser))
3228         return false;
3229     return parser->tok == TOKEN_EOL;
3230 }
3231
3232 static bool parse_pragma_do(parser_t *parser)
3233 {
3234     if (!parser_next(parser) ||
3235         parser->tok != TOKEN_IDENT ||
3236         strcmp(parser_tokval(parser), "pragma"))
3237     {
3238         parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
3239         return false;
3240     }
3241     if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
3242         parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
3243         return false;
3244     }
3245
3246     if (!strcmp(parser_tokval(parser), "noref")) {
3247         if (!parse_skipwhite(parser) || parser->tok != TOKEN_INTCONST) {
3248             parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
3249             return false;
3250         }
3251         parser->noref = !!parser_token(parser)->constval.i;
3252         if (!parse_eol(parser)) {
3253             parseerror(parser, "parse error after `noref` pragma");
3254             return false;
3255         }
3256     }
3257     else
3258     {
3259         (void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
3260         return false;
3261     }
3262
3263     return true;
3264 }
3265
3266 static bool parse_pragma(parser_t *parser)
3267 {
3268     bool rv;
3269     parser->lex->flags.preprocessing = true;
3270     parser->lex->flags.mergelines = true;
3271     rv = parse_pragma_do(parser);
3272     if (parser->tok != TOKEN_EOL) {
3273         parseerror(parser, "junk after pragma");
3274         rv = false;
3275     }
3276     parser->lex->flags.preprocessing = false;
3277     parser->lex->flags.mergelines = false;
3278     if (!parser_next(parser)) {
3279         parseerror(parser, "parse error after pragma");
3280         rv = false;
3281     }
3282     return rv;
3283 }
3284
3285 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
3286 {
3287     bool       noref, is_static;
3288     int        cvq     = CV_NONE;
3289     uint32_t   qflags  = 0;
3290     ast_value *typevar = NULL;
3291     char      *vstring = NULL;
3292
3293     *out = NULL;
3294
3295     if (parser->tok == TOKEN_IDENT)
3296         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
3297
3298     if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
3299     {
3300         /* local variable */
3301         if (!block) {
3302             parseerror(parser, "cannot declare a variable from here");
3303             return false;
3304         }
3305         if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3306             if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
3307                 return false;
3308         }
3309         if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL))
3310             return false;
3311         return true;
3312     }
3313     else if (parse_qualifiers(parser, !!block, &cvq, &noref, &is_static, &qflags, &vstring))
3314     {
3315         if (cvq == CV_WRONG)
3316             return false;
3317         return parse_variable(parser, block, true, cvq, NULL, noref, is_static, qflags, vstring);
3318     }
3319     else if (parser->tok == TOKEN_KEYWORD)
3320     {
3321         if (!strcmp(parser_tokval(parser), "__builtin_debug_printtype"))
3322         {
3323             char ty[1024];
3324             ast_value *tdef;
3325
3326             if (!parser_next(parser)) {
3327                 parseerror(parser, "parse error after __builtin_debug_printtype");
3328                 return false;
3329             }
3330
3331             if (parser->tok == TOKEN_IDENT && (tdef = parser_find_typedef(parser, parser_tokval(parser), 0)))
3332             {
3333                 ast_type_to_string((ast_expression*)tdef, ty, sizeof(ty));
3334                 con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->name, ty);
3335                 if (!parser_next(parser)) {
3336                     parseerror(parser, "parse error after __builtin_debug_printtype typename argument");
3337                     return false;
3338                 }
3339             }
3340             else
3341             {
3342                 if (!parse_statement(parser, block, out, allow_cases))
3343                     return false;
3344                 if (!*out)
3345                     con_out("__builtin_debug_printtype: got no output node\n");
3346                 else
3347                 {
3348                     ast_type_to_string(*out, ty, sizeof(ty));
3349                     con_out("__builtin_debug_printtype: `%s`\n", ty);
3350                 }
3351             }
3352             return true;
3353         }
3354         else if (!strcmp(parser_tokval(parser), "return"))
3355         {
3356             return parse_return(parser, block, out);
3357         }
3358         else if (!strcmp(parser_tokval(parser), "if"))
3359         {
3360             return parse_if(parser, block, out);
3361         }
3362         else if (!strcmp(parser_tokval(parser), "while"))
3363         {
3364             return parse_while(parser, block, out);
3365         }
3366         else if (!strcmp(parser_tokval(parser), "do"))
3367         {
3368             return parse_dowhile(parser, block, out);
3369         }
3370         else if (!strcmp(parser_tokval(parser), "for"))
3371         {
3372             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3373                 if (parsewarning(parser, WARN_EXTENSIONS, "for loops are not recognized in the original Quake C standard, to enable try an alternate standard --std=?"))
3374                     return false;
3375             }
3376             return parse_for(parser, block, out);
3377         }
3378         else if (!strcmp(parser_tokval(parser), "break"))
3379         {
3380             return parse_break_continue(parser, block, out, false);
3381         }
3382         else if (!strcmp(parser_tokval(parser), "continue"))
3383         {
3384             return parse_break_continue(parser, block, out, true);
3385         }
3386         else if (!strcmp(parser_tokval(parser), "switch"))
3387         {
3388             return parse_switch(parser, block, out);
3389         }
3390         else if (!strcmp(parser_tokval(parser), "case") ||
3391                  !strcmp(parser_tokval(parser), "default"))
3392         {
3393             if (!allow_cases) {
3394                 parseerror(parser, "unexpected 'case' label");
3395                 return false;
3396             }
3397             return true;
3398         }
3399         else if (!strcmp(parser_tokval(parser), "goto"))
3400         {
3401             return parse_goto(parser, out);
3402         }
3403         else if (!strcmp(parser_tokval(parser), "typedef"))
3404         {
3405             if (!parser_next(parser)) {
3406                 parseerror(parser, "expected type definition after 'typedef'");
3407                 return false;
3408             }
3409             return parse_typedef(parser);
3410         }
3411         parseerror(parser, "Unexpected keyword: `%s'", parser_tokval(parser));
3412         return false;
3413     }
3414     else if (parser->tok == '{')
3415     {
3416         ast_block *inner;
3417         inner = parse_block(parser);
3418         if (!inner)
3419             return false;
3420         *out = (ast_expression*)inner;
3421         return true;
3422     }
3423     else if (parser->tok == ':')
3424     {
3425         size_t i;
3426         ast_label *label;
3427         if (!parser_next(parser)) {
3428             parseerror(parser, "expected label name");
3429             return false;
3430         }
3431         if (parser->tok != TOKEN_IDENT) {
3432             parseerror(parser, "label must be an identifier");
3433             return false;
3434         }
3435         label = (ast_label*)parser_find_label(parser, parser_tokval(parser));
3436         if (label) {
3437             if (!label->undefined) {
3438                 parseerror(parser, "label `%s` already defined", label->name);
3439                 return false;
3440             }
3441             label->undefined = false;
3442         }
3443         else {
3444             label = ast_label_new(parser_ctx(parser), parser_tokval(parser), false);
3445             vec_push(parser->labels, label);
3446         }
3447         *out = (ast_expression*)label;
3448         if (!parser_next(parser)) {
3449             parseerror(parser, "parse error after label");
3450             return false;
3451         }
3452         for (i = 0; i < vec_size(parser->gotos); ++i) {
3453             if (!strcmp(parser->gotos[i]->name, label->name)) {
3454                 ast_goto_set_label(parser->gotos[i], label);
3455                 vec_remove(parser->gotos, i, 1);
3456                 --i;
3457             }
3458         }
3459         return true;
3460     }
3461     else if (parser->tok == ';')
3462     {
3463         if (!parser_next(parser)) {
3464             parseerror(parser, "parse error after empty statement");
3465             return false;
3466         }
3467         return true;
3468     }
3469     else
3470     {
3471         lex_ctx_t ctx = parser_ctx(parser);
3472         ast_expression *exp = parse_expression(parser, false, false);
3473         if (!exp)
3474             return false;
3475         *out = exp;
3476         if (!ast_side_effects(exp)) {
3477             if (compile_warning(ctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
3478                &nb