]> git.xonotic.org Git - xonotic/gmqcc.git/blob - parser.c
Disable the macros to keep clang happy (just uncomment them for when more constant...
[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)) {
4112             ast_delete(block);
4113             return NULL;
4114         }
4115
4116         return (ast_expression*)block;
4117     } else {
4118         ast_expression *left, *right;
4119         size_t diff = afterend - from;
4120         size_t middle = from + diff/2;
4121         left  = array_setter_node(parser, array, index, value, from, middle);
4122         right = array_setter_node(parser, array, index, value, middle, afterend);
4123         return array_accessor_split(parser, array, index, middle, left, right);
4124     }
4125 }
4126
4127 static ast_expression *array_field_setter_node(
4128     parser_t  *parser,
4129     ast_value *array,
4130     ast_value *entity,
4131     ast_value *index,
4132     ast_value *value,
4133     size_t     from,
4134     size_t     afterend)
4135 {
4136     lex_ctx_t ctx = ast_ctx(array);
4137
4138     if (from+1 == afterend) {
4139         /* set this value */
4140         ast_block       *block;
4141         ast_return      *ret;
4142         ast_entfield    *entfield;
4143         ast_array_index *subscript;
4144         ast_store       *st;
4145         int assignop = type_storep_instr[value->expression.vtype];
4146
4147         if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
4148             assignop = INSTR_STOREP_V;
4149
4150         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from));
4151         if (!subscript)
4152             return NULL;
4153
4154         subscript->expression.next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript);
4155         subscript->expression.vtype = TYPE_FIELD;
4156
4157         entfield = ast_entfield_new_force(ctx,
4158                                           (ast_expression*)entity,
4159                                           (ast_expression*)subscript,
4160                                           (ast_expression*)subscript);
4161         if (!entfield) {
4162             ast_delete(subscript);
4163             return NULL;
4164         }
4165
4166         st = ast_store_new(ctx, assignop, (ast_expression*)entfield, (ast_expression*)value);
4167         if (!st) {
4168             ast_delete(entfield);
4169             return NULL;
4170         }
4171
4172         block = ast_block_new(ctx);
4173         if (!block) {
4174             ast_delete(st);
4175             return NULL;
4176         }
4177
4178         if (!ast_block_add_expr(block, (ast_expression*)st)) {
4179             ast_delete(block);
4180             return NULL;
4181         }
4182
4183         ret = ast_return_new(ctx, NULL);
4184         if (!ret) {
4185             ast_delete(block);
4186             return NULL;
4187         }
4188
4189         if (!ast_block_add_expr(block, (ast_expression*)ret)) {
4190             ast_delete(block);
4191             return NULL;
4192         }
4193
4194         return (ast_expression*)block;
4195     } else {
4196         ast_expression *left, *right;
4197         size_t diff = afterend - from;
4198         size_t middle = from + diff/2;
4199         left  = array_field_setter_node(parser, array, entity, index, value, from, middle);
4200         right = array_field_setter_node(parser, array, entity, index, value, middle, afterend);
4201         return array_accessor_split(parser, array, index, middle, left, right);
4202     }
4203 }
4204
4205 static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast_value *index, size_t from, size_t afterend)
4206 {
4207     lex_ctx_t ctx = ast_ctx(array);
4208
4209     if (from+1 == afterend) {
4210         ast_return      *ret;
4211         ast_array_index *subscript;
4212
4213         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from));
4214         if (!subscript)
4215             return NULL;
4216
4217         ret = ast_return_new(ctx, (ast_expression*)subscript);
4218         if (!ret) {
4219             ast_delete(subscript);
4220             return NULL;
4221         }
4222
4223         return (ast_expression*)ret;
4224     } else {
4225         ast_expression *left, *right;
4226         size_t diff = afterend - from;
4227         size_t middle = from + diff/2;
4228         left  = array_getter_node(parser, array, index, from, middle);
4229         right = array_getter_node(parser, array, index, middle, afterend);
4230         return array_accessor_split(parser, array, index, middle, left, right);
4231     }
4232 }
4233
4234 static bool parser_create_array_accessor(parser_t *parser, ast_value *array, const char *funcname, ast_value **out)
4235 {
4236     ast_function   *func = NULL;
4237     ast_value      *fval = NULL;
4238     ast_block      *body = NULL;
4239
4240     fval = ast_value_new(ast_ctx(array), funcname, TYPE_FUNCTION);
4241     if (!fval) {
4242         parseerror(parser, "failed to create accessor function value");
4243         return false;
4244     }
4245
4246     func = ast_function_new(ast_ctx(array), funcname, fval);
4247     if (!func) {
4248         ast_delete(fval);
4249         parseerror(parser, "failed to create accessor function node");
4250         return false;
4251     }
4252
4253     body = ast_block_new(ast_ctx(array));
4254     if (!body) {
4255         parseerror(parser, "failed to create block for array accessor");
4256         ast_delete(fval);
4257         ast_delete(func);
4258         return false;
4259     }
4260
4261     vec_push(func->blocks, body);
4262     *out = fval;
4263
4264     vec_push(parser->accessors, fval);
4265
4266     return true;
4267 }
4268
4269 static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname)
4270 {
4271     ast_value      *index = NULL;
4272     ast_value      *value = NULL;
4273     ast_function   *func;
4274     ast_value      *fval;
4275
4276     if (!ast_istype(array->expression.next, ast_value)) {
4277         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
4278         return NULL;
4279     }
4280
4281     if (!parser_create_array_accessor(parser, array, funcname, &fval))
4282         return NULL;
4283     func = fval->constval.vfunc;
4284     fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
4285
4286     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
4287     value = ast_value_copy((ast_value*)array->expression.next);
4288
4289     if (!index || !value) {
4290         parseerror(parser, "failed to create locals for array accessor");
4291         goto cleanup;
4292     }
4293     (void)!ast_value_set_name(value, "value"); /* not important */
4294     vec_push(fval->expression.params, index);
4295     vec_push(fval->expression.params, value);
4296
4297     array->setter = fval;
4298     return fval;
4299 cleanup:
4300     if (index) ast_delete(index);
4301     if (value) ast_delete(value);
4302     ast_delete(func);
4303     ast_delete(fval);
4304     return NULL;
4305 }
4306
4307 static bool parser_create_array_setter_impl(parser_t *parser, ast_value *array)
4308 {
4309     ast_expression *root = NULL;
4310     root = array_setter_node(parser, array,
4311                              array->setter->expression.params[0],
4312                              array->setter->expression.params[1],
4313                              0, array->expression.count);
4314     if (!root) {
4315         parseerror(parser, "failed to build accessor search tree");
4316         return false;
4317     }
4318     if (!ast_block_add_expr(array->setter->constval.vfunc->blocks[0], root)) {
4319         ast_delete(root);
4320         return false;
4321     }
4322     return true;
4323 }
4324
4325 static bool parser_create_array_setter(parser_t *parser, ast_value *array, const char *funcname)
4326 {
4327     if (!parser_create_array_setter_proto(parser, array, funcname))
4328         return false;
4329     return parser_create_array_setter_impl(parser, array);
4330 }
4331
4332 static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, const char *funcname)
4333 {
4334     ast_expression *root = NULL;
4335     ast_value      *entity = NULL;
4336     ast_value      *index = NULL;
4337     ast_value      *value = NULL;
4338     ast_function   *func;
4339     ast_value      *fval;
4340
4341     if (!ast_istype(array->expression.next, ast_value)) {
4342         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
4343         return false;
4344     }
4345
4346     if (!parser_create_array_accessor(parser, array, funcname, &fval))
4347         return false;
4348     func = fval->constval.vfunc;
4349     fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
4350
4351     entity = ast_value_new(ast_ctx(array), "entity", TYPE_ENTITY);
4352     index  = ast_value_new(ast_ctx(array), "index",  TYPE_FLOAT);
4353     value  = ast_value_copy((ast_value*)array->expression.next);
4354     if (!entity || !index || !value) {
4355         parseerror(parser, "failed to create locals for array accessor");
4356         goto cleanup;
4357     }
4358     (void)!ast_value_set_name(value, "value"); /* not important */
4359     vec_push(fval->expression.params, entity);
4360     vec_push(fval->expression.params, index);
4361     vec_push(fval->expression.params, value);
4362
4363     root = array_field_setter_node(parser, array, entity, index, value, 0, array->expression.count);
4364     if (!root) {
4365         parseerror(parser, "failed to build accessor search tree");
4366         goto cleanup;
4367     }
4368
4369     array->setter = fval;
4370     return ast_block_add_expr(func->blocks[0], root);
4371 cleanup:
4372     if (entity) ast_delete(entity);
4373     if (index)  ast_delete(index);
4374     if (value)  ast_delete(value);
4375     if (root)   ast_delete(root);
4376     ast_delete(func);
4377     ast_delete(fval);
4378     return false;
4379 }
4380
4381 static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname)
4382 {
4383     ast_value      *index = NULL;
4384     ast_value      *fval;
4385     ast_function   *func;
4386
4387     /* NOTE: checking array->expression.next rather than elemtype since
4388      * for fields elemtype is a temporary fieldtype.
4389      */
4390     if (!ast_istype(array->expression.next, ast_value)) {
4391         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
4392         return NULL;
4393     }
4394
4395     if (!parser_create_array_accessor(parser, array, funcname, &fval))
4396         return NULL;
4397     func = fval->constval.vfunc;
4398     fval->expression.next = ast_type_copy(ast_ctx(array), elemtype);
4399
4400     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
4401
4402     if (!index) {
4403         parseerror(parser, "failed to create locals for array accessor");
4404         goto cleanup;
4405     }
4406     vec_push(fval->expression.params, index);
4407
4408     array->getter = fval;
4409     return fval;
4410 cleanup:
4411     if (index) ast_delete(index);
4412     ast_delete(func);
4413     ast_delete(fval);
4414     return NULL;
4415 }
4416
4417 static bool parser_create_array_getter_impl(parser_t *parser, ast_value *array)
4418 {
4419     ast_expression *root = NULL;
4420
4421     root = array_getter_node(parser, array, array->getter->expression.params[0], 0, array->expression.count);
4422     if (!root) {
4423         parseerror(parser, "failed to build accessor search tree");
4424         return false;
4425     }
4426     if (!ast_block_add_expr(array->getter->constval.vfunc->blocks[0], root)) {
4427         ast_delete(root);
4428         return false;
4429     }
4430     return true;
4431 }
4432
4433 static bool parser_create_array_getter(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname)
4434 {
4435     if (!parser_create_array_getter_proto(parser, array, elemtype, funcname))
4436         return false;
4437     return parser_create_array_getter_impl(parser, array);
4438 }
4439
4440 static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
4441 static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
4442 {
4443     lex_ctx_t     ctx;
4444     size_t      i;
4445     ast_value **params;
4446     ast_value  *param;
4447     ast_value  *fval;
4448     bool        first = true;
4449     bool        variadic = false;
4450     ast_value  *varparam = NULL;
4451     char       *argcounter = NULL;
4452
4453     ctx = parser_ctx(parser);
4454
4455     /* for the sake of less code we parse-in in this function */
4456     if (!parser_next(parser)) {
4457         ast_delete(var);
4458         parseerror(parser, "expected parameter list");
4459         return NULL;
4460     }
4461
4462     params = NULL;
4463
4464     /* parse variables until we hit a closing paren */
4465     while (parser->tok != ')') {
4466         if (!first) {
4467             /* there must be commas between them */
4468             if (parser->tok != ',') {
4469                 parseerror(parser, "expected comma or end of parameter list");
4470                 goto on_error;
4471             }
4472             if (!parser_next(parser)) {
4473                 parseerror(parser, "expected parameter");
4474                 goto on_error;
4475             }
4476         }
4477         first = false;
4478
4479         if (parser->tok == TOKEN_DOTS) {
4480             /* '...' indicates a varargs function */
4481             variadic = true;
4482             if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) {
4483                 parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4484                 goto on_error;
4485             }
4486             if (parser->tok == TOKEN_IDENT) {
4487                 argcounter = util_strdup(parser_tokval(parser));
4488                 if (!parser_next(parser) || parser->tok != ')') {
4489                     parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4490                     goto on_error;
4491                 }
4492             }
4493         }
4494         else
4495         {
4496             /* for anything else just parse a typename */
4497             param = parse_typename(parser, NULL, NULL);
4498             if (!param)
4499                 goto on_error;
4500             vec_push(params, param);
4501             if (param->expression.vtype >= TYPE_VARIANT) {
4502                 char tname[1024]; /* typename is reserved in C++ */
4503                 ast_type_to_string((ast_expression*)param, tname, sizeof(tname));
4504                 parseerror(parser, "type not supported as part of a parameter list: %s", tname);
4505                 goto on_error;
4506             }
4507             /* type-restricted varargs */
4508             if (parser->tok == TOKEN_DOTS) {
4509                 variadic = true;
4510                 varparam = vec_last(params);
4511                 vec_pop(params);
4512                 if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) {
4513                     parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4514                     goto on_error;
4515                 }
4516                 if (parser->tok == TOKEN_IDENT) {
4517                     argcounter = util_strdup(parser_tokval(parser));
4518                     if (!parser_next(parser) || parser->tok != ')') {
4519                         parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
4520                         goto on_error;
4521                     }
4522                 }
4523             }
4524         }
4525     }
4526
4527     if (vec_size(params) == 1 && params[0]->expression.vtype == TYPE_VOID)
4528         vec_free(params);
4529
4530     /* sanity check */
4531     if (vec_size(params) > 8 && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4532         (void)!parsewarning(parser, WARN_EXTENSIONS, "more than 8 parameters are not supported by this standard");
4533
4534     /* parse-out */
4535     if (!parser_next(parser)) {
4536         parseerror(parser, "parse error after typename");
4537         goto on_error;
4538     }
4539
4540     /* now turn 'var' into a function type */
4541     fval = ast_value_new(ctx, "<type()>", TYPE_FUNCTION);
4542     fval->expression.next     = (ast_expression*)var;
4543     if (variadic)
4544         fval->expression.flags |= AST_FLAG_VARIADIC;
4545     var = fval;
4546
4547     var->expression.params   = params;
4548     var->expression.varparam = (ast_expression*)varparam;
4549     var->argcounter          = argcounter;
4550     params = NULL;
4551
4552     return var;
4553
4554 on_error:
4555     if (argcounter)
4556         mem_d(argcounter);
4557     if (varparam)
4558         ast_delete(varparam);
4559     ast_delete(var);
4560     for (i = 0; i < vec_size(params); ++i)
4561         ast_delete(params[i]);
4562     vec_free(params);
4563     return NULL;
4564 }
4565
4566 static ast_value *parse_arraysize(parser_t *parser, ast_value *var)
4567 {
4568     ast_expression *cexp;
4569     ast_value      *cval, *tmp;
4570     lex_ctx_t ctx;
4571
4572     ctx = parser_ctx(parser);
4573
4574     if (!parser_next(parser)) {
4575         ast_delete(var);
4576         parseerror(parser, "expected array-size");
4577         return NULL;
4578     }
4579
4580     if (parser->tok != ']') {
4581         cexp = parse_expression_leave(parser, true, false, false);
4582
4583         if (!cexp || !ast_istype(cexp, ast_value)) {
4584             if (cexp)
4585                 ast_unref(cexp);
4586             ast_delete(var);
4587             parseerror(parser, "expected array-size as constant positive integer");
4588             return NULL;
4589         }
4590         cval = (ast_value*)cexp;
4591     }
4592     else {
4593         cexp = NULL;
4594         cval = NULL;
4595     }
4596
4597     tmp = ast_value_new(ctx, "<type[]>", TYPE_ARRAY);
4598     tmp->expression.next = (ast_expression*)var;
4599     var = tmp;
4600
4601     if (cval) {
4602         if (cval->expression.vtype == TYPE_INTEGER)
4603             tmp->expression.count = cval->constval.vint;
4604         else if (cval->expression.vtype == TYPE_FLOAT)
4605             tmp->expression.count = cval->constval.vfloat;
4606         else {
4607             ast_unref(cexp);
4608             ast_delete(var);
4609             parseerror(parser, "array-size must be a positive integer constant");
4610             return NULL;
4611         }
4612
4613         ast_unref(cexp);
4614     } else {
4615         var->expression.count = -1;
4616         var->expression.flags |= AST_FLAG_ARRAY_INIT;
4617     }
4618
4619     if (parser->tok != ']') {
4620         ast_delete(var);
4621         parseerror(parser, "expected ']' after array-size");
4622         return NULL;
4623     }
4624     if (!parser_next(parser)) {
4625         ast_delete(var);
4626         parseerror(parser, "error after parsing array size");
4627         return NULL;
4628     }
4629     return var;
4630 }
4631
4632 /* Parse a complete typename.
4633  * for single-variables (ie. function parameters or typedefs) storebase should be NULL
4634  * but when parsing variables separated by comma
4635  * 'storebase' should point to where the base-type should be kept.
4636  * The base type makes up every bit of type information which comes *before* the
4637  * variable name.
4638  *
4639  * The following will be parsed in its entirety:
4640  *     void() foo()
4641  * The 'basetype' in this case is 'void()'
4642  * and if there's a comma after it, say:
4643  *     void() foo(), bar
4644  * then the type-information 'void()' can be stored in 'storebase'
4645  */
4646 static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef)
4647 {
4648     ast_value *var, *tmp;
4649     lex_ctx_t    ctx;
4650
4651     const char *name = NULL;
4652     bool        isfield  = false;
4653     bool        wasarray = false;
4654     size_t      morefields = 0;
4655
4656     ctx = parser_ctx(parser);
4657
4658     /* types may start with a dot */
4659     if (parser->tok == '.') {
4660         isfield = true;
4661         /* if we parsed a dot we need a typename now */
4662         if (!parser_next(parser)) {
4663             parseerror(parser, "expected typename for field definition");
4664             return NULL;
4665         }
4666
4667         /* Further dots are handled seperately because they won't be part of the
4668          * basetype
4669          */
4670         while (parser->tok == '.') {
4671             ++morefields;
4672             if (!parser_next(parser)) {
4673                 parseerror(parser, "expected typename for field definition");
4674                 return NULL;
4675             }
4676         }
4677     }
4678     if (parser->tok == TOKEN_IDENT)
4679         cached_typedef = parser_find_typedef(parser, parser_tokval(parser), 0);
4680     if (!cached_typedef && parser->tok != TOKEN_TYPENAME) {
4681         parseerror(parser, "expected typename");
4682         return NULL;
4683     }
4684
4685     /* generate the basic type value */
4686     if (cached_typedef) {
4687         var = ast_value_copy(cached_typedef);
4688         ast_value_set_name(var, "<type(from_def)>");
4689     } else
4690         var = ast_value_new(ctx, "<type>", parser_token(parser)->constval.t);
4691
4692     for (; morefields; --morefields) {
4693         tmp = ast_value_new(ctx, "<.type>", TYPE_FIELD);
4694         tmp->expression.next = (ast_expression*)var;
4695         var = tmp;
4696     }
4697
4698     /* do not yet turn into a field - remember:
4699      * .void() foo; is a field too
4700      * .void()() foo; is a function
4701      */
4702
4703     /* parse on */
4704     if (!parser_next(parser)) {
4705         ast_delete(var);
4706         parseerror(parser, "parse error after typename");
4707         return NULL;
4708     }
4709
4710     /* an opening paren now starts the parameter-list of a function
4711      * this is where original-QC has parameter lists.
4712      * We allow a single parameter list here.
4713      * Much like fteqcc we don't allow `float()() x`
4714      */
4715     if (parser->tok == '(') {
4716         var = parse_parameter_list(parser, var);
4717         if (!var)
4718             return NULL;
4719     }
4720
4721     /* store the base if requested */
4722     if (storebase) {
4723         *storebase = ast_value_copy(var);
4724         if (isfield) {
4725             tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
4726             tmp->expression.next = (ast_expression*)*storebase;
4727             *storebase = tmp;
4728         }
4729     }
4730
4731     /* there may be a name now */
4732     if (parser->tok == TOKEN_IDENT) {
4733         name = util_strdup(parser_tokval(parser));
4734         /* parse on */
4735         if (!parser_next(parser)) {
4736             ast_delete(var);
4737             mem_d(name);
4738             parseerror(parser, "error after variable or field declaration");
4739             return NULL;
4740         }
4741     }
4742
4743     /* now this may be an array */
4744     if (parser->tok == '[') {
4745         wasarray = true;
4746         var = parse_arraysize(parser, var);
4747         if (!var) {
4748             if (name) mem_d(name);
4749             return NULL;
4750         }
4751     }
4752
4753     /* This is the point where we can turn it into a field */
4754     if (isfield) {
4755         /* turn it into a field if desired */
4756         tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
4757         tmp->expression.next = (ast_expression*)var;
4758         var = tmp;
4759     }
4760
4761     /* now there may be function parens again */
4762     if (parser->tok == '(' && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4763         parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
4764     if (parser->tok == '(' && wasarray)
4765         parseerror(parser, "arrays as part of a return type is not supported");
4766     while (parser->tok == '(') {
4767         var = parse_parameter_list(parser, var);
4768         if (!var) {
4769             if (name) mem_d(name);
4770             return NULL;
4771         }
4772     }
4773
4774     /* finally name it */
4775     if (name) {
4776         if (!ast_value_set_name(var, name)) {
4777             ast_delete(var);
4778             mem_d(name);
4779             parseerror(parser, "internal error: failed to set name");
4780             return NULL;
4781         }
4782         /* free the name, ast_value_set_name duplicates */
4783         mem_d(name);
4784     }
4785
4786     return var;
4787 }
4788
4789 static bool parse_typedef(parser_t *parser)
4790 {
4791     ast_value      *typevar, *oldtype;
4792     ast_expression *old;
4793
4794     typevar = parse_typename(parser, NULL, NULL);
4795
4796     if (!typevar)
4797         return false;
4798
4799     if ( (old = parser_find_var(parser, typevar->name)) ) {
4800         parseerror(parser, "cannot define a type with the same name as a variable: %s\n"
4801                    " -> `%s` has been declared here: %s:%i",
4802                    typevar->name, ast_ctx(old).file, ast_ctx(old).line);
4803         ast_delete(typevar);
4804         return false;
4805     }
4806
4807     if ( (oldtype = parser_find_typedef(parser, typevar->name, vec_last(parser->_blocktypedefs))) ) {
4808         parseerror(parser, "type `%s` has already been declared here: %s:%i",
4809                    typevar->name, ast_ctx(oldtype).file, ast_ctx(oldtype).line);
4810         ast_delete(typevar);
4811         return false;
4812     }
4813
4814     vec_push(parser->_typedefs, typevar);
4815     util_htset(vec_last(parser->typedefs), typevar->name, typevar);
4816
4817     if (parser->tok != ';') {
4818         parseerror(parser, "expected semicolon after typedef");
4819         return false;
4820     }
4821     if (!parser_next(parser)) {
4822         parseerror(parser, "parse error after typedef");
4823         return false;
4824     }
4825
4826     return true;
4827 }
4828
4829 static const char *cvq_to_str(int cvq) {
4830     switch (cvq) {
4831         case CV_NONE:  return "none";
4832         case CV_VAR:   return "`var`";
4833         case CV_CONST: return "`const`";
4834         default:       return "<INVALID>";
4835     }
4836 }
4837
4838 static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, const ast_value *proto)
4839 {
4840     bool av, ao;
4841     if (proto->cvq != var->cvq) {
4842         if (!(proto->cvq == CV_CONST && var->cvq == CV_NONE &&
4843               !OPTS_FLAG(INITIALIZED_NONCONSTANTS) &&
4844               parser->tok == '='))
4845         {
4846             return !parsewarning(parser, WARN_DIFFERENT_QUALIFIERS,
4847                                  "`%s` declared with different qualifiers: %s\n"
4848                                  " -> previous declaration here: %s:%i uses %s",
4849                                  var->name, cvq_to_str(var->cvq),
4850                                  ast_ctx(proto).file, ast_ctx(proto).line,
4851                                  cvq_to_str(proto->cvq));
4852         }
4853     }
4854     av = (var  ->expression.flags & AST_FLAG_NORETURN);
4855     ao = (proto->expression.flags & AST_FLAG_NORETURN);
4856     if (!av != !ao) {
4857         return !parsewarning(parser, WARN_DIFFERENT_ATTRIBUTES,
4858                              "`%s` declared with different attributes%s\n"
4859                              " -> previous declaration here: %s:%i",
4860                              var->name, (av ? ": noreturn" : ""),
4861                              ast_ctx(proto).file, ast_ctx(proto).line,
4862                              (ao ? ": noreturn" : ""));
4863     }
4864     return true;
4865 }
4866
4867 static bool create_array_accessors(parser_t *parser, ast_value *var)
4868 {
4869     char name[1024];
4870     util_snprintf(name, sizeof(name), "%s##SET", var->name);
4871     if (!parser_create_array_setter(parser, var, name))
4872         return false;
4873     util_snprintf(name, sizeof(name), "%s##GET", var->name);
4874     if (!parser_create_array_getter(parser, var, var->expression.next, name))
4875         return false;
4876     return true;
4877 }
4878
4879 static bool parse_array(parser_t *parser, ast_value *array)
4880 {
4881     size_t i;
4882     if (array->initlist) {
4883         parseerror(parser, "array already initialized elsewhere");
4884         return false;
4885     }
4886     if (!parser_next(parser)) {
4887         parseerror(parser, "parse error in array initializer");
4888         return false;
4889     }
4890     i = 0;
4891     while (parser->tok != '}') {
4892         ast_value *v = (ast_value*)parse_expression_leave(parser, true, false, false);
4893         if (!v)
4894             return false;
4895         if (!ast_istype(v, ast_value) || !v->hasvalue || v->cvq != CV_CONST) {
4896             ast_unref(v);
4897             parseerror(parser, "initializing element must be a compile time constant");
4898             return false;
4899         }
4900         vec_push(array->initlist, v->constval);
4901         if (v->expression.vtype == TYPE_STRING) {
4902             array->initlist[i].vstring = util_strdupe(array->initlist[i].vstring);
4903             ++i;
4904         }
4905         ast_unref(v);
4906         if (parser->tok == '}')
4907             break;
4908         if (parser->tok != ',' || !parser_next(parser)) {
4909             parseerror(parser, "expected comma or '}' in element list");
4910             return false;
4911         }
4912     }
4913     if (!parser_next(parser) || parser->tok != ';') {
4914         parseerror(parser, "expected semicolon after initializer, got %s");
4915         return false;
4916     }
4917     /*
4918     if (!parser_next(parser)) {
4919         parseerror(parser, "parse error after initializer");
4920         return false;
4921     }
4922     */
4923
4924     if (array->expression.flags & AST_FLAG_ARRAY_INIT) {
4925         if (array->expression.count != (size_t)-1) {
4926             parseerror(parser, "array `%s' has already been initialized with %u elements",
4927                        array->name, (unsigned)array->expression.count);
4928         }
4929         array->expression.count = vec_size(array->initlist);
4930         if (!create_array_accessors(parser, array))
4931             return false;
4932     }
4933     return true;
4934 }
4935
4936 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)
4937 {
4938     ast_value *var;
4939     ast_value *proto;
4940     ast_expression *old;
4941     bool       was_end;
4942     size_t     i;
4943
4944     ast_value *basetype = NULL;
4945     bool      retval    = true;
4946     bool      isparam   = false;
4947     bool      isvector  = false;
4948     bool      cleanvar  = true;
4949     bool      wasarray  = false;
4950
4951     ast_member *me[3] = { NULL, NULL, NULL };
4952
4953     if (!localblock && is_static)
4954         parseerror(parser, "`static` qualifier is not supported in global scope");
4955
4956     /* get the first complete variable */
4957     var = parse_typename(parser, &basetype, cached_typedef);
4958     if (!var) {
4959         if (basetype)
4960             ast_delete(basetype);
4961         return false;
4962     }
4963
4964     while (true) {
4965         proto = NULL;
4966         wasarray = false;
4967
4968         /* Part 0: finish the type */
4969         if (parser->tok == '(') {
4970             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4971                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
4972             var = parse_parameter_list(parser, var);
4973             if (!var) {
4974                 retval = false;
4975                 goto cleanup;
4976             }
4977         }
4978         /* we only allow 1-dimensional arrays */
4979         if (parser->tok == '[') {
4980             wasarray = true;
4981             var = parse_arraysize(parser, var);
4982             if (!var) {
4983                 retval = false;
4984                 goto cleanup;
4985             }
4986         }
4987         if (parser->tok == '(' && wasarray) {
4988             parseerror(parser, "arrays as part of a return type is not supported");
4989             /* we'll still parse the type completely for now */
4990         }
4991         /* for functions returning functions */
4992         while (parser->tok == '(') {
4993             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC)
4994                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
4995             var = parse_parameter_list(parser, var);
4996             if (!var) {
4997                 retval = false;
4998                 goto cleanup;
4999             }
5000         }
5001
5002         var->cvq = qualifier;
5003         var->expression.flags |= qflags;
5004
5005         /*
5006          * store the vstring back to var for alias and
5007          * deprecation messages.
5008          */
5009         if (var->expression.flags & AST_FLAG_DEPRECATED ||
5010             var->expression.flags & AST_FLAG_ALIAS)
5011             var->desc = vstring;
5012
5013         /* Part 1:
5014          * check for validity: (end_sys_..., multiple-definitions, prototypes, ...)
5015          * Also: if there was a prototype, `var` will be deleted and set to `proto` which
5016          * is then filled with the previous definition and the parameter-names replaced.
5017          */
5018         if (!strcmp(var->name, "nil")) {
5019             if (OPTS_FLAG(UNTYPED_NIL)) {
5020                 if (!localblock || !OPTS_FLAG(PERMISSIVE))
5021                     parseerror(parser, "name `nil` not allowed (try -fpermissive)");
5022             } else
5023                 (void)!parsewarning(parser, WARN_RESERVED_NAMES, "variable name `nil` is reserved");
5024         }
5025         if (!localblock) {
5026             /* Deal with end_sys_ vars */
5027             was_end = false;
5028             if (!strcmp(var->name, "end_sys_globals")) {
5029                 var->uses++;
5030                 parser->crc_globals = vec_size(parser->globals);
5031                 was_end = true;
5032             }
5033             else if (!strcmp(var->name, "end_sys_fields")) {
5034                 var->uses++;
5035                 parser->crc_fields = vec_size(parser->fields);
5036                 was_end = true;
5037             }
5038             if (was_end && var->expression.vtype == TYPE_FIELD) {
5039                 if (parsewarning(parser, WARN_END_SYS_FIELDS,
5040                                  "global '%s' hint should not be a field",
5041                                  parser_tokval(parser)))
5042                 {
5043                     retval = false;
5044                     goto cleanup;
5045                 }
5046             }
5047
5048             if (!nofields && var->expression.vtype == TYPE_FIELD)
5049             {
5050                 /* deal with field declarations */
5051                 old = parser_find_field(parser, var->name);
5052                 if (old) {
5053                     if (parsewarning(parser, WARN_FIELD_REDECLARED, "field `%s` already declared here: %s:%i",
5054                                      var->name, ast_ctx(old).file, (int)ast_ctx(old).line))
5055                     {
5056                         retval = false;
5057                         goto cleanup;
5058                     }
5059                     ast_delete(var);
5060                     var = NULL;
5061                     goto skipvar;
5062                     /*
5063                     parseerror(parser, "field `%s` already declared here: %s:%i",
5064                                var->name, ast_ctx(old).file, ast_ctx(old).line);
5065                     retval = false;
5066                     goto cleanup;
5067                     */
5068                 }
5069                 if ((OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC || OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC) &&
5070                     (old = parser_find_global(parser, var->name)))
5071                 {
5072                     parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
5073                     parseerror(parser, "field `%s` already declared here: %s:%i",
5074                                var->name, ast_ctx(old).file, ast_ctx(old).line);
5075                     retval = false;
5076                     goto cleanup;
5077                 }
5078             }
5079             else
5080             {
5081                 /* deal with other globals */
5082                 old = parser_find_global(parser, var->name);
5083                 if (old && var->expression.vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION)
5084                 {
5085                     /* This is a function which had a prototype */
5086                     if (!ast_istype(old, ast_value)) {
5087                         parseerror(parser, "internal error: prototype is not an ast_value");
5088                         retval = false;
5089                         goto cleanup;
5090                     }
5091                     proto = (ast_value*)old;
5092                     proto->desc = var->desc;
5093                     if (!ast_compare_type((ast_expression*)proto, (ast_expression*)var)) {
5094                         parseerror(parser, "conflicting types for `%s`, previous declaration was here: %s:%i",
5095                                    proto->name,
5096                                    ast_ctx(proto).file, ast_ctx(proto).line);
5097                         retval = false;
5098                         goto cleanup;
5099                     }
5100                     /* we need the new parameter-names */
5101                     for (i = 0; i < vec_size(proto->expression.params); ++i)
5102                         ast_value_set_name(proto->expression.params[i], var->expression.params[i]->name);
5103                     if (!parser_check_qualifiers(parser, var, proto)) {
5104                         retval = false;
5105                         if (proto->desc)
5106                             mem_d(proto->desc);
5107                         proto = NULL;
5108                         goto cleanup;
5109                     }
5110                     proto->expression.flags |= var->expression.flags;
5111                     ast_delete(var);
5112                     var = proto;
5113                 }
5114                 else
5115                 {
5116                     /* other globals */
5117                     if (old) {
5118                         if (parsewarning(parser, WARN_DOUBLE_DECLARATION,
5119                                          "global `%s` already declared here: %s:%i",
5120                                          var->name, ast_ctx(old).file, ast_ctx(old).line))
5121                         {
5122                             retval = false;
5123                             goto cleanup;
5124                         }
5125                         proto = (ast_value*)old;
5126                         if (!ast_istype(old, ast_value)) {
5127                             parseerror(parser, "internal error: not an ast_value");
5128                             retval = false;
5129                             proto = NULL;
5130                             goto cleanup;
5131                         }
5132                         if (!parser_check_qualifiers(parser, var, proto)) {
5133                             retval = false;
5134                             proto = NULL;
5135                             goto cleanup;
5136                         }
5137                         proto->expression.flags |= var->expression.flags;
5138                         ast_delete(var);
5139                         var = proto;
5140                     }
5141                     if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC &&
5142                         (old = parser_find_field(parser, var->name)))
5143                     {
5144                         parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
5145                         parseerror(parser, "global `%s` already declared here: %s:%i",
5146                                    var->name, ast_ctx(old).file, ast_ctx(old).line);
5147                         retval = false;
5148                         goto cleanup;
5149                     }
5150                 }
5151             }
5152         }
5153         else /* it's not a global */
5154         {
5155             old = parser_find_local(parser, var->name, vec_size(parser->variables)-1, &isparam);
5156             if (old && !isparam) {
5157                 parseerror(parser, "local `%s` already declared here: %s:%i",
5158                            var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
5159                 retval = false;
5160                 goto cleanup;
5161             }
5162             old = parser_find_local(parser, var->name, 0, &isparam);
5163             if (old && isparam) {
5164                 if (parsewarning(parser, WARN_LOCAL_SHADOWS,
5165                                  "local `%s` is shadowing a parameter", var->name))
5166                 {
5167                     parseerror(parser, "local `%s` already declared here: %s:%i",
5168                                var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
5169                     retval = false;
5170                     goto cleanup;
5171                 }
5172                 if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
5173                     ast_delete(var);
5174                     var = NULL;
5175                     goto skipvar;
5176                 }
5177             }
5178         }
5179
5180         /* in a noref section we simply bump the usecount */
5181         if (noref || parser->noref)
5182             var->uses++;
5183
5184         /* Part 2:
5185          * Create the global/local, and deal with vector types.
5186          */
5187         if (!proto) {
5188             if (var->expression.vtype == TYPE_VECTOR)
5189                 isvector = true;
5190             else if (var->expression.vtype == TYPE_FIELD &&
5191                      var->expression.next->vtype == TYPE_VECTOR)
5192                 isvector = true;
5193
5194             if (isvector) {
5195                 if (!create_vector_members(var, me)) {
5196                     retval = false;
5197                     goto cleanup;
5198                 }
5199             }
5200
5201             if (!localblock) {
5202                 /* deal with global variables, fields, functions */
5203                 if (!nofields && var->expression.vtype == TYPE_FIELD && parser->tok != '=') {
5204                     var->isfield = true;
5205                     vec_push(parser->fields, (ast_expression*)var);
5206                     util_htset(parser->htfields, var->name, var);
5207                     if (isvector) {
5208                         for (i = 0; i < 3; ++i) {
5209                             vec_push(parser->fields, (ast_expression*)me[i]);
5210                             util_htset(parser->htfields, me[i]->name, me[i]);
5211                         }
5212                     }
5213                 }
5214                 else {
5215                     if (!(var->expression.flags & AST_FLAG_ALIAS)) {
5216                         parser_addglobal(parser, var->name, (ast_expression*)var);
5217                         if (isvector) {
5218                             for (i = 0; i < 3; ++i) {
5219                                 parser_addglobal(parser, me[i]->name, (ast_expression*)me[i]);
5220                             }
5221                         }
5222                     } else {
5223                         ast_expression *find  = parser_find_global(parser, var->desc);
5224
5225                         if (!find) {
5226                             compile_error(parser_ctx(parser), "undeclared variable `%s` for alias `%s`", var->desc, var->name);
5227                             return false;
5228                         }
5229
5230                         if (var->expression.vtype != find->vtype) {
5231                             char ty1[1024];
5232                             char ty2[1024];
5233
5234                             ast_type_to_string(find,                  ty1, sizeof(ty1));
5235                             ast_type_to_string((ast_expression*)var,  ty2, sizeof(ty2));
5236
5237                             compile_error(parser_ctx(parser), "incompatible types `%s` and `%s` for alias `%s`",
5238                                 ty1, ty2, var->name
5239                             );
5240                             return false;
5241                         }
5242
5243                         /*
5244                          * add alias to aliases table and to corrector
5245                          * so corrections can apply for aliases as well.
5246                          */
5247                         util_htset(parser->aliases, var->name, find);
5248
5249                         /*
5250                          * add to corrector so corrections can work
5251                          * even for aliases too.
5252                          */
5253                         correct_add (
5254                              vec_last(parser->correct_variables),
5255                             &vec_last(parser->correct_variables_score),
5256                             var->name
5257                         );
5258
5259                         /* generate aliases for vector components */
5260                         if (isvector) {
5261                             char *buffer[3];
5262
5263                             util_asprintf(&buffer[0], "%s_x", var->desc);
5264                             util_asprintf(&buffer[1], "%s_y", var->desc);
5265                             util_asprintf(&buffer[2], "%s_z", var->desc);
5266
5267                             util_htset(parser->aliases, me[0]->name, parser_find_global(parser, buffer[0]));
5268                             util_htset(parser->aliases, me[1]->name, parser_find_global(parser, buffer[1]));
5269                             util_htset(parser->aliases, me[2]->name, parser_find_global(parser, buffer[2]));
5270
5271                             mem_d(buffer[0]);
5272                             mem_d(buffer[1]);
5273                             mem_d(buffer[2]);
5274
5275                             /*
5276                              * add to corrector so corrections can work
5277                              * even for aliases too.
5278                              */
5279                             correct_add (
5280                                  vec_last(parser->correct_variables),
5281                                 &vec_last(parser->correct_variables_score),
5282                                 me[0]->name
5283                             );
5284                             correct_add (
5285                                  vec_last(parser->correct_variables),
5286                                 &vec_last(parser->correct_variables_score),
5287                                 me[1]->name
5288                             );
5289                             correct_add (
5290                                  vec_last(parser->correct_variables),
5291                                 &vec_last(parser->correct_variables_score),
5292                                 me[2]->name
5293                             );
5294                         }
5295                     }
5296                 }
5297             } else {
5298                 if (is_static) {
5299                     /* a static adds itself to be generated like any other global
5300                      * but is added to the local namespace instead
5301                      */
5302                     char   *defname = NULL;
5303                     size_t  prefix_len, ln;
5304
5305                     ln = strlen(parser->function->name);
5306                     vec_append(defname, ln, parser->function->name);
5307
5308                     vec_append(defname, 2, "::");
5309                     /* remember the length up to here */
5310                     prefix_len = vec_size(defname);
5311
5312                     /* Add it to the local scope */
5313                     util_htset(vec_last(parser->variables), var->name, (void*)var);
5314
5315                     /* corrector */
5316                     correct_add (
5317                          vec_last(parser->correct_variables),
5318                         &vec_last(parser->correct_variables_score),
5319                         var->name
5320                     );
5321
5322                     /* now rename the global */
5323                     ln = strlen(var->name);
5324                     vec_append(defname, ln, var->name);
5325                     ast_value_set_name(var, defname);
5326
5327                     /* push it to the to-be-generated globals */
5328                     vec_push(parser->globals, (ast_expression*)var);
5329
5330                     /* same game for the vector members */
5331                     if (isvector) {
5332                         for (i = 0; i < 3; ++i) {
5333                             util_htset(vec_last(parser->variables), me[i]->name, (void*)(me[i]));
5334
5335                             /* corrector */
5336                             correct_add(
5337                                  vec_last(parser->correct_variables),
5338                                 &vec_last(parser->correct_variables_score),
5339                                 me[i]->name
5340                             );
5341
5342                             vec_shrinkto(defname, prefix_len);
5343                             ln = strlen(me[i]->name);
5344                             vec_append(defname, ln, me[i]->name);
5345                             ast_member_set_name(me[i], defname);
5346
5347                             vec_push(parser->globals, (ast_expression*)me[i]);
5348                         }
5349                     }
5350                     vec_free(defname);
5351                 } else {
5352                     vec_push(localblock->locals, var);
5353                     parser_addlocal(parser, var->name, (ast_expression*)var);
5354                     if (isvector) {
5355                         for (i = 0; i < 3; ++i) {
5356                             parser_addlocal(parser, me[i]->name, (ast_expression*)me[i]);
5357                             ast_block_collect(localblock, (ast_expression*)me[i]);
5358                         }
5359                     }
5360                 }
5361             }
5362         }
5363         me[0] = me[1] = me[2] = NULL;
5364         cleanvar = false;
5365         /* Part 2.2
5366          * deal with arrays
5367          */
5368         if (var->expression.vtype == TYPE_ARRAY) {
5369             if (var->expression.count != (size_t)-1) {
5370                 if (!create_array_accessors(parser, var))
5371                     goto cleanup;
5372             }
5373         }
5374         else if (!localblock && !nofields &&
5375                  var->expression.vtype == TYPE_FIELD &&
5376                  var->expression.next->vtype == TYPE_ARRAY)
5377         {
5378             char name[1024];
5379             ast_expression *telem;
5380             ast_value      *tfield;
5381             ast_value      *array = (ast_value*)var->expression.next;
5382
5383             if (!ast_istype(var->expression.next, ast_value)) {
5384                 parseerror(parser, "internal error: field element type must be an ast_value");
5385                 goto cleanup;
5386             }
5387
5388             util_snprintf(name, sizeof(name), "%s##SETF", var->name);
5389             if (!parser_create_array_field_setter(parser, array, name))
5390                 goto cleanup;
5391
5392             telem = ast_type_copy(ast_ctx(var), array->expression.next);
5393             tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD);
5394             tfield->expression.next = telem;
5395             util_snprintf(name, sizeof(name), "%s##GETFP", var->name);
5396             if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) {
5397                 ast_delete(tfield);
5398                 goto cleanup;
5399             }
5400             ast_delete(tfield);
5401         }
5402
5403 skipvar:
5404         if (parser->tok == ';') {
5405             ast_delete(basetype);
5406             if (!parser_next(parser)) {
5407                 parseerror(parser, "error after variable declaration");
5408                 return false;
5409             }
5410             return true;
5411         }
5412
5413         if (parser->tok == ',')
5414             goto another;
5415
5416         /*
5417         if (!var || (!localblock && !nofields && basetype->expression.vtype == TYPE_FIELD)) {
5418         */
5419         if (!var) {
5420             parseerror(parser, "missing comma or semicolon while parsing variables");
5421             break;
5422         }
5423
5424         if (localblock && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
5425             if (parsewarning(parser, WARN_LOCAL_CONSTANTS,
5426                              "initializing expression turns variable `%s` into a constant in this standard",
5427                              var->name) )
5428             {
5429                 break;
5430             }
5431         }
5432
5433         if (parser->tok != '{' || var->expression.vtype != TYPE_FUNCTION) {
5434             if (parser->tok != '=') {
5435                 if (!strcmp(parser_tokval(parser), "break")) {
5436                     if (!parser_next(parser)) {
5437                         parseerror(parser, "error parsing break definition");
5438                         break;
5439                     }
5440                     (void)!!parsewarning(parser, WARN_BREAKDEF, "break definition ignored (suggest removing it)");
5441                 } else {
5442                     parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser));
5443                     break;
5444                 }
5445             }
5446
5447             if (!parser_next(parser)) {
5448                 parseerror(parser, "error parsing initializer");
5449                 break;
5450             }
5451         }
5452         else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
5453             parseerror(parser, "expected '=' before function body in this standard");
5454         }
5455
5456         if (parser->tok == '#') {
5457             ast_function *func   = NULL;
5458             ast_value    *number = NULL;
5459             float         fractional;
5460             float         integral;
5461             int           builtin_num;
5462
5463             if (localblock) {
5464                 parseerror(parser, "cannot declare builtins within functions");
5465                 break;
5466             }
5467             if (var->expression.vtype != TYPE_FUNCTION) {
5468                 parseerror(parser, "unexpected builtin number, '%s' is not a function", var->name);
5469                 break;
5470             }
5471             if (!parser_next(parser)) {
5472                 parseerror(parser, "expected builtin number");
5473                 break;
5474             }
5475
5476             if (OPTS_FLAG(EXPRESSIONS_FOR_BUILTINS)) {
5477                 number = (ast_value*)parse_expression_leave(parser, true, false, false);
5478                 if (!number) {
5479                     parseerror(parser, "builtin number expected");
5480                     break;
5481                 }
5482                 if (!ast_istype(number, ast_value) || !number->hasvalue || number->cvq != CV_CONST)
5483                 {
5484                     ast_unref(number);
5485                     parseerror(parser, "builtin number must be a compile time constant");
5486                     break;
5487                 }
5488                 if (number->expression.vtype == TYPE_INTEGER)
5489                     builtin_num = number->constval.vint;
5490                 else if (number->expression.vtype == TYPE_FLOAT)
5491                     builtin_num = number->constval.vfloat;
5492                 else {
5493                     ast_unref(number);
5494                     parseerror(parser, "builtin number must be an integer constant");
5495                     break;
5496                 }
5497                 ast_unref(number);
5498
5499                 fractional = modff(builtin_num, &integral);
5500                 if (builtin_num < 0 || fractional != 0) {
5501                     parseerror(parser, "builtin number must be an integer greater than zero");
5502                     break;
5503                 }
5504
5505                 /* we only want the integral part anyways */
5506                 builtin_num = integral;
5507             } else if (parser->tok == TOKEN_INTCONST) {
5508                 builtin_num = parser_token(parser)->constval.i;
5509             } else {
5510                 parseerror(parser, "builtin number must be a compile time constant");
5511                 break;
5512             }
5513
5514             if (var->hasvalue) {
5515                 (void)!parsewarning(parser, WARN_DOUBLE_DECLARATION,
5516                                     "builtin `%s` has already been defined\n"
5517                                     " -> previous declaration here: %s:%i",
5518                                     var->name, ast_ctx(var).file, (int)ast_ctx(var).line);
5519             }
5520             else
5521             {
5522                 func = ast_function_new(ast_ctx(var), var->name, var);
5523                 if (!func) {
5524                     parseerror(parser, "failed to allocate function for `%s`", var->name);
5525                     break;
5526                 }
5527                 vec_push(parser->functions, func);
5528
5529                 func->builtin = -builtin_num-1;
5530             }
5531
5532             if (OPTS_FLAG(EXPRESSIONS_FOR_BUILTINS)
5533                     ? (parser->tok != ',' && parser->tok != ';')
5534                     : (!parser_next(parser)))
5535             {
5536                 parseerror(parser, "expected comma or semicolon");
5537                 if (func)
5538                     ast_function_delete(func);
5539                 var->constval.vfunc = NULL;
5540                 break;
5541             }
5542         }
5543         else if (var->expression.vtype == TYPE_ARRAY && parser->tok == '{')
5544         {
5545             if (localblock) {
5546                 /* Note that fteqcc and most others don't even *have*
5547                  * local arrays, so this is not a high priority.
5548                  */
5549                 parseerror(parser, "TODO: initializers for local arrays");
5550                 break;
5551             }
5552
5553             var->hasvalue = true;
5554             if (!parse_array(parser, var))
5555                 break;
5556         }
5557         else if (var->expression.vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '['))
5558         {
5559             if (localblock) {
5560                 parseerror(parser, "cannot declare functions within functions");
5561                 break;
5562             }
5563
5564             if (proto)
5565                 ast_ctx(proto) = parser_ctx(parser);
5566
5567             if (!parse_function_body(parser, var))
5568                 break;
5569             ast_delete(basetype);
5570             for (i = 0; i < vec_size(parser->gotos); ++i)
5571                 parseerror(parser, "undefined label: `%s`", parser->gotos[i]->name);
5572             vec_free(parser->gotos);
5573             vec_free(parser->labels);
5574             return true;
5575         } else {
5576             ast_expression *cexp;
5577             ast_value      *cval;
5578
5579             cexp = parse_expression_leave(parser, true, false, false);
5580             if (!cexp)
5581                 break;
5582
5583             if (!localblock) {
5584                 cval = (ast_value*)cexp;
5585                 if (cval != parser->nil &&
5586                     (!ast_istype(cval, ast_value) || ((!cval->hasvalue || cval->cvq != CV_CONST) && !cval->isfield))
5587                    )
5588                 {
5589                     parseerror(parser, "cannot initialize a global constant variable with a non-constant expression");
5590                 }
5591                 else
5592                 {
5593                     if (!OPTS_FLAG(INITIALIZED_NONCONSTANTS) &&
5594                         qualifier != CV_VAR)
5595                     {
5596                         var->cvq = CV_CONST;
5597                     }
5598                     if (cval == parser->nil)
5599                         var->expression.flags |= AST_FLAG_INITIALIZED;
5600                     else
5601                     {
5602                         var->hasvalue = true;
5603                         if (cval->expression.vtype == TYPE_STRING)
5604                             var->constval.vstring = parser_strdup(cval->constval.vstring);
5605                         else if (cval->expression.vtype == TYPE_FIELD)
5606                             var->constval.vfield = cval;
5607                         else
5608                             memcpy(&var->constval, &cval->constval, sizeof(var->constval));
5609                         ast_unref(cval);
5610                     }
5611                 }
5612             } else {
5613                 int cvq;
5614                 shunt sy = { NULL, NULL, NULL, NULL };
5615                 cvq = var->cvq;
5616                 var->cvq = CV_NONE;
5617                 vec_push(sy.out, syexp(ast_ctx(var), (ast_expression*)var));
5618                 vec_push(sy.out, syexp(ast_ctx(cexp), (ast_expression*)cexp));
5619                 vec_push(sy.ops, syop(ast_ctx(var), parser->assign_op));
5620                 if (!parser_sy_apply_operator(parser, &sy))
5621                     ast_unref(cexp);
5622                 else {
5623                     if (vec_size(sy.out) != 1 && vec_size(sy.ops) != 0)
5624                         parseerror(parser, "internal error: leaked operands");
5625                     if (!ast_block_add_expr(localblock, (ast_expression*)sy.out[0].out))
5626                         break;
5627                 }
5628                 vec_free(sy.out);
5629                 vec_free(sy.ops);
5630                 vec_free(sy.argc);
5631                 var->cvq = cvq;
5632             }
5633         }
5634
5635 another:
5636         if (parser->tok == ',') {
5637             if (!parser_next(parser)) {
5638                 parseerror(parser, "expected another variable");
5639                 break;
5640             }
5641
5642             if (parser->tok != TOKEN_IDENT) {
5643                 parseerror(parser, "expected another variable");
5644                 break;
5645             }
5646             var = ast_value_copy(basetype);
5647             cleanvar = true;
5648             ast_value_set_name(var, parser_tokval(parser));
5649             if (!parser_next(parser)) {
5650                 parseerror(parser, "error parsing variable declaration");
5651                 break;
5652             }
5653             continue;
5654         }
5655
5656         if (parser->tok != ';') {
5657             parseerror(parser, "missing semicolon after variables");
5658             break;
5659         }
5660
5661         if (!parser_next(parser)) {
5662             parseerror(parser, "parse error after variable declaration");
5663             break;
5664         }
5665
5666         ast_delete(basetype);
5667         return true;
5668     }
5669
5670     if (cleanvar && var)
5671         ast_delete(var);
5672     ast_delete(basetype);
5673     return false;
5674
5675 cleanup:
5676     ast_delete(basetype);
5677     if (cleanvar && var)
5678         ast_delete(var);
5679     if (me[0]) ast_member_delete(me[0]);
5680     if (me[1]) ast_member_delete(me[1]);
5681     if (me[2]) ast_member_delete(me[2]);
5682     return retval;
5683 }
5684
5685 static bool parser_global_statement(parser_t *parser)
5686 {
5687     int        cvq       = CV_WRONG;
5688     bool       noref     = false;
5689     bool       is_static = false;
5690     uint32_t   qflags    = 0;
5691     ast_value *istype    = NULL;
5692     char      *vstring   = NULL;
5693
5694     if (parser->tok == TOKEN_IDENT)
5695         istype = parser_find_typedef(parser, parser_tokval(parser), 0);
5696
5697     if (istype || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
5698     {
5699         return parse_variable(parser, NULL, false, CV_NONE, istype, false, false, 0, NULL);
5700     }
5701     else if (parse_qualifiers(parser, false, &cvq, &noref, &is_static, &qflags, &vstring))
5702     {
5703         if (cvq == CV_WRONG)
5704             return false;
5705         return parse_variable(parser, NULL, true, cvq, NULL, noref, is_static, qflags, vstring);
5706     }
5707     else if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "enum"))
5708     {
5709         return parse_enum(parser);
5710     }
5711     else if (parser->tok == TOKEN_KEYWORD)
5712     {
5713         if (!strcmp(parser_tokval(parser), "typedef")) {
5714             if (!parser_next(parser)) {
5715                 parseerror(parser, "expected type definition after 'typedef'");
5716                 return false;
5717             }
5718             return parse_typedef(parser);
5719         }
5720         parseerror(parser, "unrecognized keyword `%s`", parser_tokval(parser));
5721         return false;
5722     }
5723     else if (parser->tok == '#')
5724     {
5725         return parse_pragma(parser);
5726     }
5727     else if (parser->tok == '$')
5728     {
5729         if (!parser_next(parser)) {
5730             parseerror(parser, "parse error");
5731             return false;
5732         }
5733     }
5734     else
5735     {
5736         parseerror(parser, "unexpected token: `%s`", parser->lex->tok.value);
5737         return false;
5738     }
5739     return true;
5740 }
5741
5742 static uint16_t progdefs_crc_sum(uint16_t old, const char *str)
5743 {
5744     return util_crc16(old, str, strlen(str));
5745 }
5746
5747 static void progdefs_crc_file(const char *str)
5748 {
5749     /* write to progdefs.h here */
5750     (void)str;
5751 }
5752
5753 static uint16_t progdefs_crc_both(uint16_t old, const char *str)
5754 {
5755     old = progdefs_crc_sum(old, str);
5756     progdefs_crc_file(str);
5757     return old;
5758 }
5759
5760 static void generate_checksum(parser_t *parser, ir_builder *ir)
5761 {
5762     uint16_t   crc = 0xFFFF;
5763     size_t     i;
5764     ast_value *value;
5765
5766     crc = progdefs_crc_both(crc, "\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{");
5767     crc = progdefs_crc_sum(crc, "\tint\tpad[28];\n");
5768     /*
5769     progdefs_crc_file("\tint\tpad;\n");
5770     progdefs_crc_file("\tint\tofs_return[3];\n");
5771     progdefs_crc_file("\tint\tofs_parm0[3];\n");
5772     progdefs_crc_file("\tint\tofs_parm1[3];\n");
5773     progdefs_crc_file("\tint\tofs_parm2[3];\n");
5774     progdefs_crc_file("\tint\tofs_parm3[3];\n");
5775     progdefs_crc_file("\tint\tofs_parm4[3];\n");
5776     progdefs_crc_file("\tint\tofs_parm5[3];\n");
5777     progdefs_crc_file("\tint\tofs_parm6[3];\n");
5778     progdefs_crc_file("\tint\tofs_parm7[3];\n");
5779     */
5780     for (i = 0; i < parser->crc_globals; ++i) {
5781         if (!ast_istype(parser->globals[i], ast_value))
5782             continue;
5783         value = (ast_value*)(parser->globals[i]);
5784         switch (value->expression.vtype) {
5785             case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
5786             case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
5787             case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
5788             case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break;
5789             default:
5790                 crc = progdefs_crc_both(crc, "\tint\t");
5791                 break;
5792         }
5793         crc = progdefs_crc_both(crc, value->name);
5794         crc = progdefs_crc_both(crc, ";\n");
5795     }
5796     crc = progdefs_crc_both(crc, "} globalvars_t;\n\ntypedef struct\n{\n");
5797     for (i = 0; i < parser->crc_fields; ++i) {
5798         if (!ast_istype(parser->fields[i], ast_value))
5799             continue;
5800         value = (ast_value*)(parser->fields[i]);
5801         switch (value->expression.next->vtype) {
5802             case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
5803             case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
5804             case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
5805             case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break;
5806             default:
5807                 crc = progdefs_crc_both(crc, "\tint\t");
5808                 break;
5809         }
5810         crc = progdefs_crc_both(crc, value->name);
5811         crc = progdefs_crc_both(crc, ";\n");
5812     }
5813     crc = progdefs_crc_both(crc, "} entvars_t;\n\n");
5814     ir->code->crc = crc;
5815 }
5816
5817 parser_t *parser_create()
5818 {
5819     parser_t *parser;
5820     lex_ctx_t empty_ctx;
5821     size_t i;
5822
5823     parser = (parser_t*)mem_a(sizeof(parser_t));
5824     if (!parser)
5825         return NULL;
5826
5827     memset(parser, 0, sizeof(*parser));
5828
5829     for (i = 0; i < operator_count; ++i) {
5830         if (operators[i].id == opid1('=')) {
5831             parser->assign_op = operators+i;
5832             break;
5833         }
5834     }
5835     if (!parser->assign_op) {
5836         printf("internal error: initializing parser: failed to find assign operator\n");
5837         mem_d(parser);
5838         return NULL;
5839     }
5840
5841     vec_push(parser->variables, parser->htfields  = util_htnew(PARSER_HT_SIZE));
5842     vec_push(parser->variables, parser->htglobals = util_htnew(PARSER_HT_SIZE));
5843     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
5844     vec_push(parser->_blocktypedefs, 0);
5845
5846     parser->aliases = util_htnew(PARSER_HT_SIZE);
5847
5848     /* corrector */
5849     vec_push(parser->correct_variables, correct_trie_new());
5850     vec_push(parser->correct_variables_score, NULL);
5851
5852     empty_ctx.file   = "<internal>";
5853     empty_ctx.line   = 0;
5854     empty_ctx.column = 0;
5855     parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL);
5856     parser->nil->cvq = CV_CONST;
5857     if (OPTS_FLAG(UNTYPED_NIL))
5858         util_htset(parser->htglobals, "nil", (void*)parser->nil);
5859
5860     parser->max_param_count = 1;
5861
5862     parser->const_vec[0] = ast_value_new(empty_ctx, "<vector.x>", TYPE_NOEXPR);
5863     parser->const_vec[1] = ast_value_new(empty_ctx, "<vector.y>", TYPE_NOEXPR);
5864     parser->const_vec[2] = ast_value_new(empty_ctx, "<vector.z>", TYPE_NOEXPR);
5865
5866     if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) {
5867         parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING);
5868         parser->reserved_version->cvq = CV_CONST;
5869         parser->reserved_version->hasvalue = true;
5870         parser->reserved_version->expression.flags |= AST_FLAG_INCLUDE_DEF;
5871         parser->reserved_version->constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
5872     } else {
5873         parser->reserved_version = NULL;
5874     }
5875
5876     parser->fold = fold_init(parser);
5877     return parser;
5878 }
5879
5880 static bool parser_compile(parser_t *parser)
5881 {
5882     /* initial lexer/parser state */
5883     parser->lex->flags.noops = true;
5884
5885     if (parser_next(parser))
5886     {
5887         while (parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR)
5888         {
5889             if (!parser_global_statement(parser)) {
5890                 if (parser->tok == TOKEN_EOF)
5891                     parseerror(parser, "unexpected end of file");
5892                 else if (compile_errors)
5893                     parseerror(parser, "there have been errors, bailing out");
5894                 lex_close(parser->lex);
5895                 parser->lex = NULL;
5896                 return false;
5897             }
5898         }
5899     } else {
5900         parseerror(parser, "parse error");
5901         lex_close(parser->lex);
5902         parser->lex = NULL;
5903         return false;
5904     }
5905
5906     lex_close(parser->lex);
5907     parser->lex = NULL;
5908
5909     return !compile_errors;
5910 }
5911
5912 bool parser_compile_file(parser_t *parser, const char *filename)
5913 {
5914     parser->lex = lex_open(filename);
5915     if (!parser->lex) {
5916         con_err("failed to open file \"%s\"\n", filename);
5917         return false;
5918     }
5919     return parser_compile(parser);
5920 }
5921
5922 bool parser_compile_string(parser_t *parser, const char *name, const char *str, size_t len)
5923 {
5924     parser->lex = lex_open_string(str, len, name);
5925     if (!parser->lex) {
5926         con_err("failed to create lexer for string \"%s\"\n", name);
5927         return false;
5928     }
5929     return parser_compile(parser);
5930 }
5931
5932 static void parser_remove_ast(parser_t *parser)
5933 {
5934     size_t i;
5935     if (parser->ast_cleaned)
5936         return;
5937     parser->ast_cleaned = true;
5938     for (i = 0; i < vec_size(parser->accessors); ++i) {
5939         ast_delete(parser->accessors[i]->constval.vfunc);
5940         parser->accessors[i]->constval.vfunc = NULL;
5941         ast_delete(parser->accessors[i]);
5942     }
5943     for (i = 0; i < vec_size(parser->functions); ++i) {
5944         ast_delete(parser->functions[i]);
5945     }
5946     for (i = 0; i < vec_size(parser->fields); ++i) {
5947         ast_delete(parser->fields[i]);
5948     }
5949     for (i = 0; i < vec_size(parser->globals); ++i) {
5950         ast_delete(parser->globals[i]);
5951     }
5952     vec_free(parser->accessors);
5953     vec_free(parser->functions);
5954     vec_free(parser->globals);
5955     vec_free(parser->fields);
5956
5957     for (i = 0; i < vec_size(parser->variables); ++i)
5958         util_htdel(parser->variables[i]);
5959     vec_free(parser->variables);
5960     vec_free(parser->_blocklocals);
5961     vec_free(parser->_locals);
5962
5963     /* corrector */
5964     for (i = 0; i < vec_size(parser->correct_variables); ++i) {
5965         correct_del(parser->correct_variables[i], parser->correct_variables_score[i]);
5966     }
5967     vec_free(parser->correct_variables);
5968     vec_free(parser->correct_variables_score);
5969
5970     for (i = 0; i < vec_size(parser->_typedefs); ++i)
5971         ast_delete(parser->_typedefs[i]);
5972     vec_free(parser->_typedefs);
5973     for (i = 0; i < vec_size(parser->typedefs); ++i)
5974         util_htdel(parser->typedefs[i]);
5975     vec_free(parser->typedefs);
5976     vec_free(parser->_blocktypedefs);
5977
5978     vec_free(parser->_block_ctx);
5979
5980     vec_free(parser->labels);
5981     vec_free(parser->gotos);
5982     vec_free(parser->breaks);
5983     vec_free(parser->continues);
5984
5985     ast_value_delete(parser->nil);
5986
5987     ast_value_delete(parser->const_vec[0]);
5988     ast_value_delete(parser->const_vec[1]);
5989     ast_value_delete(parser->const_vec[2]);
5990
5991     if (parser->reserved_version)
5992         ast_value_delete(parser->reserved_version);
5993
5994     util_htdel(parser->aliases);
5995     intrin_intrinsics_destroy(parser);
5996     fold_cleanup(parser->fold);
5997 }
5998
5999 void parser_cleanup(parser_t *parser)
6000 {
6001     parser_remove_ast(parser);
6002     mem_d(parser);
6003 }
6004
6005 bool parser_finish(parser_t *parser, const char *output)
6006 {
6007     size_t i;
6008     ir_builder *ir;
6009     bool retval = true;
6010
6011     if (compile_errors) {
6012         con_out("*** there were compile errors\n");
6013         return false;
6014     }
6015
6016     ir = ir_builder_new("gmqcc_out");
6017     if (!ir) {
6018         con_out("failed to allocate builder\n");
6019         return false;
6020     }
6021
6022     for (i = 0; i < vec_size(parser->fields); ++i) {
6023         ast_value *field;
6024         bool hasvalue;
6025         if (!ast_istype(parser->fields[i], ast_value))
6026             continue;
6027         field = (ast_value*)parser->fields[i];
6028         hasvalue = field->hasvalue;
6029         field->hasvalue = false;
6030         if (!ast_global_codegen((ast_value*)field, ir, true)) {
6031             con_out("failed to generate field %s\n", field->name);
6032             ir_builder_delete(ir);
6033             return false;
6034         }
6035         if (hasvalue) {
6036             ir_value *ifld;
6037             ast_expression *subtype;
6038             field->hasvalue = true;
6039             subtype = field->expression.next;
6040             ifld = ir_builder_create_field(ir, field->name, subtype->vtype);
6041             if (subtype->vtype == TYPE_FIELD)
6042                 ifld->fieldtype = subtype->next->vtype;
6043             else if (subtype->vtype == TYPE_FUNCTION)
6044                 ifld->outtype = subtype->next->vtype;
6045             (void)!ir_value_set_field(field->ir_v, ifld);
6046         }
6047     }
6048     for (i = 0; i < vec_size(parser->globals); ++i) {
6049         ast_value *asvalue;
6050         if (!ast_istype(parser->globals[i], ast_value))
6051             continue;
6052         asvalue = (ast_value*)(parser->globals[i]);
6053         if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) {
6054             retval = retval && !compile_warning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE,
6055                                                 "unused global: `%s`", asvalue->name);
6056         }
6057         if (!ast_global_codegen(asvalue, ir, false)) {
6058             con_out("failed to generate global %s\n", asvalue->name);
6059             ir_builder_delete(ir);
6060             return false;
6061         }
6062     }
6063     /* Build function vararg accessor ast tree now before generating
6064      * immediates, because the accessors may add new immediates
6065      */
6066     for (i = 0; i < vec_size(parser->functions); ++i) {
6067         ast_function *f = parser->functions[i];
6068         if (f->varargs) {
6069             if (parser->max_param_count > vec_size(f->vtype->expression.params)) {
6070                 f->varargs->expression.count = parser->max_param_count - vec_size(f->vtype->expression.params);
6071                 if (!parser_create_array_setter_impl(parser, f->varargs)) {
6072                     con_out("failed to generate vararg setter for %s\n", f->name);
6073                     ir_builder_delete(ir);
6074                     return false;
6075                 }
6076                 if (!parser_create_array_getter_impl(parser, f->varargs)) {
6077                     con_out("failed to generate vararg getter for %s\n", f->name);
6078                     ir_builder_delete(ir);
6079                     return false;
6080                 }
6081             } else {
6082                 ast_delete(f->varargs);
6083                 f->varargs = NULL;
6084             }
6085         }
6086     }
6087     /* Now we can generate immediates */
6088     if (!fold_generate(parser->fold, ir))
6089         return false;
6090
6091     for (i = 0; i < vec_size(parser->globals); ++i) {
6092         ast_value *asvalue;
6093         if (!ast_istype(parser->globals[i], ast_value))
6094             continue;
6095         asvalue = (ast_value*)(parser->globals[i]);
6096         if (!(asvalue->expression.flags & AST_FLAG_INITIALIZED))
6097         {
6098             if (asvalue->cvq == CV_CONST && !asvalue->hasvalue)
6099                 (void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_CONSTANT,
6100                                        "uninitialized constant: `%s`",
6101                                        asvalue->name);
6102             else if ((asvalue->cvq == CV_NONE || asvalue->cvq == CV_CONST) && !asvalue->hasvalue)
6103                 (void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_GLOBAL,
6104                                        "uninitialized global: `%s`",
6105                                        asvalue->name);
6106         }
6107         if (!ast_generate_accessors(asvalue, ir)) {
6108             ir_builder_delete(ir);
6109             return false;
6110         }
6111     }
6112     for (i = 0; i < vec_size(parser->fields); ++i) {
6113         ast_value *asvalue;
6114         asvalue = (ast_value*)(parser->fields[i]->next);
6115
6116         if (!ast_istype((ast_expression*)asvalue, ast_value))
6117             continue;
6118         if (asvalue->expression.vtype != TYPE_ARRAY)
6119             continue;
6120         if (!ast_generate_accessors(asvalue, ir)) {
6121             ir_builder_delete(ir);
6122             return false;
6123         }
6124     }
6125     if (parser->reserved_version &&
6126         !ast_global_codegen(parser->reserved_version, ir, false))
6127     {
6128         con_out("failed to generate reserved::version");
6129         ir_builder_delete(ir);
6130         return false;
6131     }
6132     for (i = 0; i < vec_size(parser->functions); ++i) {
6133         ast_function *f = parser->functions[i];
6134         if (!ast_function_codegen(f, ir)) {
6135             con_out("failed to generate function %s\n", f->name);
6136             ir_builder_delete(ir);
6137             return false;
6138         }
6139     }
6140
6141     generate_checksum(parser, ir);
6142
6143     if (OPTS_OPTION_BOOL(OPTION_DUMP))
6144         ir_builder_dump(ir, con_out);
6145     for (i = 0; i < vec_size(parser->functions); ++i) {
6146         if (!ir_function_finalize(parser->functions[i]->ir_func)) {
6147             con_out("failed to finalize function %s\n", parser->functions[i]->name);
6148             ir_builder_delete(ir);
6149             return false;
6150         }
6151     }
6152     parser_remove_ast(parser);
6153
6154     if (compile_Werrors) {
6155         con_out("*** there were warnings treated as errors\n");
6156         compile_show_werrors();
6157         retval = false;
6158     }
6159
6160     if (retval) {
6161         if (OPTS_OPTION_BOOL(OPTION_DUMPFIN))
6162             ir_builder_dump(ir, con_out);
6163
6164         if (!ir_builder_generate(ir, output)) {
6165             con_out("*** failed to generate output file\n");
6166             ir_builder_delete(ir);
6167             return false;
6168         }
6169     }
6170     ir_builder_delete(ir);
6171     return retval;
6172 }