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