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