Remove debugging aid and left over cruft.
[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     switch (op->id)
357     {
358         default:
359             compile_error(ctx, "internal error: unhandled operator: %s (%i)", op->op, (int)op->id);
360             return false;
361
362         case opid1('.'):
363             if (exprs[0]->vtype == TYPE_VECTOR &&
364                 exprs[1]->vtype == TYPE_NOEXPR)
365             {
366                 if      (exprs[1] == (ast_expression*)parser->const_vec[0])
367                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
368                 else if (exprs[1] == (ast_expression*)parser->const_vec[1])
369                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
370                 else if (exprs[1] == (ast_expression*)parser->const_vec[2])
371                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
372                 else {
373                     compile_error(ctx, "access to invalid vector component");
374                     return false;
375                 }
376             }
377             else if (exprs[0]->vtype == TYPE_ENTITY) {
378                 if (exprs[1]->vtype != TYPE_FIELD) {
379                     compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
380                     return false;
381                 }
382                 out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
383             }
384             else if (exprs[0]->vtype == TYPE_VECTOR) {
385                 compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
386                 return false;
387             }
388             else {
389                 compile_error(ast_ctx(exprs[1]), "type error: member-of operator on something that is not an entity or vector");
390                 return false;
391             }
392             break;
393
394         case opid1('['):
395             if (exprs[0]->vtype != TYPE_ARRAY &&
396                 !(exprs[0]->vtype == TYPE_FIELD &&
397                   exprs[0]->next->vtype == TYPE_ARRAY))
398             {
399                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
400                 compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
401                 return false;
402             }
403             if (exprs[1]->vtype != TYPE_FLOAT) {
404                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
405                 compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
406                 return false;
407             }
408             out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]);
409             if (rotate_entfield_array_index_nodes(&out))
410             {
411 #if 0
412                 /* This is not broken in fteqcc anymore */
413                 if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
414                     /* this error doesn't need to make us bail out */
415                     (void)!parsewarning(parser, WARN_EXTENSIONS,
416                                         "accessing array-field members of an entity without parenthesis\n"
417                                         " -> this is an extension from -std=gmqcc");
418                 }
419 #endif
420             }
421             break;
422
423         case opid1(','):
424             if (vec_size(sy->paren) && vec_last(sy->paren) == PAREN_FUNC) {
425                 vec_push(sy->out, syexp(ctx, exprs[0]));
426                 vec_push(sy->out, syexp(ctx, exprs[1]));
427                 vec_last(sy->argc)++;
428                 return true;
429             }
430             if (blocks[0]) {
431                 if (!ast_block_add_expr(blocks[0], exprs[1]))
432                     return false;
433             } else {
434                 blocks[0] = ast_block_new(ctx);
435                 if (!ast_block_add_expr(blocks[0], exprs[0]) ||
436                     !ast_block_add_expr(blocks[0], exprs[1]))
437                 {
438                     return false;
439                 }
440             }
441             ast_block_set_type(blocks[0], exprs[1]);
442
443             vec_push(sy->out, syblock(ctx, blocks[0]));
444             return true;
445
446         case opid2('+','P'):
447             out = exprs[0];
448             break;
449         case opid2('-','P'):
450             if (!(out = fold_op(parser->fold, op, exprs))) {
451                 switch (exprs[0]->vtype) {
452                     case TYPE_FLOAT:
453                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F,
454                                                                   (ast_expression*)parser->fold->imm_float[0],
455                                                                   exprs[0]);
456                         break;
457                     case TYPE_VECTOR:
458                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V,
459                                                                   (ast_expression*)parser->fold->imm_vector[0],
460                                                                   exprs[0]);
461                         break;
462                     default:
463                     compile_error(ctx, "invalid types used in expression: cannot negate type %s",
464                                   type_name[exprs[0]->vtype]);
465                     return false;
466                 }
467             }
468             break;
469
470         case opid2('!','P'):
471             if (!(out = fold_op(parser->fold, op, exprs))) {
472                 switch (exprs[0]->vtype) {
473                     case TYPE_FLOAT:
474                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
475                         break;
476                     case TYPE_VECTOR:
477                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]);
478                         break;
479                     case TYPE_STRING:
480                         if (OPTS_FLAG(TRUE_EMPTY_STRINGS))
481                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
482                         else
483                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]);
484                         break;
485                     /* we don't constant-fold NOT for these types */
486                     case TYPE_ENTITY:
487                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_ENT, exprs[0]);
488                         break;
489                     case TYPE_FUNCTION:
490                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_FNC, exprs[0]);
491                         break;
492                     default:
493                     compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
494                                   type_name[exprs[0]->vtype]);
495                     return false;
496                 }
497             }
498             break;
499
500         case opid1('+'):
501             if (exprs[0]->vtype != exprs[1]->vtype ||
502                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
503             {
504                 compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
505                               type_name[exprs[0]->vtype],
506                               type_name[exprs[1]->vtype]);
507                 return false;
508             }
509             if (!(out = fold_op(parser->fold, op, exprs))) {
510                 switch (exprs[0]->vtype) {
511                     case TYPE_FLOAT:
512                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
513                         break;
514                     case TYPE_VECTOR:
515                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
516                         break;
517                     default:
518                         compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
519                                       type_name[exprs[0]->vtype],
520                                       type_name[exprs[1]->vtype]);
521                         return false;
522                 }
523             }
524             break;
525         case opid1('-'):
526             if  (exprs[0]->vtype != exprs[1]->vtype ||
527                 (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT))
528             {
529                 compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
530                               type_name[exprs[1]->vtype],
531                               type_name[exprs[0]->vtype]);
532                 return false;
533             }
534             if (!(out = fold_op(parser->fold, op, exprs))) {
535                 switch (exprs[0]->vtype) {
536                     case TYPE_FLOAT:
537                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
538                         break;
539                     case TYPE_VECTOR:
540                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
541                         break;
542                     default:
543                         compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
544                                       type_name[exprs[1]->vtype],
545                                       type_name[exprs[0]->vtype]);
546                         return false;
547                 }
548             }
549             break;
550         case opid1('*'):
551             if (exprs[0]->vtype != exprs[1]->vtype &&
552                 !(exprs[0]->vtype == TYPE_VECTOR &&
553                   exprs[1]->vtype == TYPE_FLOAT) &&
554                 !(exprs[1]->vtype == TYPE_VECTOR &&
555                   exprs[0]->vtype == TYPE_FLOAT)
556                 )
557             {
558                 compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
559                               type_name[exprs[1]->vtype],
560                               type_name[exprs[0]->vtype]);
561                 return false;
562             }
563             if (!(out = fold_op(parser->fold, op, exprs))) {
564                 switch (exprs[0]->vtype) {
565                     case TYPE_FLOAT:
566                         if (exprs[1]->vtype == TYPE_VECTOR)
567                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
568                         else
569                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
570                         break;
571                     case TYPE_VECTOR:
572                         if (exprs[1]->vtype == TYPE_FLOAT)
573                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
574                         else
575                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
576                         break;
577                     default:
578                         compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
579                                       type_name[exprs[1]->vtype],
580                                       type_name[exprs[0]->vtype]);
581                         return false;
582                 }
583             }
584             break;
585
586         case opid1('/'):
587             if (exprs[1]->vtype != TYPE_FLOAT) {
588                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
589                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
590                 compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2);
591                 return false;
592             }
593             if (!(out = fold_op(parser->fold, op, exprs))) {
594                 if (exprs[0]->vtype == TYPE_FLOAT)
595                     out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
596                 else {
597                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
598                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
599                     compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2);
600                     return false;
601                 }
602             }
603             break;
604
605         case opid1('%'):
606             if (NotSameType(TYPE_FLOAT)) {
607                 compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s",
608                     type_name[exprs[0]->vtype],
609                     type_name[exprs[1]->vtype]);
610                 return false;
611             } else if (!(out = fold_op(parser->fold, op, exprs))) {
612                 /* generate a call to __builtin_mod */
613                 ast_expression *mod  = intrin_func(parser, "mod");
614                 ast_call       *call = NULL;
615                 if (!mod) return false; /* can return null for missing floor */
616
617                 call = ast_call_new(parser_ctx(parser), mod);
618                 vec_push(call->params, exprs[0]);
619                 vec_push(call->params, exprs[1]);
620
621                 out = (ast_expression*)call;
622             }
623             break;
624
625         case opid2('%','='):
626             compile_error(ctx, "%= is unimplemented");
627             return false;
628
629         case opid1('|'):
630         case opid1('&'):
631             if (NotSameType(TYPE_FLOAT)) {
632                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
633                               type_name[exprs[0]->vtype],
634                               type_name[exprs[1]->vtype]);
635                 return false;
636             }
637             if (!(out = fold_op(parser->fold, op, exprs)))
638                 out = (ast_expression*)ast_binary_new(ctx,
639                     (op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND),
640                     exprs[0], exprs[1]);
641             break;
642         case opid1('^'):
643             /*
644              * Okay lets designate what the hell is an acceptable use
645              * of the ^ operator. In many vector processing units, XOR
646              * is allowed to be used on vectors, but only if the first
647              * operand is a vector, the second operand can be a float
648              * or vector. It's never legal for the first operand to be
649              * a float, and then the following operand to be a vector.
650              * Further more, the only time it is legal to do XOR otherwise
651              * is when both operand are floats. This nicely crafted if
652              * statement catches them all.
653              *
654              * In the event that the first operand is a vector, two
655              * possible situations can arise, thus, each element of
656              * vector A (operand A) is exclusive-ORed with the corresponding
657              * element of vector B (operand B), If B is scalar, the
658              * scalar value is first replicated for each element.
659              *
660              * The QCVM itself lacks a BITXOR instruction. Thus emulating
661              * the mathematics of it is required. The following equation
662              * is used: (LHS | RHS) & ~(LHS & RHS). However, due to the
663              * QCVM also lacking a BITNEG instruction, we need to emulate
664              * ~FOO with -1 - FOO, the whole process becoming this nicely
665              * crafted expression: (LHS | RHS) & (-1 - (LHS & RHS)).
666              *
667              * When A is not scalar, this process is repeated for all
668              * components of vector A with the value in operand B,
669              * only if operand B is scalar. When A is not scalar, and B
670              * is also not scalar, this process is repeated for all
671              * components of the vector A with the components of vector B.
672              * Finally when A is scalar and B is scalar, this process is
673              * simply used once for A and B being LHS and RHS respectfully.
674              *
675              * Yes the semantics are a bit strange (no pun intended).
676              * But then again BITXOR is strange itself, consdering it's
677              * commutative, assocative, and elements of the BITXOR operation
678              * are their own inverse.
679              */
680             if ( !(exprs[0]->vtype == TYPE_FLOAT  && exprs[1]->vtype == TYPE_FLOAT) &&
681                  !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_FLOAT) &&
682                  !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_VECTOR))
683             {
684                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
685                               type_name[exprs[0]->vtype],
686                               type_name[exprs[1]->vtype]);
687                 return false;
688             }
689
690             if (!(out = fold_op(parser->fold, op, exprs))) {
691                 /*
692                  * IF the first expression is float, the following will be too
693                  * since scalar ^ vector is not allowed.
694                  */
695                 if (exprs[0]->vtype == TYPE_FLOAT) {
696                     ast_binary *expr = ast_binary_new(
697                         ctx,
698                         INSTR_SUB_F,
699                         (ast_expression*)parser->fold->imm_float[2],
700                         (ast_expression*)ast_binary_new(
701                             ctx,
702                             INSTR_BITAND,
703                             exprs[0],
704                             exprs[1]
705                         )
706                     );
707                     expr->refs = AST_REF_NONE;
708
709                     out = (ast_expression*)
710                         ast_binary_new(
711                             ctx,
712                             INSTR_BITAND,
713                             (ast_expression*)ast_binary_new(
714                                 ctx,
715                                 INSTR_BITOR,
716                                 exprs[0],
717                                 exprs[1]
718                             ),
719                             (ast_expression*)expr
720                         );
721                 } else {
722                     /*
723                      * The first is a vector: vector is allowed to xor with vector and
724                      * with scalar, branch here for the second operand.
725                      */
726                     if (exprs[1]->vtype == TYPE_VECTOR) {
727                         /*
728                          * Xor all the values of the vector components against the
729                          * vectors components in question.
730                          */
731                         compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against vector");
732                         return false;
733                     } else {
734                         compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against float");
735                         return false;
736                     }
737                 }
738             }
739             break;
740
741         case opid2('<','<'):
742         case opid2('>','>'):
743         case opid3('<','<','='):
744         case opid3('>','>','='):
745             if(!(out = fold_op(parser->fold, op, exprs))) {
746                 compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts");
747                 return false;
748             }
749
750         case opid2('|','|'):
751             generated_op += 1; /* INSTR_OR */
752         case opid2('&','&'):
753             generated_op += INSTR_AND;
754             if (!(out = fold_op(parser->fold, op, exprs))) {
755                 if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) {
756                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
757                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
758                     compile_error(ctx, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2);
759                     return false;
760                 }
761                 for (i = 0; i < 2; ++i) {
762                     if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) {
763                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
764                         if (!out) break;
765                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
766                         if (!out) break;
767                         exprs[i] = out; out = NULL;
768                         if (OPTS_FLAG(PERL_LOGIC)) {
769                             /* here we want to keep the right expressions' type */
770                             break;
771                         }
772                     }
773                     else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) {
774                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
775                         if (!out) break;
776                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
777                         if (!out) break;
778                         exprs[i] = out; out = NULL;
779                         if (OPTS_FLAG(PERL_LOGIC)) {
780                             /* here we want to keep the right expressions' type */
781                             break;
782                         }
783                     }
784                 }
785                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
786             }
787             break;
788
789         case opid2('?',':'):
790             if (vec_last(sy->paren) != PAREN_TERNARY2) {
791                 compile_error(ctx, "mismatched parenthesis/ternary");
792                 return false;
793             }
794             vec_pop(sy->paren);
795             if (!ast_compare_type(exprs[1], exprs[2])) {
796                 ast_type_to_string(exprs[1], ty1, sizeof(ty1));
797                 ast_type_to_string(exprs[2], ty2, sizeof(ty2));
798                 compile_error(ctx, "operands of ternary expression must have the same type, got %s and %s", ty1, ty2);
799                 return false;
800             }
801             if (!(out = fold_op(parser->fold, op, exprs)))
802                 out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]);
803             break;
804
805         case opid2('*', '*'):
806             if (NotSameType(TYPE_FLOAT)) {
807                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
808                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
809                 compile_error(ctx, "invalid types used in exponentiation: %s and %s",
810                     ty1, ty2);
811                 return false;
812             }
813             
814             if (!(out = fold_op(parser->fold, op, exprs))) {
815                 ast_call *gencall = ast_call_new(parser_ctx(parser), intrin_func(parser, "pow"));
816                 vec_push(gencall->params, exprs[0]);
817                 vec_push(gencall->params, exprs[1]);
818                 out = (ast_expression*)gencall;
819             }
820             break;
821
822         case opid3('<','=','>'): /* -1, 0, or 1 */
823             if (NotSameType(TYPE_FLOAT)) {
824                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
825                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
826                 compile_error(ctx, "invalid types used in comparision: %s and %s",
827                     ty1, ty2);
828
829                 return false;
830             } 
831
832             if (!(out = fold_op(parser->fold, op, exprs))) {
833                 ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
834
835                 eq->refs = AST_REF_NONE;
836
837                     /* if (lt) { */
838                 out = (ast_expression*)ast_ternary_new(ctx,
839                         (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]),
840                         /* out = -1 */
841                         (ast_expression*)parser->fold->imm_float[2],
842                     /* } else { */
843                         /* if (eq) { */
844                         (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq,
845                             /* out = 0 */
846                             (ast_expression*)parser->fold->imm_float[0],
847                         /* } else { */
848                             /* out = 1 */
849                             (ast_expression*)parser->fold->imm_float[1]
850                         /* } */
851                         )
852                     /* } */
853                     );
854
855             }
856             break;
857
858         case opid1('>'):
859             generated_op += 1; /* INSTR_GT */
860         case opid1('<'):
861             generated_op += 1; /* INSTR_LT */
862         case opid2('>', '='):
863             generated_op += 1; /* INSTR_GE */
864         case opid2('<', '='):
865             generated_op += INSTR_LE;
866             if (NotSameType(TYPE_FLOAT)) {
867                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
868                               type_name[exprs[0]->vtype],
869                               type_name[exprs[1]->vtype]);
870                 return false;
871             }
872             if (!(out = fold_op(parser->fold, op, exprs)))
873                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
874             break;
875         case opid2('!', '='):
876             if (exprs[0]->vtype != exprs[1]->vtype) {
877                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
878                               type_name[exprs[0]->vtype],
879                               type_name[exprs[1]->vtype]);
880                 return false;
881             }
882             if (!(out = fold_op(parser->fold, op, exprs)))
883                 out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
884             break;
885         case opid2('=', '='):
886             if (exprs[0]->vtype != exprs[1]->vtype) {
887                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
888                               type_name[exprs[0]->vtype],
889                               type_name[exprs[1]->vtype]);
890                 return false;
891             }
892             if (!(out = fold_op(parser->fold, op, exprs)))
893                 out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
894             break;
895
896         case opid1('='):
897             if (ast_istype(exprs[0], ast_entfield)) {
898                 ast_expression *field = ((ast_entfield*)exprs[0])->field;
899                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
900                     exprs[0]->vtype == TYPE_FIELD &&
901                     exprs[0]->next->vtype == TYPE_VECTOR)
902                 {
903                     assignop = type_storep_instr[TYPE_VECTOR];
904                 }
905                 else
906                     assignop = type_storep_instr[exprs[0]->vtype];
907                 if (assignop == VINSTR_END || !ast_compare_type(field->next, exprs[1]))
908                 {
909                     ast_type_to_string(field->next, ty1, sizeof(ty1));
910                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
911                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
912                         field->next->vtype == TYPE_FUNCTION &&
913                         exprs[1]->vtype == TYPE_FUNCTION)
914                     {
915                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
916                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
917                     }
918                     else
919                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
920                 }
921             }
922             else
923             {
924                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
925                     exprs[0]->vtype == TYPE_FIELD &&
926                     exprs[0]->next->vtype == TYPE_VECTOR)
927                 {
928                     assignop = type_store_instr[TYPE_VECTOR];
929                 }
930                 else {
931                     assignop = type_store_instr[exprs[0]->vtype];
932                 }
933
934                 if (assignop == VINSTR_END) {
935                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
936                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
937                     compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
938                 }
939                 else if (!ast_compare_type(exprs[0], exprs[1]))
940                 {
941                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
942                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
943                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
944                         exprs[0]->vtype == TYPE_FUNCTION &&
945                         exprs[1]->vtype == TYPE_FUNCTION)
946                     {
947                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
948                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
949                     }
950                     else
951                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
952                 }
953             }
954             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
955                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
956             }
957             out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]);
958             break;
959         case opid3('+','+','P'):
960         case opid3('-','-','P'):
961             /* prefix ++ */
962             if (exprs[0]->vtype != TYPE_FLOAT) {
963                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
964                 compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
965                 return false;
966             }
967             if (op->id == opid3('+','+','P'))
968                 addop = INSTR_ADD_F;
969             else
970                 addop = INSTR_SUB_F;
971             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
972                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
973             }
974             if (ast_istype(exprs[0], ast_entfield)) {
975                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
976                                                         exprs[0],
977                                                         (ast_expression*)parser->fold->imm_float[1]);
978             } else {
979                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
980                                                         exprs[0],
981                                                         (ast_expression*)parser->fold->imm_float[1]);
982             }
983             break;
984         case opid3('S','+','+'):
985         case opid3('S','-','-'):
986             /* prefix ++ */
987             if (exprs[0]->vtype != TYPE_FLOAT) {
988                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
989                 compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
990                 return false;
991             }
992             if (op->id == opid3('S','+','+')) {
993                 addop = INSTR_ADD_F;
994                 subop = INSTR_SUB_F;
995             } else {
996                 addop = INSTR_SUB_F;
997                 subop = INSTR_ADD_F;
998             }
999             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1000                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
1001             }
1002             if (ast_istype(exprs[0], ast_entfield)) {
1003                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
1004                                                         exprs[0],
1005                                                         (ast_expression*)parser->fold->imm_float[1]);
1006             } else {
1007                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
1008                                                         exprs[0],
1009                                                         (ast_expression*)parser->fold->imm_float[1]);
1010             }
1011             if (!out)
1012                 return false;
1013             out = (ast_expression*)ast_binary_new(ctx, subop,
1014                                                   out,
1015                                                   (ast_expression*)parser->fold->imm_float[1]);
1016             break;
1017         case opid2('+','='):
1018         case opid2('-','='):
1019             if (exprs[0]->vtype != exprs[1]->vtype ||
1020                 (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
1021             {
1022                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1023                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1024                 compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1025                               ty1, ty2);
1026                 return false;
1027             }
1028             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1029                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1030             }
1031             if (ast_istype(exprs[0], ast_entfield))
1032                 assignop = type_storep_instr[exprs[0]->vtype];
1033             else
1034                 assignop = type_store_instr[exprs[0]->vtype];
1035             switch (exprs[0]->vtype) {
1036                 case TYPE_FLOAT:
1037                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1038                                                             (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
1039                                                             exprs[0], exprs[1]);
1040                     break;
1041                 case TYPE_VECTOR:
1042                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1043                                                             (op->id == opid2('+','=') ? INSTR_ADD_V : INSTR_SUB_V),
1044                                                             exprs[0], exprs[1]);
1045                     break;
1046                 default:
1047                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1048                                   type_name[exprs[0]->vtype],
1049                                   type_name[exprs[1]->vtype]);
1050                     return false;
1051             };
1052             break;
1053         case opid2('*','='):
1054         case opid2('/','='):
1055             if (exprs[1]->vtype != TYPE_FLOAT ||
1056                 !(exprs[0]->vtype == TYPE_FLOAT ||
1057                   exprs[0]->vtype == TYPE_VECTOR))
1058             {
1059                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1060                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1061                 compile_error(ctx, "invalid types used in expression: %s and %s",
1062                               ty1, ty2);
1063                 return false;
1064             }
1065             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1066                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1067             }
1068             if (ast_istype(exprs[0], ast_entfield))
1069                 assignop = type_storep_instr[exprs[0]->vtype];
1070             else
1071                 assignop = type_store_instr[exprs[0]->vtype];
1072             switch (exprs[0]->vtype) {
1073                 case TYPE_FLOAT:
1074                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1075                                                             (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
1076                                                             exprs[0], exprs[1]);
1077                     break;
1078                 case TYPE_VECTOR:
1079                     if (op->id == opid2('*','=')) {
1080                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1081                                                                 exprs[0], exprs[1]);
1082                     } else {
1083                         out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
1084                                                                   (ast_expression*)parser->fold->imm_float[1],
1085                                                                   exprs[1]);
1086                         if (!out) {
1087                             compile_error(ctx, "internal error: failed to generate division");
1088                             return false;
1089                         }
1090                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1091                                                                 exprs[0], out);
1092                     }
1093                     break;
1094                 default:
1095                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1096                                   type_name[exprs[0]->vtype],
1097                                   type_name[exprs[1]->vtype]);
1098                     return false;
1099             };
1100             break;
1101         case opid2('&','='):
1102         case opid2('|','='):
1103             if (NotSameType(TYPE_FLOAT)) {
1104                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1105                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1106                 compile_error(ctx, "invalid types used in expression: %s and %s",
1107                               ty1, ty2);
1108                 return false;
1109             }
1110             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1111                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1112             }
1113             if (ast_istype(exprs[0], ast_entfield))
1114                 assignop = type_storep_instr[exprs[0]->vtype];
1115             else
1116                 assignop = type_store_instr[exprs[0]->vtype];
1117             out = (ast_expression*)ast_binstore_new(ctx, assignop,
1118                                                     (op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
1119                                                     exprs[0], exprs[1]);
1120             break;
1121         case opid3('&','~','='):
1122             /* This is like: a &= ~(b);
1123              * But QC has no bitwise-not, so we implement it as
1124              * a -= a & (b);
1125              */
1126             if (NotSameType(TYPE_FLOAT)) {
1127                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1128                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1129                 compile_error(ctx, "invalid types used in expression: %s and %s",
1130                               ty1, ty2);
1131                 return false;
1132             }
1133             if (ast_istype(exprs[0], ast_entfield))
1134                 assignop = type_storep_instr[exprs[0]->vtype];
1135             else
1136                 assignop = type_store_instr[exprs[0]->vtype];
1137             out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
1138             if (!out)
1139                 return false;
1140             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1141                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1142             }
1143             asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out);
1144             asbinstore->keep_dest = true;
1145             out = (ast_expression*)asbinstore;
1146             break;
1147
1148         case opid2('~', 'P'):
1149             if (exprs[0]->vtype != TYPE_FLOAT) {
1150                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1151                 compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
1152                 return false;
1153             }
1154             if (!(out = fold_op(parser->fold, op, exprs)))
1155                 out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]);
1156             break;
1157     }
1158 #undef NotSameType
1159     if (!out) {
1160         compile_error(ctx, "failed to apply operator %s", op->op);
1161         return false;
1162     }
1163
1164     vec_push(sy->out, syexp(ctx, out));
1165     return true;
1166 }
1167
1168 static bool parser_close_call(parser_t *parser, shunt *sy)
1169 {
1170     /* was a function call */
1171     ast_expression *fun;
1172     ast_value      *funval = NULL;
1173     ast_call       *call;
1174
1175     size_t          fid;
1176     size_t          paramcount, i;
1177
1178     fid = vec_last(sy->ops).off;
1179     vec_shrinkby(sy->ops, 1);
1180
1181     /* out[fid] is the function
1182      * everything above is parameters...
1183      */
1184     if (!vec_size(sy->argc)) {
1185         parseerror(parser, "internal error: no argument counter available");
1186         return false;
1187     }
1188
1189     paramcount = vec_last(sy->argc);
1190     vec_pop(sy->argc);
1191
1192     if (vec_size(sy->out) < fid) {
1193         parseerror(parser, "internal error: broken function call%lu < %lu+%lu\n",
1194                    (unsigned long)vec_size(sy->out),
1195                    (unsigned long)fid,
1196                    (unsigned long)paramcount);
1197         return false;
1198     }
1199
1200     fun = sy->out[fid].out;
1201
1202     if (fun == intrinsic_debug_typestring) {
1203         char ty[1024];
1204         if (fid+2 != vec_size(sy->out) ||
1205             vec_last(sy->out).block)
1206         {
1207             parseerror(parser, "intrinsic __builtin_debug_typestring requires exactly 1 parameter");
1208             return false;
1209         }
1210         ast_type_to_string(vec_last(sy->out).out, ty, sizeof(ty));
1211         ast_unref(vec_last(sy->out).out);
1212         sy->out[fid] = syexp(ast_ctx(vec_last(sy->out).out),
1213                              (ast_expression*)fold_constgen_string(parser->fold, ty, false));
1214         vec_shrinkby(sy->out, 1);
1215         return true;
1216     }
1217
1218     call = ast_call_new(sy->ops[vec_size(sy->ops)].ctx, fun);
1219     if (!call)
1220         return false;
1221
1222     if (fid+1 < vec_size(sy->out))
1223         ++paramcount;
1224
1225     if (fid+1 + paramcount != vec_size(sy->out)) {
1226         parseerror(parser, "internal error: parameter count mismatch: (%lu+1+%lu), %lu",
1227                    (unsigned long)fid, (unsigned long)paramcount, (unsigned long)vec_size(sy->out));
1228         return false;
1229     }
1230
1231     for (i = 0; i < paramcount; ++i)
1232         vec_push(call->params, sy->out[fid+1 + i].out);
1233     vec_shrinkby(sy->out, paramcount);
1234     (void)!ast_call_check_types(call, parser->function->vtype->expression.varparam);
1235     if (parser->max_param_count < paramcount)
1236         parser->max_param_count = paramcount;
1237
1238     if (ast_istype(fun, ast_value)) {
1239         funval = (ast_value*)fun;
1240         if ((fun->flags & AST_FLAG_VARIADIC) &&
1241             !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
1242         {
1243             call->va_count = (ast_expression*)fold_constgen_float(parser->fold, (qcfloat_t)paramcount);
1244         }
1245     }
1246
1247     /* overwrite fid, the function, with a call */
1248     sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
1249
1250     if (fun->vtype != TYPE_FUNCTION) {
1251         parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
1252         return false;
1253     }
1254
1255     if (!fun->next) {
1256         parseerror(parser, "could not determine function return type");
1257         return false;
1258     } else {
1259         ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
1260
1261         if (fun->flags & AST_FLAG_DEPRECATED) {
1262             if (!fval) {
1263                 return !parsewarning(parser, WARN_DEPRECATED,
1264                         "call to function (which is marked deprecated)\n",
1265                         "-> it has been declared here: %s:%i",
1266                         ast_ctx(fun).file, ast_ctx(fun).line);
1267             }
1268             if (!fval->desc) {
1269                 return !parsewarning(parser, WARN_DEPRECATED,
1270                         "call to `%s` (which is marked deprecated)\n"
1271                         "-> `%s` declared here: %s:%i",
1272                         fval->name, fval->name, ast_ctx(fun).file, ast_ctx(fun).line);
1273             }
1274             return !parsewarning(parser, WARN_DEPRECATED,
1275                     "call to `%s` (deprecated: %s)\n"
1276                     "-> `%s` declared here: %s:%i",
1277                     fval->name, fval->desc, fval->name, ast_ctx(fun).file,
1278                     ast_ctx(fun).line);
1279         }
1280
1281         if (vec_size(fun->params) != paramcount &&
1282             !((fun->flags & AST_FLAG_VARIADIC) &&
1283               vec_size(fun->params) < paramcount))
1284         {
1285             const char *fewmany = (vec_size(fun->params) > paramcount) ? "few" : "many";
1286             if (fval)
1287                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1288                                      "too %s parameters for call to %s: expected %i, got %i\n"
1289                                      " -> `%s` has been declared here: %s:%i",
1290                                      fewmany, fval->name, (int)vec_size(fun->params), (int)paramcount,
1291                                      fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1292             else
1293                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1294                                      "too %s parameters for function call: expected %i, got %i\n"
1295                                      " -> it has been declared here: %s:%i",
1296                                      fewmany, (int)vec_size(fun->params), (int)paramcount,
1297                                      ast_ctx(fun).file, (int)ast_ctx(fun).line);
1298         }
1299     }
1300
1301     return true;
1302 }
1303
1304 static bool parser_close_paren(parser_t *parser, shunt *sy)
1305 {
1306     if (!vec_size(sy->ops)) {
1307         parseerror(parser, "unmatched closing paren");
1308         return false;
1309     }
1310
1311     while (vec_size(sy->ops)) {
1312         if (vec_last(sy->ops).isparen) {
1313             if (vec_last(sy->paren) == PAREN_FUNC) {
1314                 vec_pop(sy->paren);
1315                 if (!parser_close_call(parser, sy))
1316                     return false;
1317                 break;
1318             }
1319             if (vec_last(sy->paren) == PAREN_EXPR) {
1320                 vec_pop(sy->paren);
1321                 if (!vec_size(sy->out)) {
1322                     compile_error(vec_last(sy->ops).ctx, "empty paren expression");
1323                     vec_shrinkby(sy->ops, 1);
1324                     return false;
1325                 }
1326                 vec_shrinkby(sy->ops, 1);
1327                 break;
1328             }
1329             if (vec_last(sy->paren) == PAREN_INDEX) {
1330                 vec_pop(sy->paren);
1331                 /* pop off the parenthesis */
1332                 vec_shrinkby(sy->ops, 1);
1333                 /* then apply the index operator */
1334                 if (!parser_sy_apply_operator(parser, sy))
1335                     return false;
1336                 break;
1337             }
1338             if (vec_last(sy->paren) == PAREN_TERNARY1) {
1339                 vec_last(sy->paren) = PAREN_TERNARY2;
1340                 /* pop off the parenthesis */
1341                 vec_shrinkby(sy->ops, 1);
1342                 break;
1343             }
1344             compile_error(vec_last(sy->ops).ctx, "invalid parenthesis");
1345             return false;
1346         }
1347         if (!parser_sy_apply_operator(parser, sy))
1348             return false;
1349     }
1350     return true;
1351 }
1352
1353 static void parser_reclassify_token(parser_t *parser)
1354 {
1355     size_t i;
1356     if (parser->tok >= TOKEN_START)
1357         return;
1358     for (i = 0; i < operator_count; ++i) {
1359         if (!strcmp(parser_tokval(parser), operators[i].op)) {
1360             parser->tok = TOKEN_OPERATOR;
1361             return;
1362         }
1363     }
1364 }
1365
1366 static ast_expression* parse_vararg_do(parser_t *parser)
1367 {
1368     ast_expression *idx, *out;
1369     ast_value      *typevar;
1370     ast_value      *funtype = parser->function->vtype;
1371     lex_ctx_t         ctx     = parser_ctx(parser);
1372
1373     if (!parser->function->varargs) {
1374         parseerror(parser, "function has no variable argument list");
1375         return NULL;
1376     }
1377
1378     if (!parser_next(parser) || parser->tok != '(') {
1379         parseerror(parser, "expected parameter index and type in parenthesis");
1380         return NULL;
1381     }
1382     if (!parser_next(parser)) {
1383         parseerror(parser, "error parsing parameter index");
1384         return NULL;
1385     }
1386
1387     idx = parse_expression_leave(parser, true, false, false);
1388     if (!idx)
1389         return NULL;
1390
1391     if (parser->tok != ',') {
1392         if (parser->tok != ')') {
1393             ast_unref(idx);
1394             parseerror(parser, "expected comma after parameter index");
1395             return NULL;
1396         }
1397         /* vararg piping: ...(start) */
1398         out = (ast_expression*)ast_argpipe_new(ctx, idx);
1399         return out;
1400     }
1401
1402     if (!parser_next(parser) || (parser->tok != TOKEN_IDENT && parser->tok != TOKEN_TYPENAME)) {
1403         ast_unref(idx);
1404         parseerror(parser, "expected typename for vararg");
1405         return NULL;
1406     }
1407
1408     typevar = parse_typename(parser, NULL, NULL);
1409     if (!typevar) {
1410         ast_unref(idx);
1411         return NULL;
1412     }
1413
1414     if (parser->tok != ')') {
1415         ast_unref(idx);
1416         ast_delete(typevar);
1417         parseerror(parser, "expected closing paren");
1418         return NULL;
1419     }
1420
1421     if (funtype->expression.varparam &&
1422         !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
1423     {
1424         char ty1[1024];
1425         char ty2[1024];
1426         ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1));
1427         ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2));
1428         compile_error(ast_ctx(typevar),
1429                       "function was declared to take varargs of type `%s`, requested type is: %s",
1430                       ty2, ty1);
1431     }
1432
1433     out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->varargs), idx);
1434     ast_type_adopt(out, typevar);
1435     ast_delete(typevar);
1436     return out;
1437 }
1438
1439 static ast_expression* parse_vararg(parser_t *parser)
1440 {
1441     bool           old_noops = parser->lex->flags.noops;
1442
1443     ast_expression *out;
1444
1445     parser->lex->flags.noops = true;
1446     out = parse_vararg_do(parser);
1447
1448     parser->lex->flags.noops = old_noops;
1449     return out;
1450 }
1451
1452 /* not to be exposed */
1453 extern bool ftepp_predef_exists(const char *name);
1454
1455 static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
1456 {
1457     if (OPTS_FLAG(TRANSLATABLE_STRINGS) &&
1458         parser->tok == TOKEN_IDENT &&
1459         !strcmp(parser_tokval(parser), "_"))
1460     {
1461         /* a translatable string */
1462         ast_value *val;
1463
1464         parser->lex->flags.noops = true;
1465         if (!parser_next(parser) || parser->tok != '(') {
1466             parseerror(parser, "use _(\"string\") to create a translatable string constant");
1467             return false;
1468         }
1469         parser->lex->flags.noops = false;
1470         if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
1471             parseerror(parser, "expected a constant string in translatable-string extension");
1472             return false;
1473         }
1474         val = (ast_value*)fold_constgen_string(parser->fold, parser_tokval(parser), true);
1475         if (!val)
1476             return false;
1477         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1478
1479         if (!parser_next(parser) || parser->tok != ')') {
1480             parseerror(parser, "expected closing paren after translatable string");
1481             return false;
1482         }
1483         return true;
1484     }
1485     else if (parser->tok == TOKEN_DOTS)
1486     {
1487         ast_expression *va;
1488         if (!OPTS_FLAG(VARIADIC_ARGS)) {
1489             parseerror(parser, "cannot access varargs (try -fvariadic-args)");
1490             return false;
1491         }
1492         va = parse_vararg(parser);
1493         if (!va)
1494             return false;
1495         vec_push(sy->out, syexp(parser_ctx(parser), va));
1496         return true;
1497     }
1498     else if (parser->tok == TOKEN_FLOATCONST) {
1499         ast_expression *val = fold_constgen_float(parser->fold, (parser_token(parser)->constval.f));
1500         if (!val)
1501             return false;
1502         vec_push(sy->out, syexp(parser_ctx(parser), val));
1503         return true;
1504     }
1505     else if (parser->tok == TOKEN_INTCONST || parser->tok == TOKEN_CHARCONST) {
1506         ast_expression *val = fold_constgen_float(parser->fold, (qcfloat_t)(parser_token(parser)->constval.i));
1507         if (!val)
1508             return false;
1509         vec_push(sy->out, syexp(parser_ctx(parser), val));
1510         return true;
1511     }
1512     else if (parser->tok == TOKEN_STRINGCONST) {
1513         ast_expression *val = fold_constgen_string(parser->fold, parser_tokval(parser), false);
1514         if (!val)
1515             return false;
1516         vec_push(sy->out, syexp(parser_ctx(parser), val));
1517         return true;
1518     }
1519     else if (parser->tok == TOKEN_VECTORCONST) {
1520         ast_expression *val = fold_constgen_vector(parser->fold, parser_token(parser)->constval.v);
1521         if (!val)
1522             return false;
1523         vec_push(sy->out, syexp(parser_ctx(parser), val));
1524         return true;
1525     }
1526     else if (parser->tok == TOKEN_IDENT)
1527     {
1528         const char     *ctoken = parser_tokval(parser);
1529         ast_expression *prev = vec_size(sy->out) ? vec_last(sy->out).out : NULL;
1530         ast_expression *var;
1531         /* a_vector.{x,y,z} */
1532         if (!vec_size(sy->ops) ||
1533             !vec_last(sy->ops).etype ||
1534             operators[vec_last(sy->ops).etype-1].id != opid1('.') ||
1535             (prev >= intrinsic_debug_typestring &&
1536              prev <= intrinsic_debug_typestring))
1537         {
1538             /* When adding more intrinsics, fix the above condition */
1539             prev = NULL;
1540         }
1541         if (prev && prev->vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
1542         {
1543             var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
1544         } else {
1545             var = parser_find_var(parser, parser_tokval(parser));
1546             if (!var)
1547                 var = parser_find_field(parser, parser_tokval(parser));
1548         }
1549         if (!var && with_labels) {
1550             var = (ast_expression*)parser_find_label(parser, parser_tokval(parser));
1551             if (!with_labels) {
1552                 ast_label *lbl = ast_label_new(parser_ctx(parser), parser_tokval(parser), true);
1553                 var = (ast_expression*)lbl;
1554                 vec_push(parser->labels, lbl);
1555             }
1556         }
1557         if (!var && !strcmp(parser_tokval(parser), "__FUNC__"))
1558             var = (ast_expression*)fold_constgen_string(parser->fold, parser->function->name, false);
1559         if (!var) {
1560             /* intrinsics */
1561             if (!strcmp(parser_tokval(parser), "__builtin_debug_typestring")) {
1562                 var = (ast_expression*)intrinsic_debug_typestring;
1563             }
1564             /* now we try for the real intrinsic hashtable. If the string
1565              * begins with __builtin, we simply skip past it, otherwise we
1566              * use the identifier as is.
1567              */
1568             else if (!strncmp(parser_tokval(parser), "__builtin_", 10)) {
1569                 var = intrin_func(parser, parser_tokval(parser) + 10 /* skip __builtin */);
1570             }
1571
1572             if (!var) {
1573                 char *correct = NULL;
1574                 size_t i;
1575
1576                 /*
1577                  * sometimes people use preprocessing predefs without enabling them
1578                  * i've done this thousands of times already myself.  Lets check for
1579                  * it in the predef table.  And diagnose it better :)
1580                  */
1581                 if (!OPTS_FLAG(FTEPP_PREDEFS) && ftepp_predef_exists(parser_tokval(parser))) {
1582                     parseerror(parser, "unexpected identifier: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
1583                     return false;
1584                 }
1585
1586                 /*
1587                  * TODO: determine the best score for the identifier: be it
1588                  * a variable, a field.
1589                  *
1590                  * We should also consider adding correction tables for
1591                  * other things as well.
1592                  */
1593                 if (OPTS_OPTION_BOOL(OPTION_CORRECTION) && strlen(parser_tokval(parser)) <= 16) {
1594                     correction_t corr;
1595                     correct_init(&corr);
1596
1597                     for (i = 0; i < vec_size(parser->correct_variables); i++) {
1598                         correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser));
1599                         if (strcmp(correct, parser_tokval(parser))) {
1600                             break;
1601                         } else  {
1602                             mem_d(correct);
1603                             correct = NULL;
1604                         }
1605                     }
1606                     correct_free(&corr);
1607
1608                     if (correct) {
1609                         parseerror(parser, "unexpected identifier: %s (did you mean %s?)", parser_tokval(parser), correct);
1610                         mem_d(correct);
1611                         return false;
1612                     }
1613                 }
1614                 parseerror(parser, "unexpected identifier: %s", parser_tokval(parser));
1615                 return false;
1616             }
1617         }
1618         else
1619         {
1620             if (ast_istype(var, ast_value)) {
1621                 ((ast_value*)var)->uses++;
1622             }
1623             else if (ast_istype(var, ast_member)) {
1624                 ast_member *mem = (ast_member*)var;
1625                 if (ast_istype(mem->owner, ast_value))
1626                     ((ast_value*)(mem->owner))->uses++;
1627             }
1628         }
1629         vec_push(sy->out, syexp(parser_ctx(parser), var));
1630         return true;
1631     }
1632     parseerror(parser, "unexpected token `%s`", parser_tokval(parser));
1633     return false;
1634 }
1635
1636 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels)
1637 {
1638     ast_expression *expr = NULL;
1639     shunt sy;
1640     size_t i;
1641     bool wantop = false;
1642     /* only warn once about an assignment in a truth value because the current code
1643      * would trigger twice on: if(a = b && ...), once for the if-truth-value, once for the && part
1644      */
1645     bool warn_truthvalue = true;
1646
1647     /* count the parens because an if starts with one, so the
1648      * end of a condition is an unmatched closing paren
1649      */
1650     int ternaries = 0;
1651
1652     memset(&sy, 0, sizeof(sy));
1653
1654     parser->lex->flags.noops = false;
1655
1656     parser_reclassify_token(parser);
1657
1658     while (true)
1659     {
1660         if (parser->tok == TOKEN_TYPENAME) {
1661             parseerror(parser, "unexpected typename `%s`", parser_tokval(parser));
1662             goto onerr;
1663         }
1664
1665         if (parser->tok == TOKEN_OPERATOR)
1666         {
1667             /* classify the operator */
1668             const oper_info *op;
1669             const oper_info *olast = NULL;
1670             size_t o;
1671             for (o = 0; o < operator_count; ++o) {
1672                 if (((!(operators[o].flags & OP_PREFIX) == !!wantop)) &&
1673                     /* !(operators[o].flags & OP_SUFFIX) && / * remove this */
1674                     !strcmp(parser_tokval(parser), operators[o].op))
1675                 {
1676                     break;
1677                 }
1678             }
1679             if (o == operator_count) {
1680                 compile_error(parser_ctx(parser), "unknown operator: %s", parser_tokval(parser));
1681                 goto onerr;
1682             }
1683             /* found an operator */
1684             op = &operators[o];
1685
1686             /* when declaring variables, a comma starts a new variable */
1687             if (op->id == opid1(',') && !vec_size(sy.paren) && stopatcomma) {
1688                 /* fixup the token */
1689                 parser->tok = ',';
1690                 break;
1691             }
1692
1693             /* a colon without a pervious question mark cannot be a ternary */
1694             if (!ternaries && op->id == opid2(':','?')) {
1695                 parser->tok = ':';
1696                 break;
1697             }
1698
1699             if (op->id == opid1(',')) {
1700                 if (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1701                     (void)!parsewarning(parser, WARN_TERNARY_PRECEDENCE, "suggesting parenthesis around ternary expression");
1702                 }
1703             }
1704
1705             if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
1706                 olast = &operators[vec_last(sy.ops).etype-1];
1707
1708 #define IsAssignOp(x) (\
1709                 (x) == opid1('=') || \
1710                 (x) == opid2('+','=') || \
1711                 (x) == opid2('-','=') || \
1712                 (x) == opid2('*','=') || \
1713                 (x) == opid2('/','=') || \
1714                 (x) == opid2('%','=') || \
1715                 (x) == opid2('&','=') || \
1716                 (x) == opid2('|','=') || \
1717                 (x) == opid3('&','~','=') \
1718                 )
1719             if (warn_truthvalue) {
1720                 if ( (olast && IsAssignOp(olast->id) && (op->id == opid2('&','&') || op->id == opid2('|','|'))) ||
1721                      (olast && IsAssignOp(op->id) && (olast->id == opid2('&','&') || olast->id == opid2('|','|'))) ||
1722                      (truthvalue && !vec_size(sy.paren) && IsAssignOp(op->id))
1723                    )
1724                 {
1725                     (void)!parsewarning(parser, WARN_PARENTHESIS, "suggesting parenthesis around assignment used as truth value");
1726                     warn_truthvalue = false;
1727                 }
1728             }
1729
1730             while (olast && (
1731                     (op->prec < olast->prec) ||
1732                     (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
1733             {
1734                 if (!parser_sy_apply_operator(parser, &sy))
1735                     goto onerr;
1736                 if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
1737                     olast = &operators[vec_last(sy.ops).etype-1];
1738                 else
1739                     olast = NULL;
1740             }
1741
1742             if (op->id == opid1('(')) {
1743                 if (wantop) {
1744                     size_t sycount = vec_size(sy.out);
1745                     /* we expected an operator, this is the function-call operator */
1746                     vec_push(sy.paren, PAREN_FUNC);
1747                     vec_push(sy.ops, syparen(parser_ctx(parser), sycount-1));
1748                     vec_push(sy.argc, 0);
1749                 } else {
1750                     vec_push(sy.paren, PAREN_EXPR);
1751                     vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1752                 }
1753                 wantop = false;
1754             } else if (op->id == opid1('[')) {
1755                 if (!wantop) {
1756                     parseerror(parser, "unexpected array subscript");
1757                     goto onerr;
1758                 }
1759                 vec_push(sy.paren, PAREN_INDEX);
1760                 /* push both the operator and the paren, this makes life easier */
1761                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1762                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1763                 wantop = false;
1764             } else if (op->id == opid2('?',':')) {
1765                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1766                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1767                 wantop = false;
1768                 ++ternaries;
1769                 vec_push(sy.paren, PAREN_TERNARY1);
1770             } else if (op->id == opid2(':','?')) {
1771                 if (!vec_size(sy.paren)) {
1772                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
1773                     goto onerr;
1774                 }
1775                 if (vec_last(sy.paren) != PAREN_TERNARY1) {
1776                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
1777                     goto onerr;
1778                 }
1779                 if (!parser_close_paren(parser, &sy))
1780                     goto onerr;
1781                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1782                 wantop = false;
1783                 --ternaries;
1784             } else {
1785                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1786                 wantop = !!(op->flags & OP_SUFFIX);
1787             }
1788         }
1789         else if (parser->tok == ')') {
1790             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1791                 if (!parser_sy_apply_operator(parser, &sy))
1792                     goto onerr;
1793             }
1794             if (!vec_size(sy.paren))
1795                 break;
1796             if (wantop) {
1797                 if (vec_last(sy.paren) == PAREN_TERNARY1) {
1798                     parseerror(parser, "mismatched parentheses (closing paren in ternary expression?)");
1799                     goto onerr;
1800                 }
1801                 if (!parser_close_paren(parser, &sy))
1802                     goto onerr;
1803             } else {
1804                 /* must be a function call without parameters */
1805                 if (vec_last(sy.paren) != PAREN_FUNC) {
1806                     parseerror(parser, "closing paren in invalid position");
1807                     goto onerr;
1808                 }
1809                 if (!parser_close_paren(parser, &sy))
1810                     goto onerr;
1811             }
1812             wantop = true;
1813         }
1814         else if (parser->tok == '(') {
1815             parseerror(parser, "internal error: '(' should be classified as operator");
1816             goto onerr;
1817         }
1818         else if (parser->tok == '[') {
1819             parseerror(parser, "internal error: '[' should be classified as operator");
1820             goto onerr;
1821         }
1822         else if (parser->tok == ']') {
1823             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1824                 if (!parser_sy_apply_operator(parser, &sy))
1825                     goto onerr;
1826             }
1827             if (!vec_size(sy.paren))
1828                 break;
1829             if (vec_last(sy.paren) != PAREN_INDEX) {
1830                 parseerror(parser, "mismatched parentheses, unexpected ']'");
1831                 goto onerr;
1832             }
1833             if (!parser_close_paren(parser, &sy))
1834                 goto onerr;
1835             wantop = true;
1836         }
1837         else if (!wantop) {
1838             if (!parse_sya_operand(parser, &sy, with_labels))
1839                 goto onerr;
1840 #if 0
1841             if (vec_size(sy.paren) && vec_last(sy.ops).isparen && vec_last(sy.paren) == PAREN_FUNC)
1842                 vec_last(sy.argc)++;
1843 #endif
1844             wantop = true;
1845         }
1846         else {
1847             /* in this case we might want to allow constant string concatenation */
1848             bool concatenated = false;
1849             if (parser->tok == TOKEN_STRINGCONST && vec_size(sy.out)) {
1850                 ast_expression *lexpr = vec_last(sy.out).out;
1851                 if (ast_istype(lexpr, ast_value)) {
1852                     ast_value *last = (ast_value*)lexpr;
1853                     if (last->isimm == true && last->cvq == CV_CONST &&
1854                         last->hasvalue && last->expression.vtype == TYPE_STRING)
1855                     {
1856                         char *newstr = NULL;
1857                         util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser));
1858                         vec_last(sy.out).out = (ast_expression*)fold_constgen_string(parser->fold, newstr, false);
1859                         mem_d(newstr);
1860                         concatenated = true;
1861                     }
1862                 }
1863             }
1864             if (!concatenated) {
1865                 parseerror(parser, "expected operator or end of statement");
1866                 goto onerr;
1867             }
1868         }
1869
1870         if (!parser_next(parser)) {
1871             goto onerr;
1872         }
1873         if (parser->tok == ';' ||
1874             ((!vec_size(sy.paren) || (vec_size(sy.paren) == 1 && vec_last(sy.paren) == PAREN_TERNARY2)) &&
1875             (parser->tok == ']' || parser->tok == ')' || parser->tok == '}')))
1876         {
1877             break;
1878         }
1879     }
1880
1881     while (vec_size(sy.ops)) {
1882         if (!parser_sy_apply_operator(parser, &sy))
1883             goto onerr;
1884     }
1885
1886     parser->lex->flags.noops = true;
1887     if (vec_size(sy.out) != 1) {
1888         parseerror(parser, "expression with not 1 but %lu output values...", (unsigned long) vec_size(sy.out));
1889         expr = NULL;
1890     } else
1891         expr = sy.out[0].out;
1892     vec_free(sy.out);
1893     vec_free(sy.ops);
1894     if (vec_size(sy.paren)) {
1895         parseerror(parser, "internal error: vec_size(sy.paren) = %lu", (unsigned long)vec_size(sy.paren));
1896         return NULL;
1897     }
1898     vec_free(sy.paren);
1899     vec_free(sy.argc);
1900     return expr;
1901
1902 onerr:
1903     parser->lex->flags.noops = true;
1904     for (i = 0; i < vec_size(sy.out); ++i) {
1905         if (sy.out[i].out)
1906             ast_unref(sy.out[i].out);
1907     }
1908     vec_free(sy.out);
1909     vec_free(sy.ops);
1910     vec_free(sy.paren);
1911     vec_free(sy.argc);
1912     return NULL;
1913 }
1914
1915 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels)
1916 {
1917     ast_expression *e = parse_expression_leave(parser, stopatcomma, false, with_labels);
1918     if (!e)
1919         return NULL;
1920     if (parser->tok != ';') {
1921         parseerror(parser, "semicolon expected after expression");
1922         ast_unref(e);
1923         return NULL;
1924     }
1925     if (!parser_next(parser)) {
1926         ast_unref(e);
1927         return NULL;
1928     }
1929     return e;
1930 }
1931
1932 static void parser_enterblock(parser_t *parser)
1933 {
1934     vec_push(parser->variables, util_htnew(PARSER_HT_SIZE));
1935     vec_push(parser->_blocklocals, vec_size(parser->_locals));
1936     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
1937     vec_push(parser->_blocktypedefs, vec_size(parser->_typedefs));
1938     vec_push(parser->_block_ctx, parser_ctx(parser));
1939
1940     /* corrector */
1941     vec_push(parser->correct_variables, correct_trie_new());
1942     vec_push(parser->correct_variables_score, NULL);
1943 }
1944
1945 static bool parser_leaveblock(parser_t *parser)
1946 {
1947     bool   rv = true;
1948     size_t locals, typedefs;
1949
1950     if (vec_size(parser->variables) <= PARSER_HT_LOCALS) {
1951         parseerror(parser, "internal error: parser_leaveblock with no block");
1952         return false;
1953     }
1954
1955     util_htdel(vec_last(parser->variables));
1956     correct_del(vec_last(parser->correct_variables), vec_last(parser->correct_variables_score));
1957
1958     vec_pop(parser->variables);
1959     vec_pop(parser->correct_variables);
1960     vec_pop(parser->correct_variables_score);
1961     if (!vec_size(parser->_blocklocals)) {
1962         parseerror(parser, "internal error: parser_leaveblock with no block (2)");
1963         return false;
1964     }
1965
1966     locals = vec_last(parser->_blocklocals);
1967     vec_pop(parser->_blocklocals);
1968     while (vec_size(parser->_locals) != locals) {
1969         ast_expression *e = vec_last(parser->_locals);
1970         ast_value      *v = (ast_value*)e;
1971         vec_pop(parser->_locals);
1972         if (ast_istype(e, ast_value) && !v->uses) {
1973             if (compile_warning(ast_ctx(v), WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name))
1974                 rv = false;
1975         }
1976     }
1977
1978     typedefs = vec_last(parser->_blocktypedefs);
1979     while (vec_size(parser->_typedefs) != typedefs) {
1980         ast_delete(vec_last(parser->_typedefs));
1981         vec_pop(parser->_typedefs);
1982     }
1983     util_htdel(vec_last(parser->typedefs));
1984     vec_pop(parser->typedefs);
1985
1986     vec_pop(parser->_block_ctx);
1987
1988     return rv;
1989 }
1990
1991 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e)
1992 {
1993     vec_push(parser->_locals, e);
1994     util_htset(vec_last(parser->variables), name, (void*)e);
1995
1996     /* corrector */
1997     correct_add (
1998          vec_last(parser->correct_variables),
1999         &vec_last(parser->correct_variables_score),
2000         name
2001     );
2002 }
2003
2004 static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e)
2005 {
2006     vec_push(parser->globals, e);
2007     util_htset(parser->htglobals, name, e);
2008
2009     /* corrector */
2010     correct_add (
2011          parser->correct_variables[0],
2012         &parser->correct_variables_score[0],
2013         name
2014     );
2015 }
2016
2017 static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
2018 {
2019     bool       ifnot = false;
2020     ast_unary *unary;
2021     ast_expression *prev;
2022
2023     if (cond->vtype == TYPE_VOID || cond->vtype >= TYPE_VARIANT) {
2024         char ty[1024];
2025         ast_type_to_string(cond, ty, sizeof(ty));
2026         compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty);
2027     }
2028
2029     if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->vtype == TYPE_STRING)
2030     {
2031         prev = cond;
2032         cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
2033         if (!cond) {
2034             ast_unref(prev);
2035             parseerror(parser, "internal error: failed to process condition");
2036             return NULL;
2037         }
2038         ifnot = !ifnot;
2039     }
2040     else if (OPTS_FLAG(CORRECT_LOGIC) && cond->vtype == TYPE_VECTOR)
2041     {
2042         /* vector types need to be cast to true booleans */
2043         ast_binary *bin = (ast_binary*)cond;
2044         if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR))
2045         {
2046             /* in perl-logic, AND and OR take care of the -fcorrect-logic */
2047             prev = cond;
2048             cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond);
2049             if (!cond) {
2050                 ast_unref(prev);
2051                 parseerror(parser, "internal error: failed to process condition");
2052                 return NULL;
2053             }
2054             ifnot = !ifnot;
2055         }
2056     }
2057
2058     unary = (ast_unary*)cond;
2059     /* ast_istype dereferences cond, should test here for safety */
2060     while (cond && ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F)
2061     {
2062         cond = unary->operand;
2063         unary->operand = NULL;
2064         ast_delete(unary);
2065         ifnot = !ifnot;
2066         unary = (ast_unary*)cond;
2067     }
2068
2069     if (!cond)
2070         parseerror(parser, "internal error: failed to process condition");
2071
2072     if (ifnot) *_ifnot = !*_ifnot;
2073     return cond;
2074 }
2075
2076 static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
2077 {
2078     ast_ifthen *ifthen;
2079     ast_expression *cond, *ontrue = NULL, *onfalse = NULL;
2080     bool ifnot = false;
2081
2082     lex_ctx_t ctx = parser_ctx(parser);
2083
2084     (void)block; /* not touching */
2085
2086     /* skip the 'if', parse an optional 'not' and check for an opening paren */
2087     if (!parser_next(parser)) {
2088         parseerror(parser, "expected condition or 'not'");
2089         return false;
2090     }
2091     if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "not")) {
2092         ifnot = true;
2093         if (!parser_next(parser)) {
2094             parseerror(parser, "expected condition in parenthesis");
2095             return false;
2096         }
2097     }
2098     if (parser->tok != '(') {
2099         parseerror(parser, "expected 'if' condition in parenthesis");
2100         return false;
2101     }
2102     /* parse into the expression */
2103     if (!parser_next(parser)) {
2104         parseerror(parser, "expected 'if' condition after opening paren");
2105         return false;
2106     }
2107     /* parse the condition */
2108     cond = parse_expression_leave(parser, false, true, false);
2109     if (!cond)
2110         return false;
2111     /* closing paren */
2112     if (parser->tok != ')') {
2113         parseerror(parser, "expected closing paren after 'if' condition");
2114         ast_unref(cond);
2115         return false;
2116     }
2117     /* parse into the 'then' branch */
2118     if (!parser_next(parser)) {
2119         parseerror(parser, "expected statement for on-true branch of 'if'");
2120         ast_unref(cond);
2121         return false;
2122     }
2123     if (!parse_statement_or_block(parser, &ontrue)) {
2124         ast_unref(cond);
2125         return false;
2126     }
2127     if (!ontrue)
2128         ontrue = (ast_expression*)ast_block_new(parser_ctx(parser));
2129     /* check for an else */
2130     if (!strcmp(parser_tokval(parser), "else")) {
2131         /* parse into the 'else' branch */
2132         if (!parser_next(parser)) {
2133             parseerror(parser, "expected on-false branch after 'else'");
2134             ast_delete(ontrue);
2135             ast_unref(cond);
2136             return false;
2137         }
2138         if (!parse_statement_or_block(parser, &onfalse)) {
2139             ast_delete(ontrue);
2140             ast_unref(cond);
2141             return false;
2142         }
2143     }
2144
2145     cond = process_condition(parser, cond, &ifnot);
2146     if (!cond) {
2147         if (ontrue)  ast_delete(ontrue);
2148         if (onfalse) ast_delete(onfalse);
2149         return false;
2150     }
2151
2152     if (ifnot)
2153         ifthen = ast_ifthen_new(ctx, cond, onfalse, ontrue);
2154     else
2155         ifthen = ast_ifthen_new(ctx, cond, ontrue, onfalse);
2156     *out = (ast_expression*)ifthen;
2157     return true;
2158 }
2159
2160 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out);
2161 static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out)
2162 {
2163     bool rv;
2164     char *label = NULL;
2165
2166     /* skip the 'while' and get the body */
2167     if (!parser_next(parser)) {
2168         if (OPTS_FLAG(LOOP_LABELS))
2169             parseerror(parser, "expected loop label or 'while' condition in parenthesis");
2170         else
2171             parseerror(parser, "expected 'while' condition in parenthesis");
2172         return false;
2173     }
2174
2175     if (parser->tok == ':') {
2176         if (!OPTS_FLAG(LOOP_LABELS))
2177             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2178         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2179             parseerror(parser, "expected loop label");
2180             return false;
2181         }
2182         label = util_strdup(parser_tokval(parser));
2183         if (!parser_next(parser)) {
2184             mem_d(label);
2185             parseerror(parser, "expected 'while' condition in parenthesis");
2186             return false;
2187         }
2188     }
2189
2190     if (parser->tok != '(') {
2191         parseerror(parser, "expected 'while' condition in parenthesis");
2192         return false;
2193     }
2194
2195     vec_push(parser->breaks, label);
2196     vec_push(parser->continues, label);
2197
2198     rv = parse_while_go(parser, block, out);
2199     if (label)
2200         mem_d(label);
2201     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2202         parseerror(parser, "internal error: label stack corrupted");
2203         rv = false;
2204         ast_delete(*out);
2205         *out = NULL;
2206     }
2207     else {
2208         vec_pop(parser->breaks);
2209         vec_pop(parser->continues);
2210     }
2211     return rv;
2212 }
2213
2214 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out)
2215 {
2216     ast_loop *aloop;
2217     ast_expression *cond, *ontrue;
2218
2219     bool ifnot = false;
2220
2221     lex_ctx_t ctx = parser_ctx(parser);
2222
2223     (void)block; /* not touching */
2224
2225     /* parse into the expression */
2226     if (!parser_next(parser)) {
2227         parseerror(parser, "expected 'while' condition after opening paren");
2228         return false;
2229     }
2230     /* parse the condition */
2231     cond = parse_expression_leave(parser, false, true, false);
2232     if (!cond)
2233         return false;
2234     /* closing paren */
2235     if (parser->tok != ')') {
2236         parseerror(parser, "expected closing paren after 'while' condition");
2237         ast_unref(cond);
2238         return false;
2239     }
2240     /* parse into the 'then' branch */
2241     if (!parser_next(parser)) {
2242         parseerror(parser, "expected while-loop body");
2243         ast_unref(cond);
2244         return false;
2245     }
2246     if (!parse_statement_or_block(parser, &ontrue)) {
2247         ast_unref(cond);
2248         return false;
2249     }
2250
2251     cond = process_condition(parser, cond, &ifnot);
2252     if (!cond) {
2253         ast_unref(ontrue);
2254         return false;
2255     }
2256     aloop = ast_loop_new(ctx, NULL, cond, ifnot, NULL, false, NULL, ontrue);
2257     *out = (ast_expression*)aloop;
2258     return true;
2259 }
2260
2261 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out);
2262 static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **out)
2263 {
2264     bool rv;
2265     char *label = NULL;
2266
2267     /* skip the 'do' and get the body */
2268     if (!parser_next(parser)) {
2269         if (OPTS_FLAG(LOOP_LABELS))
2270             parseerror(parser, "expected loop label or body");
2271         else
2272             parseerror(parser, "expected loop body");
2273         return false;
2274     }
2275
2276     if (parser->tok == ':') {
2277         if (!OPTS_FLAG(LOOP_LABELS))
2278             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2279         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2280             parseerror(parser, "expected loop label");
2281             return false;
2282         }
2283         label = util_strdup(parser_tokval(parser));
2284         if (!parser_next(parser)) {
2285             mem_d(label);
2286             parseerror(parser, "expected loop body");
2287             return false;
2288         }
2289     }
2290
2291     vec_push(parser->breaks, label);
2292     vec_push(parser->continues, label);
2293
2294     rv = parse_dowhile_go(parser, block, out);
2295     if (label)
2296         mem_d(label);
2297     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2298         parseerror(parser, "internal error: label stack corrupted");
2299         rv = false;
2300         /*
2301          * Test for NULL otherwise ast_delete dereferences null pointer
2302          * and boom.
2303          */
2304         if (*out)
2305             ast_delete(*out);
2306         *out = NULL;
2307     }
2308     else {
2309         vec_pop(parser->breaks);
2310         vec_pop(parser->continues);
2311     }
2312     return rv;
2313 }
2314
2315 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out)
2316 {
2317     ast_loop *aloop;
2318     ast_expression *cond, *ontrue;
2319
2320     bool ifnot = false;
2321
2322     lex_ctx_t ctx = parser_ctx(parser);
2323
2324     (void)block; /* not touching */
2325
2326     if (!parse_statement_or_block(parser, &ontrue))
2327         return false;
2328
2329     /* expect the "while" */
2330     if (parser->tok != TOKEN_KEYWORD ||
2331         strcmp(parser_tokval(parser), "while"))
2332     {
2333         parseerror(parser, "expected 'while' and condition");
2334         ast_delete(ontrue);
2335         return false;
2336     }
2337
2338     /* skip the 'while' and check for opening paren */
2339     if (!parser_next(parser) || parser->tok != '(') {
2340         parseerror(parser, "expected 'while' condition in parenthesis");
2341         ast_delete(ontrue);
2342         return false;
2343     }
2344     /* parse into the expression */
2345     if (!parser_next(parser)) {
2346         parseerror(parser, "expected 'while' condition after opening paren");
2347         ast_delete(ontrue);
2348         return false;
2349     }
2350     /* parse the condition */
2351     cond = parse_expression_leave(parser, false, true, false);
2352     if (!cond)
2353         return false;
2354     /* closing paren */
2355     if (parser->tok != ')') {
2356         parseerror(parser, "expected closing paren after 'while' condition");
2357         ast_delete(ontrue);
2358         ast_unref(cond);
2359         return false;
2360     }
2361     /* parse on */
2362     if (!parser_next(parser) || parser->tok != ';') {
2363         parseerror(parser, "expected semicolon after condition");
2364         ast_delete(ontrue);
2365         ast_unref(cond);
2366         return false;
2367     }
2368
2369     if (!parser_next(parser)) {
2370         parseerror(parser, "parse error");
2371         ast_delete(ontrue);
2372         ast_unref(cond);
2373         return false;
2374     }
2375
2376     cond = process_condition(parser, cond, &ifnot);
2377     if (!cond) {
2378         ast_delete(ontrue);
2379         return false;
2380     }
2381     aloop = ast_loop_new(ctx, NULL, NULL, false, cond, ifnot, NULL, ontrue);
2382     *out = (ast_expression*)aloop;
2383     return true;
2384 }
2385
2386 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out);
2387 static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
2388 {
2389     bool rv;
2390     char *label = NULL;
2391
2392     /* skip the 'for' and check for opening paren */
2393     if (!parser_next(parser)) {
2394         if (OPTS_FLAG(LOOP_LABELS))
2395             parseerror(parser, "expected loop label or 'for' expressions in parenthesis");
2396         else
2397             parseerror(parser, "expected 'for' expressions in parenthesis");
2398         return false;
2399     }
2400
2401     if (parser->tok == ':') {
2402         if (!OPTS_FLAG(LOOP_LABELS))
2403             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2404         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2405             parseerror(parser, "expected loop label");
2406             return false;
2407         }
2408         label = util_strdup(parser_tokval(parser));
2409         if (!parser_next(parser)) {
2410             mem_d(label);
2411             parseerror(parser, "expected 'for' expressions in parenthesis");
2412             return false;
2413         }
2414     }
2415
2416     if (parser->tok != '(') {
2417         parseerror(parser, "expected 'for' expressions in parenthesis");
2418         return false;
2419     }
2420
2421     vec_push(parser->breaks, label);
2422     vec_push(parser->continues, label);
2423
2424     rv = parse_for_go(parser, block, out);
2425     if (label)
2426         mem_d(label);
2427     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2428         parseerror(parser, "internal error: label stack corrupted");
2429         rv = false;
2430         ast_delete(*out);
2431         *out = NULL;
2432     }
2433     else {
2434         vec_pop(parser->breaks);
2435         vec_pop(parser->continues);
2436     }
2437     return rv;
2438 }
2439 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out)
2440 {
2441     ast_loop       *aloop;
2442     ast_expression *initexpr, *cond, *increment, *ontrue;
2443     ast_value      *typevar;
2444
2445     bool ifnot  = false;
2446
2447     lex_ctx_t ctx = parser_ctx(parser);
2448
2449     parser_enterblock(parser);
2450
2451     initexpr  = NULL;
2452     cond      = NULL;
2453     increment = NULL;
2454     ontrue    = NULL;
2455
2456     /* parse into the expression */
2457     if (!parser_next(parser)) {
2458         parseerror(parser, "expected 'for' initializer after opening paren");
2459         goto onerr;
2460     }
2461
2462     typevar = NULL;
2463     if (parser->tok == TOKEN_IDENT)
2464         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
2465
2466     if (typevar || parser->tok == TOKEN_TYPENAME) {
2467 #if 0
2468         if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
2469             if (parsewarning(parser, WARN_EXTENSIONS,
2470                              "current standard does not allow variable declarations in for-loop initializers"))
2471                 goto onerr;
2472         }
2473 #endif
2474         if (!parse_variable(parser, block, true, CV_VAR, typevar, false, false, 0, NULL))
2475             goto onerr;
2476     }
2477     else if (parser->tok != ';')
2478     {
2479         initexpr = parse_expression_leave(parser, false, false, false);
2480         if (!initexpr)
2481             goto onerr;
2482     }
2483
2484     /* move on to condition */
2485     if (parser->tok != ';') {
2486         parseerror(parser, "expected semicolon after for-loop initializer");
2487         goto onerr;
2488     }
2489     if (!parser_next(parser)) {
2490         parseerror(parser, "expected for-loop condition");
2491         goto onerr;
2492     }
2493
2494     /* parse the condition */
2495     if (parser->tok != ';') {
2496         cond = parse_expression_leave(parser, false, true, false);
2497         if (!cond)
2498             goto onerr;
2499     }
2500
2501     /* move on to incrementor */
2502     if (parser->tok != ';') {
2503         parseerror(parser, "expected semicolon after for-loop initializer");
2504         goto onerr;
2505     }
2506     if (!parser_next(parser)) {
2507         parseerror(parser, "expected for-loop condition");
2508         goto onerr;
2509     }
2510
2511     /* parse the incrementor */
2512     if (parser->tok != ')') {
2513         lex_ctx_t condctx = parser_ctx(parser);
2514         increment = parse_expression_leave(parser, false, false, false);
2515         if (!increment)
2516             goto onerr;
2517         if (!ast_side_effects(increment)) {
2518             if (compile_warning(condctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
2519                 goto onerr;
2520         }
2521     }
2522
2523     /* closing paren */
2524     if (parser->tok != ')') {
2525         parseerror(parser, "expected closing paren after 'for-loop' incrementor");
2526         goto onerr;
2527     }
2528     /* parse into the 'then' branch */
2529     if (!parser_next(parser)) {
2530         parseerror(parser, "expected for-loop body");
2531         goto onerr;
2532     }
2533     if (!parse_statement_or_block(parser, &ontrue))
2534         goto onerr;
2535
2536     if (cond) {
2537         cond = process_condition(parser, cond, &ifnot);
2538         if (!cond)
2539             goto onerr;
2540     }
2541     aloop = ast_loop_new(ctx, initexpr, cond, ifnot, NULL, false, increment, ontrue);
2542     *out = (ast_expression*)aloop;
2543
2544     if (!parser_leaveblock(parser)) {
2545         ast_delete(aloop);
2546         return false;
2547     }
2548     return true;
2549 onerr:
2550     if (initexpr)  ast_unref(initexpr);
2551     if (cond)      ast_unref(cond);
2552     if (increment) ast_unref(increment);
2553     (void)!parser_leaveblock(parser);
2554     return false;
2555 }
2556
2557 static bool parse_return(parser_t *parser, ast_block *block, ast_expression **out)
2558 {
2559     ast_expression *exp      = NULL;
2560     ast_expression *var      = NULL;
2561     ast_return     *ret      = NULL;
2562     ast_value      *retval   = parser->function->return_value;
2563     ast_value      *expected = parser->function->vtype;
2564
2565     lex_ctx_t ctx = parser_ctx(parser);
2566
2567     (void)block; /* not touching */
2568
2569     if (!parser_next(parser)) {
2570         parseerror(parser, "expected return expression");
2571         return false;
2572     }
2573
2574     /* return assignments */
2575     if (parser->tok == '=') {
2576         if (!OPTS_FLAG(RETURN_ASSIGNMENTS)) {
2577             parseerror(parser, "return assignments not activated, try using -freturn-assigments");
2578             return false;
2579         }
2580
2581         if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) {
2582             char ty1[1024];
2583             ast_type_to_string(expected->expression.next, ty1, sizeof(ty1));
2584             parseerror(parser, "invalid return type: `%s'", ty1);
2585             return false;
2586         }
2587
2588         if (!parser_next(parser)) {
2589             parseerror(parser, "expected return assignment expression");
2590             return false;
2591         }
2592
2593         if (!(exp = parse_expression_leave(parser, false, false, false)))
2594             return false;
2595
2596         /* prepare the return value */
2597         if (!retval) {
2598             retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID);
2599             ast_type_adopt(retval, expected->expression.next);
2600             parser->function->return_value = retval;
2601         }
2602
2603         if (!ast_compare_type(exp, (ast_expression*)retval)) {
2604             char ty1[1024], ty2[1024];
2605             ast_type_to_string(exp, ty1, sizeof(ty1));
2606             ast_type_to_string(&retval->expression, ty2, sizeof(ty2));
2607             parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2);
2608         }
2609
2610         /* store to 'return' local variable */
2611         var = (ast_expression*)ast_store_new(
2612             ctx,
2613             type_store_instr[expected->expression.next->vtype],
2614             (ast_expression*)retval, exp);
2615
2616         if (!var) {
2617             ast_unref(exp);
2618             return false;
2619         }
2620
2621         if (parser->tok != ';')
2622             parseerror(parser, "missing semicolon after return assignment");
2623         else if (!parser_next(parser))
2624             parseerror(parser, "parse error after return assignment");
2625
2626         *out = var;
2627         return true;
2628     }
2629
2630     if (parser->tok != ';') {
2631         exp = parse_expression(parser, false, false);
2632         if (!exp)
2633             return false;
2634
2635         if (exp->vtype != TYPE_NIL &&
2636             exp->vtype != ((ast_expression*)expected)->next->vtype)
2637         {
2638             parseerror(parser, "return with invalid expression");
2639         }
2640
2641         ret = ast_return_new(ctx, exp);
2642         if (!ret) {
2643             ast_unref(exp);
2644             return false;
2645         }
2646     } else {
2647         if (!parser_next(parser))
2648             parseerror(parser, "parse error");
2649
2650         if (!retval && expected->expression.next->vtype != TYPE_VOID)
2651         {
2652             (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
2653         }
2654         ret = ast_return_new(ctx, (ast_expression*)retval);
2655     }
2656     *out = (ast_expression*)ret;
2657     return true;
2658 }
2659
2660 static bool parse_break_continue(parser_t *parser, ast_block *block, ast_expression **out, bool is_continue)
2661 {
2662     size_t       i;
2663     unsigned int levels = 0;
2664     lex_ctx_t      ctx = parser_ctx(parser);
2665     const char **loops = (is_continue ? parser->continues : parser->breaks);
2666
2667     (void)block; /* not touching */
2668     if (!parser_next(parser)) {
2669         parseerror(parser, "expected semicolon or loop label");
2670         return false;
2671     }
2672
2673     if (!vec_size(loops)) {
2674         if (is_continue)
2675             parseerror(parser, "`continue` can only be used inside loops");
2676         else
2677             parseerror(parser, "`break` can only be used inside loops or switches");
2678     }
2679
2680     if (parser->tok == TOKEN_IDENT) {
2681         if (!OPTS_FLAG(LOOP_LABELS))
2682             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2683         i = vec_size(loops);
2684         while (i--) {
2685             if (loops[i] && !strcmp(loops[i], parser_tokval(parser)))
2686                 break;
2687             if (!i) {
2688                 parseerror(parser, "no such loop to %s: `%s`",
2689                            (is_continue ? "continue" : "break out of"),
2690                            parser_tokval(parser));
2691                 return false;
2692             }
2693             ++levels;
2694         }
2695         if (!parser_next(parser)) {
2696             parseerror(parser, "expected semicolon");
2697             return false;
2698         }
2699     }
2700
2701     if (parser->tok != ';') {
2702         parseerror(parser, "expected semicolon");
2703         return false;
2704     }
2705
2706     if (!parser_next(parser))
2707         parseerror(parser, "parse error");
2708
2709     *out = (ast_expression*)ast_breakcont_new(ctx, is_continue, levels);
2710     return true;
2711 }
2712
2713 /* returns true when it was a variable qualifier, false otherwise!
2714  * on error, cvq is set to CV_WRONG
2715  */
2716 static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *noref, bool *is_static, uint32_t *_flags, char **message)
2717 {
2718     bool had_const    = false;
2719     bool had_var      = false;
2720     bool had_noref    = false;
2721     bool had_attrib   = false;
2722     bool had_static   = false;
2723     uint32_t flags    = 0;
2724
2725     *cvq = CV_NONE;
2726     for (;;) {
2727         if (parser->tok == TOKEN_ATTRIBUTE_OPEN) {
2728             had_attrib = true;
2729             /* parse an attribute */
2730             if (!parser_next(parser)) {
2731                 parseerror(parser, "expected attribute after `[[`");
2732                 *cvq = CV_WRONG;
2733                 return false;
2734             }
2735             if (!strcmp(parser_tokval(parser), "noreturn")) {
2736                 flags |= AST_FLAG_NORETURN;
2737                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2738                     parseerror(parser, "`noreturn` attribute has no parameters, expected `]]`");
2739                     *cvq = CV_WRONG;
2740                     return false;
2741                 }
2742             }
2743             else if (!strcmp(parser_tokval(parser), "noref")) {
2744                 had_noref = true;
2745                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2746                     parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
2747                     *cvq = CV_WRONG;
2748                     return false;
2749                 }
2750             }
2751             else if (!strcmp(parser_tokval(parser), "inline")) {
2752                 flags |= AST_FLAG_INLINE;
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), "alias") && !(flags & AST_FLAG_ALIAS)) {
2760                 flags   |= AST_FLAG_ALIAS;
2761                 *message = NULL;
2762
2763                 if (!parser_next(parser)) {
2764                     parseerror(parser, "parse error in attribute");
2765                     goto argerr;
2766                 }
2767
2768                 if (parser->tok == '(') {
2769                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2770                         parseerror(parser, "`alias` attribute missing parameter");
2771                         goto argerr;
2772                     }
2773
2774                     *message = util_strdup(parser_tokval(parser));
2775
2776                     if (!parser_next(parser)) {
2777                         parseerror(parser, "parse error in attribute");
2778                         goto argerr;
2779                     }
2780
2781                     if (parser->tok != ')') {
2782                         parseerror(parser, "`alias` attribute expected `)` after parameter");
2783                         goto argerr;
2784                     }
2785
2786                     if (!parser_next(parser)) {
2787                         parseerror(parser, "parse error in attribute");
2788                         goto argerr;
2789                     }
2790                 }
2791
2792                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2793                     parseerror(parser, "`alias` attribute expected `]]`");
2794                     goto argerr;
2795                 }
2796             }
2797             else if (!strcmp(parser_tokval(parser), "deprecated") && !(flags & AST_FLAG_DEPRECATED)) {
2798                 flags   |= AST_FLAG_DEPRECATED;
2799                 *message = NULL;
2800
2801                 if (!parser_next(parser)) {
2802                     parseerror(parser, "parse error in attribute");
2803                     goto argerr;
2804                 }
2805
2806                 if (parser->tok == '(') {
2807                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2808                         parseerror(parser, "`deprecated` attribute missing parameter");
2809                         goto argerr;
2810                     }
2811
2812                     *message = util_strdup(parser_tokval(parser));
2813
2814                     if (!parser_next(parser)) {
2815                         parseerror(parser, "parse error in attribute");
2816                         goto argerr;
2817                     }
2818
2819                     if(parser->tok != ')') {
2820                         parseerror(parser, "`deprecated` attribute expected `)` after parameter");
2821                         goto argerr;
2822                     }
2823
2824                     if (!parser_next(parser)) {
2825                         parseerror(parser, "parse error in attribute");
2826                         goto argerr;
2827                     }
2828                 }
2829                 /* no message */
2830                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2831                     parseerror(parser, "`deprecated` attribute expected `]]`");
2832
2833                     argerr: /* ugly */
2834                     if (*message) mem_d(*message);
2835                     *message = NULL;
2836                     *cvq     = CV_WRONG;
2837                     return false;
2838                 }
2839             }
2840             else
2841             {
2842                 /* Skip tokens until we hit a ]] */
2843                 (void)!parsewarning(parser, WARN_UNKNOWN_ATTRIBUTE, "unknown attribute starting with `%s`", parser_tokval(parser));
2844                 while (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2845                     if (!parser_next(parser)) {
2846                         parseerror(parser, "error inside attribute");
2847                         *cvq = CV_WRONG;
2848                         return false;
2849                     }
2850                 }
2851             }
2852         }
2853         else if (with_local && !strcmp(parser_tokval(parser), "static"))
2854             had_static = true;
2855         else if (!strcmp(parser_tokval(parser), "const"))
2856             had_const = true;
2857         else if (!strcmp(parser_tokval(parser), "var"))
2858             had_var = true;
2859         else if (with_local && !strcmp(parser_tokval(parser), "local"))
2860             had_var = true;
2861         else if (!strcmp(parser_tokval(parser), "noref"))
2862             had_noref = true;
2863         else if (!had_const && !had_var && !had_noref && !had_attrib && !had_static && !flags) {
2864             return false;
2865         }
2866         else
2867             break;
2868         if (!parser_next(parser))
2869             goto onerr;
2870     }
2871     if (had_const)
2872         *cvq = CV_CONST;
2873     else if (had_var)
2874         *cvq = CV_VAR;
2875     else
2876         *cvq = CV_NONE;
2877     *noref     = had_noref;
2878     *is_static = had_static;
2879     *_flags    = flags;
2880     return true;
2881 onerr:
2882     parseerror(parser, "parse error after variable qualifier");
2883     *cvq = CV_WRONG;
2884     return true;
2885 }
2886
2887 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out);
2888 static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **out)
2889 {
2890     bool rv;
2891     char *label = NULL;
2892
2893     /* skip the 'while' and get the body */
2894     if (!parser_next(parser)) {
2895         if (OPTS_FLAG(LOOP_LABELS))
2896             parseerror(parser, "expected loop label or 'switch' operand in parenthesis");
2897         else
2898             parseerror(parser, "expected 'switch' operand in parenthesis");
2899         return false;
2900     }
2901
2902     if (parser->tok == ':') {
2903         if (!OPTS_FLAG(LOOP_LABELS))
2904             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2905         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2906             parseerror(parser, "expected loop label");
2907             return false;
2908         }
2909         label = util_strdup(parser_tokval(parser));
2910         if (!parser_next(parser)) {
2911             mem_d(label);
2912             parseerror(parser, "expected 'switch' operand in parenthesis");
2913             return false;
2914         }
2915     }
2916
2917     if (parser->tok != '(') {
2918         parseerror(parser, "expected 'switch' operand in parenthesis");
2919         return false;
2920     }
2921
2922     vec_push(parser->breaks, label);
2923
2924     rv = parse_switch_go(parser, block, out);
2925     if (label)
2926         mem_d(label);
2927     if (vec_last(parser->breaks) != label) {
2928         parseerror(parser, "internal error: label stack corrupted");
2929         rv = false;
2930         ast_delete(*out);
2931         *out = NULL;
2932     }
2933     else {
2934         vec_pop(parser->breaks);
2935     }
2936     return rv;
2937 }
2938
2939 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out)
2940 {
2941     ast_expression *operand;
2942     ast_value      *opval;
2943     ast_value      *typevar;
2944     ast_switch     *switchnode;
2945     ast_switch_case swcase;
2946
2947     int  cvq;
2948     bool noref, is_static;
2949     uint32_t qflags = 0;
2950
2951     lex_ctx_t ctx = parser_ctx(parser);
2952
2953     (void)block; /* not touching */
2954     (void)opval;
2955
2956     /* parse into the expression */
2957     if (!parser_next(parser)) {
2958         parseerror(parser, "expected switch operand");
2959         return false;
2960     }
2961     /* parse the operand */
2962     operand = parse_expression_leave(parser, false, false, false);
2963     if (!operand)
2964         return false;
2965
2966     switchnode = ast_switch_new(ctx, operand);
2967
2968     /* closing paren */
2969     if (parser->tok != ')') {
2970         ast_delete(switchnode);
2971         parseerror(parser, "expected closing paren after 'switch' operand");
2972         return false;
2973     }
2974
2975     /* parse over the opening paren */
2976     if (!parser_next(parser) || parser->tok != '{') {
2977         ast_delete(switchnode);
2978         parseerror(parser, "expected list of cases");
2979         return false;
2980     }
2981
2982     if (!parser_next(parser)) {
2983         ast_delete(switchnode);
2984         parseerror(parser, "expected 'case' or 'default'");
2985         return false;
2986     }
2987
2988     /* new block; allow some variables to be declared here */
2989     parser_enterblock(parser);
2990     while (true) {
2991         typevar = NULL;
2992         if (parser->tok == TOKEN_IDENT)
2993             typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
2994         if (typevar || parser->tok == TOKEN_TYPENAME) {
2995             if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL)) {
2996                 ast_delete(switchnode);
2997                 return false;
2998             }
2999             continue;
3000         }
3001         if (parse_qualifiers(parser, true, &cvq, &noref, &is_static, &qflags, NULL))
3002         {
3003             if (cvq == CV_WRONG) {
3004                 ast_delete(switchnode);
3005                 return false;
3006             }
3007             if (!parse_variable(parser, block, false, cvq, NULL, noref, is_static, qflags, NULL)) {
3008                 ast_delete(switchnode);
3009                 return false;
3010             }
3011             continue;
3012         }
3013         break;
3014     }
3015
3016     /* case list! */
3017     while (parser->tok != '}') {
3018         ast_block *caseblock;
3019
3020         if (!strcmp(parser_tokval(parser), "case")) {
3021             if (!parser_next(parser)) {
3022                 ast_delete(switchnode);
3023                 parseerror(parser, "expected expression for case");
3024                 return false;
3025             }
3026             swcase.value = parse_expression_leave(parser, false, false, false);
3027             if (!swcase.value) {
3028                 ast_delete(switchnode);
3029                 parseerror(parser, "expected expression for case");
3030                 return false;
3031             }
3032             if (!OPTS_FLAG(RELAXED_SWITCH)) {
3033                 if (!ast_istype(swcase.value, ast_value)) { /* || ((ast_value*)swcase.value)->cvq != CV_CONST) { */
3034                     parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch");
3035                     ast_unref(operand);
3036                     return false;
3037                 }
3038             }
3039         }
3040         else if (!strcmp(parser_tokval(parser), "default")) {
3041             swcase.value = NULL;
3042             if (!parser_next(parser)) {
3043                 ast_delete(switchnode);
3044                 parseerror(parser, "expected colon");
3045                 return false;
3046             }
3047         }
3048         else {
3049             ast_delete(switchnode);
3050             parseerror(parser, "expected 'case' or 'default'");
3051             return false;
3052         }
3053
3054         /* Now the colon and body */
3055         if (parser->tok != ':') {
3056             if (swcase.value) ast_unref(swcase.value);
3057             ast_delete(switchnode);
3058             parseerror(parser, "expected colon");
3059             return false;
3060         }
3061
3062         if (!parser_next(parser)) {
3063             if (swcase.value) ast_unref(swcase.value);
3064             ast_delete(switchnode);
3065             parseerror(parser, "expected statements or case");
3066             return false;
3067         }
3068         caseblock = ast_block_new(parser_ctx(parser));
3069         if (!caseblock) {
3070             if (swcase.value) ast_unref(swcase.value);
3071             ast_delete(switchnode);
3072             return false;
3073         }
3074         swcase.code = (ast_expression*)caseblock;
3075         vec_push(switchnode->cases, swcase);
3076         while (true) {
3077             ast_expression *expr;
3078             if (parser->tok == '}')
3079                 break;
3080             if (parser->tok == TOKEN_KEYWORD) {
3081                 if (!strcmp(parser_tokval(parser), "case") ||
3082                     !strcmp(parser_tokval(parser), "default"))
3083                 {
3084                     break;
3085                 }
3086             }
3087             if (!parse_statement(parser, caseblock, &expr, true)) {
3088                 ast_delete(switchnode);
3089                 return false;
3090             }
3091             if (!expr)
3092                 continue;
3093             if (!ast_block_add_expr(caseblock, expr)) {
3094                 ast_delete(switchnode);
3095                 return false;
3096             }
3097         }
3098     }
3099
3100     parser_leaveblock(parser);
3101
3102     /* closing paren */
3103     if (parser->tok != '}') {
3104         ast_delete(switchnode);
3105         parseerror(parser, "expected closing paren of case list");
3106         return false;
3107     }
3108     if (!parser_next(parser)) {
3109         ast_delete(switchnode);
3110         parseerror(parser, "parse error after switch");
3111         return false;
3112     }
3113     *out = (ast_expression*)switchnode;
3114     return true;
3115 }
3116
3117 /* parse computed goto sides */
3118 static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **side) {
3119     ast_expression *on_true;
3120     ast_expression *on_false;
3121     ast_expression *cond;
3122
3123     if (!*side)
3124         return NULL;
3125
3126     if (ast_istype(*side, ast_ternary)) {
3127         ast_ternary *tern = (ast_ternary*)*side;
3128         on_true  = parse_goto_computed(parser, &tern->on_true);
3129         on_false = parse_goto_computed(parser, &tern->on_false);
3130
3131         if (!on_true || !on_false) {
3132             parseerror(parser, "expected label or expression in ternary");
3133             if (on_true) ast_unref(on_true);
3134             if (on_false) ast_unref(on_false);
3135             return NULL;
3136         }
3137
3138         cond = tern->cond;
3139         tern->cond = NULL;
3140         ast_delete(tern);
3141         *side = NULL;
3142         return (ast_expression*)ast_ifthen_new(parser_ctx(parser), cond, on_true, on_false);
3143     } else if (ast_istype(*side, ast_label)) {
3144         ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->name);
3145         ast_goto_set_label(gt, ((ast_label*)*side));
3146         *side = NULL;
3147         return (ast_expression*)gt;
3148     }
3149     return NULL;
3150 }
3151
3152 static bool parse_goto(parser_t *parser, ast_expression **out)
3153 {
3154     ast_goto       *gt = NULL;
3155     ast_expression *lbl;
3156
3157     if (!parser_next(parser))
3158         return false;
3159
3160     if (parser->tok != TOKEN_IDENT) {
3161         ast_expression *expression;
3162
3163         /* could be an expression i.e computed goto :-) */
3164         if (parser->tok != '(') {
3165             parseerror(parser, "expected label name after `goto`");
3166             return false;
3167         }
3168
3169         /* failed to parse expression for goto */
3170         if (!(expression = parse_expression(parser, false, true)) ||
3171             !(*out = parse_goto_computed(parser, &expression))) {
3172             parseerror(parser, "invalid goto expression");
3173             if(expression)
3174                 ast_unref(expression);
3175             return false;
3176         }
3177
3178         return true;
3179     }
3180
3181     /* not computed goto */
3182     gt = ast_goto_new(parser_ctx(parser), parser_tokval(parser));
3183     lbl = parser_find_label(parser, gt->name);
3184     if (lbl) {
3185         if (!ast_istype(lbl, ast_label)) {
3186             parseerror(parser, "internal error: label is not an ast_label");
3187             ast_delete(gt);
3188             return false;
3189         }
3190         ast_goto_set_label(gt, (ast_label*)lbl);
3191     }
3192     else
3193         vec_push(parser->gotos, gt);
3194
3195     if (!parser_next(parser) || parser->tok != ';') {
3196         parseerror(parser, "semicolon expected after goto label");
3197         return false;
3198     }
3199     if (!parser_next(parser)) {
3200         parseerror(parser, "parse error after goto");
3201         return false;
3202     }
3203
3204     *out = (ast_expression*)gt;
3205     return true;
3206 }
3207
3208 static bool parse_skipwhite(parser_t *parser)
3209 {
3210     do {
3211         if (!parser_next(parser))
3212             return false;
3213     } while (parser->tok == TOKEN_WHITE && parser->tok < TOKEN_ERROR);
3214     return parser->tok < TOKEN_ERROR;
3215 }
3216
3217 static bool parse_eol(parser_t *parser)
3218 {
3219     if (!parse_skipwhite(parser))
3220         return false;
3221     return parser->tok == TOKEN_EOL;
3222 }
3223
3224 static bool parse_pragma_do(parser_t *parser)
3225 {
3226     if (!parser_next(parser) ||
3227         parser->tok != TOKEN_IDENT ||
3228         strcmp(parser_tokval(parser), "pragma"))
3229     {
3230         parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
3231         return false;
3232     }
3233     if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
3234         parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
3235         return false;
3236     }
3237
3238     if (!strcmp(parser_tokval(parser), "noref")) {
3239         if (!parse_skipwhite(parser) || parser->tok != TOKEN_INTCONST) {
3240             parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
3241             return false;
3242         }
3243         parser->noref = !!parser_token(parser)->constval.i;
3244         if (!parse_eol(parser)) {
3245             parseerror(parser, "parse error after `noref` pragma");
3246             return false;
3247         }
3248     }
3249     else
3250     {
3251         (void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
3252         return false;
3253     }
3254
3255     return true;
3256 }
3257
3258 static bool parse_pragma(parser_t *parser)
3259 {
3260     bool rv;
3261     parser->lex->flags.preprocessing = true;
3262     parser->lex->flags.mergelines = true;
3263     rv = parse_pragma_do(parser);
3264     if (parser->tok != TOKEN_EOL) {
3265         parseerror(parser, "junk after pragma");
3266         rv = false;
3267     }
3268     parser->lex->flags.preprocessing = false;
3269     parser->lex->flags.mergelines = false;
3270     if (!parser_next(parser)) {
3271         parseerror(parser, "parse error after pragma");
3272         rv = false;
3273     }
3274     return rv;
3275 }
3276
3277 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
3278 {
3279     bool       noref, is_static;
3280     int        cvq     = CV_NONE;
3281     uint32_t   qflags  = 0;
3282     ast_value *typevar = NULL;
3283     char      *vstring = NULL;
3284
3285     *out = NULL;
3286
3287     if (parser->tok == TOKEN_IDENT)
3288         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
3289
3290     if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
3291     {
3292         /* local variable */
3293         if (!block) {
3294             parseerror(parser, "cannot declare a variable from here");
3295             return false;
3296         }
3297         if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3298             if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
3299                 return false;
3300         }
3301         if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL))
3302             return false;
3303         return true;
3304     }
3305     else if (parse_qualifiers(parser, !!block, &cvq, &noref, &is_static, &qflags, &vstring))
3306     {
3307         if (cvq == CV_WRONG)
3308             return false;
3309         return parse_variable(parser, block, true, cvq, NULL, noref, is_static, qflags, vstring);
3310     }
3311     else if (parser->tok == TOKEN_KEYWORD)
3312     {
3313         if (!strcmp(parser_tokval(parser), "__builtin_debug_printtype"))
3314         {
3315             char ty[1024];
3316             ast_value *tdef;
3317
3318             if (!parser_next(parser)) {
3319                 parseerror(parser, "parse error after __builtin_debug_printtype");
3320                 return false;
3321             }
3322
3323             if (parser->tok == TOKEN_IDENT && (tdef = parser_find_typedef(parser, parser_tokval(parser), 0)))
3324             {
3325                 ast_type_to_string((ast_expression*)tdef, ty, sizeof(ty));
3326                 con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->name, ty);
3327                 if (!parser_next(parser)) {
3328                     parseerror(parser, "parse error after __builtin_debug_printtype typename argument");
3329                     return false;
3330                 }
3331             }
3332             else
3333             {
3334                 if (!parse_statement(parser, block, out, allow_cases))
3335                     return false;
3336                 if (!*out)
3337                     con_out("__builtin_debug_printtype: got no output node\n");
3338                 else
3339                 {
3340                     ast_type_to_string(*out, ty, sizeof(ty));
3341                     con_out("__builtin_debug_printtype: `%s`\n", ty);
3342                 }
3343             }
3344             return true;
3345         }
3346         else if (!strcmp(parser_tokval(parser), "return"))
3347         {
3348             return parse_return(parser, block, out);
3349         }
3350         else if (!strcmp(parser_tokval(parser), "if"))
3351         {
3352             return parse_if(parser, block, out);
3353         }
3354         else if (!strcmp(parser_tokval(parser), "while"))
3355         {
3356             return parse_while(parser, block, out);
3357         }
3358         else if (!strcmp(parser_tokval(parser), "do"))
3359         {
3360             return parse_dowhile(parser, block, out);
3361         }
3362         else if (!strcmp(parser_tokval(parser), "for"))
3363         {
3364             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3365                 if (parsewarning(parser, WARN_EXTENSIONS, "for loops are not recognized in the original Quake C standard, to enable try an alternate standard --std=?"))
3366                     return false;
3367             }
3368             return parse_for(parser, block, out);
3369         }
3370         else if (!strcmp(parser_tokval(parser), "break"))
3371         {
3372             return parse_break_continue(parser, block, out, false);
3373         }
3374         else if (!strcmp(parser_tokval(parser), "continue"))
3375         {
3376             return parse_break_continue(parser, block, out, true);
3377         }
3378         else if (!strcmp(parser_tokval(parser), "switch"))
3379         {
3380             return parse_switch(parser, block, out);
3381         }
3382         else if (!strcmp(parser_tokval(parser), "case") ||
3383                  !strcmp(parser_tokval(parser), "default"))
3384         {
3385             if (!allow_cases) {
3386                 parseerror(parser, "unexpected 'case' label");
3387                 return false;
3388             }
3389             return true;
3390         }
3391         else if (!strcmp(parser_tokval(parser), "goto"))
3392         {
3393             return parse_goto(parser, out);
3394         }
3395         else if (!strcmp(parser_tokval(parser), "typedef"))
3396         {
3397             if (!parser_next(parser)) {
3398                 parseerror(parser, "expected type definition after 'typedef'");
3399                 return false;
3400             }
3401             return parse_typedef(parser);
3402         }
3403         parseerror(parser, "Unexpected keyword: `%s'", parser_tokval(parser));
3404         return false;
3405     }
3406     else if (parser->tok == '{')
3407     {
3408         ast_block *inner;
3409         inner = parse_block(parser);
3410         if (!inner)
3411             return false;
3412         *out = (ast_expression*)inner;
3413         return true;
3414     }
3415     else if (parser->tok == ':')
3416     {
3417         size_t i;
3418         ast_label *label;
3419         if (!parser_next(parser)) {
3420             parseerror(parser, "expected label name");
3421             return false;
3422         }
3423         if (parser->tok != TOKEN_IDENT) {
3424             parseerror(parser, "label must be an identifier");
3425             return false;
3426         }
3427         label = (ast_label*)parser_find_label(parser, parser_tokval(parser));
3428         if (label) {
3429             if (!label->undefined) {
3430                 parseerror(parser, "label `%s` already defined", label->name);
3431                 return false;
3432             }
3433             label->undefined = false;
3434         }
3435         else {
3436             label = ast_label_new(parser_ctx(parser), parser_tokval(parser), false);
3437             vec_push(parser->labels, label);
3438         }
3439         *out = (ast_expression*)label;
3440         if (!parser_next(parser)) {
3441             parseerror(parser, "parse error after label");
3442             return false;
3443         }
3444         for (i = 0; i < vec_size(parser->gotos); ++i) {
3445             if (!strcmp(parser->gotos[i]->name, label->name)) {
3446                 ast_goto_set_label(parser->gotos[i], label);
3447                 vec_remove(parser->gotos, i, 1);
3448                 --i;
3449             }
3450         }
3451         return true;
3452     }
3453     else if (parser->tok == ';')
3454     {
3455         if (!parser_next(parser)) {
3456             parseerror(parser, "parse error after empty statement");
3457             return false;
3458         }
3459         return true;
3460     }
3461     else
3462     {
3463         lex_ctx_t ctx = parser_ctx(parser);
3464         ast_expression *exp = parse_expression(parser, false, false);
3465         if (!exp)
3466             return false;
3467         *out = exp;
3468         if (!ast_side_effects(exp)) {
3469             if (compile_warning(ctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
3470                 return false;
3471         }
3472         return true;
3473     }
3474 }
3475
3476 static bool parse_enum(parser_t *parser)
3477 {
3478     bool        flag = false;
3479     bool        reverse = false;
3480     qcfloat_t     num = 0;
3481     ast_value **values = NULL;
3482     ast_value  *var = NULL;
3483     ast_value  *asvalue;
3484
3485     ast_expression *old;
3486
3487     if (!parser_next(parser) || (parser->tok != '{' && parser->tok != ':')) {
3488         parseerror(parser, "expected `{` or `:` after `enum` keyword");
3489         return false;
3490     }
3491
3492     /* enumeration attributes (can add more later) */
3493     if (parser->tok == ':') {
3494         if (!parser_next(parser) || parser->tok != TOKEN_IDENT){
3495             parseerror(parser, "expected `flag` or `reverse` for enumeration attribute");
3496             return false;
3497         }
3498
3499         /* attributes? */
3500         if (!strcmp(parser_tokval(parser), "flag")) {
3501             num  = 1;
3502             flag = true;
3503         }
3504         else if (!strcmp(parser_tokval(parser), "reverse")) {
3505             reverse = true;
3506         }
3507         else {
3508             parseerror(parser, "invalid attribute `%s` for enumeration", parser_tokval(parser));
3509             return false;
3510         }
3511
3512         if (!parser_next(parser) || parser->tok != '{') {
3513             parseerror(parser, "expected `{` after enum attribute ");
3514             return false;
3515         }
3516     }
3517
3518     while (true) {
3519         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
3520             if (parser->tok == '}') {
3521                 /* allow an empty enum */
3522                 break;
3523             }
3524             parseerror(parser, "expected identifier or `}`");
3525             goto onerror;
3526         }
3527
3528         old = parser_find_field(parser, parser_tokval(parser));
3529         if (!old)
3530             old = parser_find_global(parser, parser_tokval(parser));
3531         if (old) {
3532             parseerror(parser, "value `%s` has already been declared here: %s:%i",
3533                        parser_tokval(parser), ast_ctx(old).file, ast_ctx(old).line);
3534             goto onerror;
3535         }
3536
3537         var = ast_value_new(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT);
3538         vec_push(values, var);
3539         var->cvq             = CV_CONST;
3540         var->hasvalue        = true;
3541
3542         /* for flagged enumerations increment in POTs of TWO */
3543         var->constval.vfloat = (flag) ? (num *= 2) : (num ++);
3544         parser_addglobal(parser, var->name, (ast_expression*)var);
3545
3546         if (!parser_next(parser)) {
3547             parseerror(parser, "expected `=`, `}` or comma after identifier");
3548             goto onerror;
3549         }
3550
3551         if (parser->tok == ',')
3552             continue;
3553         if (parser->tok == '}')
3554             break;
3555         if (parser->tok != '=') {
3556             parseerror(parser, "expected `=`, `}` or comma after identifier");
3557             goto onerror;
3558         }
3559
3560         if (!parser_next(parser)) {
3561             parseerror(parser, "expected expression after `=`");
3562             goto onerror;
3563         }
3564
3565         /* We got a value! */
3566         old = parse_expression_leave(parser, true, false, false);
3567         asvalue = (ast_value*)old;
3568         if (!ast_istype(old, ast_value) || asvalue->cvq != CV_CONST || !asvalue->hasvalue) {
3569             compile_error(ast_ctx(var), "constant value or expression expected");
3570             goto onerror;
3571         }
3572         num = (var->constval.vfloat = asvalue->constval.vfloat) + 1;
3573
3574         if (parser->tok == '}')
3575             break;
3576         if (parser->tok != ',') {
3577             parseerror(parser, "expected `}` or comma after expression");
3578             goto onerror;
3579         }
3580     }
3581
3582     /* patch them all (for reversed attribute) */
3583     if (reverse) {
3584         size_t i;
3585         for (i = 0; i < vec_size(values); i++)
3586             values[i]->constval.vfloat = vec_size(values) - i - 1;
3587     }
3588
3589     if (parser->tok != '}') {
3590         parseerror(parser, "internal error: breaking without `}`");
3591         goto onerror;
3592     }
3593
3594     if (!parser_next(parser) || parser->tok != ';') {
3595         parseerror(parser, "expected semicolon after enumeration");
3596         goto onerror;
3597     }
3598
3599     if (!parser_next(parser)) {
3600         parseerror(parser, "parse error after enumeration");
3601         goto onerror;
3602     }
3603
3604     vec_free(values);
3605     return true;
3606
3607 onerror:
3608     vec_free(values);
3609     return false;
3610 }
3611
3612 static bool parse_block_into(parser_t *parser, ast_block *block)
3613 {
3614     bool   retval = true;
3615
3616     parser_enterblock(parser);
3617
3618     if (!parser_next(parser)) { /* skip the '{' */
3619         parseerror(parser, "expected function body");
3620         goto cleanup;
3621     }
3622
3623     while (parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR)
3624     {
3625         ast_expression *expr = NULL;
3626         if (parser->tok == '}')
3627             break;
3628
3629         if (!parse_statement(parser, block, &expr, false)) {
3630             /* parseerror(parser, "parse error"); */
3631             block = NULL;
3632             goto cleanup;
3633         }
3634         if (!expr)
3635             continue;
3636         if (!ast_block_add_expr(block, expr)) {
3637             ast_delete(block);
3638             block = NULL;
3639             goto cleanup;
3640         }
3641     }
3642
3643     if (parser->tok != '}') {
3644         block = NULL;
3645     } else {
3646         (void)parser_next(parser);
3647     }
3648
3649 cleanup:
3650     if (!parser_leaveblock(parser))
3651         retval = false;
3652     return retval && !!block;
3653 }
3654
3655 static ast_block* parse_block(parser_t *parser)
3656 {
3657     ast_block *block;
3658     block = ast_block_new(parser_ctx(parser));
3659     if (!block)
3660         return NULL;
3661     if (!parse_block_into(parser, block)) {
3662         ast_block_delete(block);
3663         return NULL;
3664     }
3665     return block;
3666 }
3667
3668 static bool parse_statement_or_block(parser_t *parser, ast_expression **out)
3669 {
3670     if (parser->tok == '{') {
3671         *out = (ast_expression*)parse_block(parser);
3672         return !!*out;
3673     }
3674     return parse_statement(parser, NULL, out, false);
3675 }
3676
3677 static bool create_vector_members(ast_value *var, ast_member **me)
3678 {
3679     size_t i;
3680     size_t len = strlen(var->name);
3681
3682     for (i = 0; i < 3; ++i) {
3683         char *name = (char*)mem_a(len+3);
3684         memcpy(name, var->name, len);
3685         name[len+0] = '_';
3686         name[len+1] = 'x'+i;
3687         name[len+2] = 0;
3688         me[i] = ast_member_new(ast_ctx(var), (ast_expression*)var, i, name);
3689         mem_d(name);
3690         if (!me[i])
3691             break;
3692     }
3693     if (i == 3)
3694         return true;
3695
3696     /* unroll */
3697     do { ast_member_delete(me[--i]); } while(i);
3698     return false;
3699 }
3700
3701 static bool parse_function_body(parser_t *parser, ast_value *var)
3702 {
3703     ast_block      *block = NULL;
3704     ast_function   *func;
3705     ast_function   *old;
3706     size_t          parami;
3707
3708     ast_expression *framenum  = NULL;
3709     ast_expression *nextthink = NULL;
3710     /* None of the following have to be deleted */
3711     ast_expression *fld_think = NULL, *fld_nextthink = NULL, *fld_frame = NULL;
3712     ast_expression *gbl_time = NULL, *gbl_self = NULL;
3713     bool            has_frame_think;
3714
3715     bool retval = true;
3716
3717     has_frame_think = false;
3718     old = parser->function;
3719
3720     if (var->expression.flags & AST_FLAG_ALIAS) {
3721         parseerror(parser, "function aliases cannot have bodies");
3722         return false;
3723     }
3724
3725     if (vec_size(parser->gotos) || vec_size(parser->labels)) {
3726         parseerror(parser, "gotos/labels leaking");
3727         return false;
3728     }
3729
3730     if (!OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
3731         if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
3732                          "variadic function with implementation will not be able to access additional parameters (try -fvariadic-args)"))
3733         {
3734             return false;
3735         }
3736     }
3737
3738     if (parser->tok == '[') {
3739         /* got a frame definition: [ framenum, nextthink ]
3740          * this translates to:
3741          * self.frame = framenum;
3742          * self.nextthink = time + 0.1;
3743          * self.think = nextthink;
3744          */
3745         nextthink = NULL;
3746
3747         fld_think     = parser_find_field(parser, "think");
3748         fld_nextthink = parser_find_field(parser, "nextthink");
3749         fld_frame     = parser_find_field(parser, "frame");
3750         if (!fld_think || !fld_nextthink || !fld_frame) {
3751             parseerror(parser, "cannot use [frame,think] notation without the required fields");
3752             parseerror(parser, "please declare the following entityfields: `frame`, `think`, `nextthink`");
3753             return false;
3754         }
3755         gbl_time      = parser_find_global(parser, "time");
3756         gbl_self      = parser_find_global(parser, "self");
3757         if (!gbl_time || !gbl_self) {
3758             parseerror(parser, "cannot use [frame,think] notation without the required globals");
3759             parseerror(parser, "please declare the following globals: `time`, `self`");
3760             return false;
3761         }
3762
3763         if (!parser_next(parser))
3764             return false;
3765
3766         framenum = parse_expression_leave(parser, true, false, false);
3767         if (!framenum) {
3768             parseerror(parser, "expected a framenumber constant in[frame,think] notation");
3769             return false;
3770         }
3771         if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->hasvalue) {
3772             ast_unref(framenum);
3773             parseerror(parser, "framenumber in [frame,think] notation must be a constant");
3774             return false;
3775         }
3776
3777         if (parser->tok != ',') {
3778             ast_unref(framenum);
3779             parseerror(parser, "expected comma after frame number in [frame,think] notation");
3780             parseerror(parser, "Got a %i\n", parser->tok);
3781             return false;
3782         }
3783
3784         if (!parser_next(parser)) {
3785             ast_unref(framenum);
3786             return false;
3787         }
3788
3789         if (parser->tok == TOKEN_IDENT && !parser_find_var(parser, parser_tokval(parser)))
3790         {
3791             /* qc allows the use of not-yet-declared functions here
3792              * - this automatically creates a prototype */
3793             ast_value      *thinkfunc;
3794             ast_expression *functype = fld_think->next;
3795
3796             thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->vtype);
3797             if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/
3798                 ast_unref(framenum);
3799                 parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
3800                 return false;
3801             }
3802             ast_type_adopt(thinkfunc, functype);
3803
3804             if (!parser_next(parser)) {
3805                 ast_unref(framenum);
3806                 ast_delete(thinkfunc);
3807                 return false;
3808             }
3809
3810             parser_addglobal(parser, thinkfunc->name, (ast_expression*)thinkfunc);
3811
3812             nextthink = (ast_expression*)thinkfunc;
3813
3814         } else {
3815             nextthink = parse_expression_leave(parser, true, false, false);
3816             if (!nextthink) {
3817                 ast_unref(framenum);
3818                 parseerror(parser, "expected a think-function in [frame,think] notation");
3819                 return false;
3820             }
3821         }
3822
3823         if (!ast_istype(nextthink, ast_value)) {
3824             parseerror(parser, "think-function in [frame,think] notation must be a constant");
3825             retval = false;
3826         }
3827
3828         if (retval && parser->tok != ']') {
3829             parseerror(parser, "expected closing `]` for [frame,think] notation");
3830             retval = false;
3831         }
3832
3833         if (retval && !parser_next(parser)) {
3834             retval = false;
3835         }
3836
3837         if (retval && parser->tok != '{') {
3838             parseerror(parser, "a function body has to be declared after a [frame,think] declaration");
3839             retval = false;
3840         }
3841
3842         if (!retval) {
3843             ast_unref(nextthink);
3844             ast_unref(framenum);
3845             return false;
3846         }
3847
3848         has_frame_think = true;
3849     }
3850
3851     block = ast_block_new(parser_ctx(parser));
3852     if (!block) {
3853         parseerror(parser, "failed to allocate block");
3854         if (has_frame_think) {
3855             ast_unref(nextthink);
3856             ast_unref(framenum);
3857         }
3858         return false;
3859     }
3860
3861     if (has_frame_think) {
3862         lex_ctx_t ctx;
3863         ast_expression *self_frame;
3864         ast_expression *self_nextthink;
3865         ast_expression *self_think;
3866         ast_expression *time_plus_1;
3867         ast_store *store_frame;
3868         ast_store *store_nextthink;
3869         ast_store *store_think;
3870
3871         ctx = parser_ctx(parser);
3872         self_frame     = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_frame);
3873         self_nextthink = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_nextthink);
3874         self_think     = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_think);
3875
3876         time_plus_1    = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F,
3877                          gbl_time, (ast_expression*)fold_constgen_float(parser->fold, 0.1));
3878
3879         if (!self_frame || !self_nextthink || !self_think || !time_plus_1) {
3880             if (self_frame)     ast_delete(self_frame);
3881             if (self_nextthink) ast_delete(self_nextthink);
3882             if (self_think)     ast_delete(self_think);
3883             if (time_plus_1)    ast_delete(time_plus_1);
3884             retval = false;
3885         }
3886
3887         if (retval)
3888         {
3889             store_frame     = ast_store_new(ctx, INSTR_STOREP_F,   self_frame,     framenum);
3890             store_nextthink = ast_store_new(ctx, INSTR_STOREP_F,   self_nextthink, time_plus_1);
3891             store_think     = ast_store_new(ctx, INSTR_STOREP_FNC, self_think,     nextthink);
3892
3893             if (!store_frame) {
3894                 ast_delete(self_frame);
3895                 retval = false;
3896             }
3897             if (!store_nextthink) {
3898                 ast_delete(self_nextthink);
3899                 retval = false;
3900             }
3901             if (!store_think) {
3902                 ast_delete(self_think);
3903                 retval = false;
3904             }
3905             if (!retval) {
3906                 if (store_frame)     ast_delete(store_frame);
3907                 if (store_nextthink) ast_delete(store_nextthink);
3908                 if (store_think)     ast_delete(store_think);
3909                 retval = false;
3910             }
3911             if (!ast_block_add_expr(block, (ast_expression*)store_frame) ||
3912                 !ast_block_add_expr(block, (ast_expression*)store_nextthink) ||
3913                 !ast_block_add_expr(block, (ast_expression*)store_think))
3914             {
3915                 retval = false;
3916             }
3917         }
3918
3919         if (!retval) {
3920             parseerror(parser, "failed to generate code for [frame,think]");
3921             ast_unref(nextthink);
3922             ast_unref(framenum);
3923             ast_delete(block);
3924             return false;
3925         }
3926     }
3927
3928     if (var->hasvalue) {
3929         parseerror(parser, "function `%s` declared with multiple bodies", var->name);
3930         ast_block_delete(block);
3931         goto enderr;
3932     }
3933
3934     func = ast_function_new(ast_ctx(var), var->name, var);
3935     if (!func) {
3936         parseerror(parser, "failed to allocate function for `%s`", var->name);
3937         ast_block_delete(block);
3938         goto enderr;
3939     }
3940     vec_push(parser->functions, func);
3941
3942     parser_enterblock(parser);
3943
3944     for (parami = 0; parami < vec_size(var->expression.params); ++parami) {
3945         size_t     e;
3946         ast_value *param = var->expression.params[parami];
3947         ast_member *me[3];
3948
3949         if (param->expression.vtype != TYPE_VECTOR &&
3950             (param->expression.vtype != TYPE_FIELD ||
3951              param->expression.next->vtype != TYPE_VECTOR))
3952         {
3953             continue;
3954         }
3955
3956         if (!create_vector_members(param, me)) {
3957             ast_block_delete(block);
3958             goto enderrfn;
3959         }
3960
3961         for (e = 0; e < 3; ++e) {
3962             parser_addlocal(parser, me[e]->name, (ast_expression*)me[e]);
3963             ast_block_collect(block, (ast_expression*)me[e]);
3964         }
3965     }
3966
3967     if (var->argcounter) {
3968         ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT);
3969         parser_addlocal(parser, argc->name, (ast_expression*)argc);
3970         func->argc = argc;
3971     }
3972
3973     if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
3974         char name[1024];
3975         ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY);
3976         varargs->expression.flags |= AST_FLAG_IS_VARARG;
3977         varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), NULL, TYPE_VECTOR);
3978         varargs->expression.count = 0;
3979         util_snprintf(name, sizeof(name), "%s##va##SET", var->name);
3980         if (!parser_create_array_setter_proto(parser, varargs, name)) {
3981             ast_delete(varargs);
3982             ast_block_delete(block);
3983             goto enderrfn;
3984         }
3985         util_snprintf(name, sizeof(name), "%s##va##GET", var->name);
3986         if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) {
3987             ast_delete(varargs);
3988             ast_block_delete(block);
3989             goto enderrfn;
3990         }
3991         func->varargs     = varargs;
3992         func->fixedparams = (ast_value*)fold_constgen_float(parser->fold, vec_size(var->expression.params));
3993     }
3994
3995     parser->function = func;
3996     if (!parse_block_into(parser, block)) {
3997         ast_block_delete(block);
3998         goto enderrfn;
3999     }
4000
4001     vec_push(func->blocks, block);
4002
4003
4004     parser->function = old;
4005     if (!parser_leaveblock(parser))
4006         retval = false;
4007     if (vec_size(parser->variables) != PARSER_HT_LOCALS) {
4008         parseerror(parser, "internal error: local scopes left");
4009         retval = false;
4010     }
4011
4012     if (parser->tok == ';')
4013         return parser_next(parser);
4014     else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4015         parseerror(parser, "missing semicolon after function body (mandatory with -std=qcc)");
4016     return retval;
4017
4018 enderrfn:
4019     (void)!parser_leaveblock(parser);
4020     vec_pop(parser->functions);
4021     ast_function_delete(func);
4022     var->constval.vfunc = NULL;
4023
4024 enderr:
4025     parser->function = old;
4026     return false;
4027 }
4028
4029 static ast_expression *array_accessor_split(
4030     parser_t  *parser,
4031     ast_value *array,
4032     ast_value *index,
4033     size_t     middle,
4034     ast_expression *left,
4035     ast_expression *right
4036     )
4037 {
4038     ast_ifthen *ifthen;
4039     ast_binary *cmp;
4040
4041     lex_ctx_t ctx = ast_ctx(array);
4042
4043     if (!left || !right) {
4044         if (left)  ast_delete(left);
4045         if (right) ast_delete(right);
4046         return NULL;
4047     }
4048
4049     cmp = ast_binary_new(ctx, INSTR_LT,
4050                          (ast_expression*)index,
4051                          (ast_expression*)fold_constgen_float(parser->fold, middle));
4052     if (!cmp) {
4053         ast_delete(left);
4054         ast_delete(right);
4055         parseerror(parser, "internal error: failed to create comparison for array setter");
4056         return NULL;
4057     }
4058
4059     ifthen = ast_ifthen_new(ctx, (ast_expression*)cmp, left, right);
4060     if (!ifthen) {
4061         ast_delete(cmp); /* will delete left and right */
4062         parseerror(parser, "internal error: failed to create conditional jump for array setter");
4063         return NULL;
4064     }
4065
4066     return (ast_expression*)ifthen;
4067 }
4068
4069 static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast_value *index, ast_value *value, size_t from, size_t afterend)
4070 {
4071     lex_ctx_t ctx = ast_ctx(array);
4072
4073     if (from+1 == afterend) {
4074         /* set this value */
4075         ast_block       *block;
4076         ast_return      *ret;
4077         ast_array_index *subscript;
4078         ast_store       *st;
4079         int assignop = type_store_instr[value->expression.vtype];
4080
4081         if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
4082             assignop = INSTR_STORE_V;
4083
4084         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from));
4085         if (!subscript)
4086             return NULL;
4087
4088         st = ast_store_new(ctx, assignop, (ast_expression*)subscript, (ast_expression*)value);
4089         if (!st) {
4090             ast_delete(subscript);
4091             return NULL;
4092         }
4093
4094         block = ast_block_new(ctx);
4095         if (!block) {
4096             ast_delete(st);
4097             return NULL;
4098         }
4099
4100         if (!ast_block_add_expr(block, (ast_expression*)st)) {
4101             ast_delete(block);
4102             return NULL;
4103         }
4104
4105         ret = ast_return_new(ctx, NULL);
4106         if (!ret) {
4107             ast_delete(block);
4108             return NULL;
4109         }
4110
4111         if (!ast_block_add_expr(block, (ast_expression*)ret)) {