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