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