2 * QuakeC compiler for Doom2D:TL!, based on FTEQCC
3 * Copyright (C) 1996-1997 Id Software, Inc.
4 * Also copyright FrikQCC and FTEQCC authors
5 * Copyright (C) 2013 Ketmar Dark
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 static const char *basictypenames
[] = {
37 qccbool flag_assume_integer
; // is that an integer or a float? qcc says float. but we support int too, so maybe we want that instead?
39 qccbool opt_overlaptemps
; // reduce numpr_globals by reuse of temps: when they are not needed they are freed for reuse
40 qccbool opt_shortenifnots
; // if(!var) is made an IF rather than NOT IFNOT
41 qccbool opt_nonvec_parms
; // store_f instead of store_v on function calls, where possible
42 qccbool opt_constant_names
; // take out the defs and name strings of constants
43 qccbool opt_constant_names_strings
; // removes the defs of strings too (plays havok with multiprogs)
44 qccbool opt_unreferenced
; // strip defs that are not referenced
45 qccbool opt_locals
= 0; // strip out the names of locals and immediates
46 qccbool opt_compound_jumps
; // jumps to jump statements jump to the final point
47 qccbool opt_locals_marshalling
; // make the local vars of all functions occupy the same globals
48 qccbool opt_vectorcalls
; // vectors can be packed into 3 floats, which can yield lower numpr_globals, but cost two more statements per call
49 qccbool opt_simplifiedifs
; // if (f != 0) -> if (f). if (f == 0) -> ifnot (f)
51 //these are the results of the opt_. The values are printed out when compilation is compleate, showing effectivness.
52 int optres_shortenifnots
;
53 int optres_assignments
;
54 int optres_overlaptemps
;
55 int optres_noduplicatestrings
;
56 int optres_constantarith
;
57 int optres_nonvec_parms
;
58 int optres_constant_names
;
59 int optres_constant_names_strings
;
60 int optres_unreferenced
;
62 int optres_dupconstdefs
;
63 int optres_compound_jumps
;
64 int optres_locals_marshalling
;
67 qccbool expandedemptymacro
;
70 //QCC_def_t **pr_global_defs/*[MAX_REGS]*/; // to find def for a global variable
72 //keeps track of how many funcs are called while parsing a statement
73 //int qcc_functioncalled;
75 //========================================
77 QCC_def_t
*pr_scope
; // the function being parsed, or NULL
79 QCC_string_t s_file
, s_file2
; // filename for function definition
81 unsigned int locals_start
; // for tracking local variables vs temps
82 unsigned int locals_end
; // for tracking local variables vs temps
84 jmp_buf pr_parse_abort
; // longjump with this on parse error
86 qccbool qcc_usefulstatement
;
97 QCC_def_t
**pr_casesdef
;
98 QCC_def_t
**pr_casesdef2
;
108 gotooperator_t
*pr_labels
;
109 gotooperator_t
*pr_gotos
;
113 QCC_def_t
*extra_parms
[MAX_EXTRA_PARMS
];
115 static int conditional
;
116 temp_t
*functemps
; // floats/strings/funcs/ents...
118 static int constchecks
;
119 static int varchecks
;
120 static int typechecks
;
123 typedef struct freeoffset_s
{
124 struct freeoffset_s
*next
;
129 freeoffset_t
*qcc_freeofs
;
132 ////////////////////////////////////////////////////////////////////////////////
133 #include "qcc_pr_comp_operators.c"
136 ////////////////////////////////////////////////////////////////////////////////
137 static QCC_def_t
*QCC_SupplyConversion (QCC_def_t
*var
, qcc_etype wanted
, qccbool fatal
);
139 static void QCC_PR_ParseStatement (qccbool nosublocs
);
140 static QCC_def_t
*QCC_PR_Statement (const QCC_opcode_t
*op
, QCC_def_t
*var_a
, QCC_def_t
*var_b
, QCC_dstatement_t
**outstatement
);
141 static QCC_dstatement_t
*QCC_PR_SimpleStatement (int op
, int var_a
, int var_b
, int var_c
, int force
);
142 static int QCC_AStatementJumpsTo (int targ
, int first
, int last
);
143 static qccbool
QCC_StatementIsAJump (int stnum
, int notifdest
);
144 static QCC_def_t
*QCC_PR_DummyDef (QCC_type_t
*type
, const char *name
, QCC_def_t
*scope
, int arraysize
, unsigned int ofs
, int referable
, qccbool saved
);
146 static gofs_t
QCC_GetFreeOffsetSpace (unsigned int size
);
148 static void QCC_WriteAsmFunction (QCC_def_t
*sc
, unsigned int firststatement
, gofs_t firstparm
);
152 EXPR_WARN_ABOVE_1
= 2,
153 EXPR_DISALLOW_COMMA
= 4,
154 EXPR_DISALLOW_FCALL
= 8
157 static QCC_def_t
*QCC_PR_Expression (int priority
, int exprflags
);
160 ////////////////////////////////////////////////////////////////////////////////
161 static inline qccbool
is_branch_op (int op
) {
163 case OP_IF_I
: case OP_IFNOT_I
:
164 case OP_IF_S
: case OP_IFNOT_S
:
165 case OP_IF_F
: case OP_IFNOT_F
:
173 static inline int branch_dest (int opofs
) {
174 return opofs
+statements
[opofs
].sargs
[statements
[opofs
].op
== OP_GOTO
? 0 : 1];
178 ////////////////////////////////////////////////////////////////////////////////
179 static inline qccbool
OpAssignsToC (unsigned int op
) {
180 // calls, switches and cases DON'T
181 if (pr_opcodes
[op
].type_c
== &type_void
) return qcc_false
;
182 if (op
>= OP_BITSET
&& op
<= OP_BITCLRP
) return qcc_false
;
183 /*if (op >= OP_STORE_I && op <= OP_STORE_FI) return qcc_false; <- add STOREP_*?*/
184 if (op
== OP_STOREP_C
/* || op == OP_LOADP_C*/) return qcc_false
;
185 if (op
>= OP_MULSTORE_F
&& op
<= OP_SUBSTOREP_V
) return qcc_false
;
191 static qccbool OpAssignsToB (unsigned int op) {
192 if (op >= OP_BITSET && op <= OP_BITCLRP) return qcc_true;
193 if (op >= OP_STORE_I && op <= OP_STORE_FI) return qcc_true;
194 if (op == OP_STOREP_C || op == OP_LOADP_C) return qcc_true;
195 if (op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V) return qcc_true;
196 if (op >= OP_STORE_F && op <= OP_STOREP_FNC) return qcc_true;
202 // no emulated opcodes
203 static inline qccbool
QCC_OPCodeValid (const QCC_opcode_t
*op
) {
204 return (op
-pr_opcodes
< OP_NUMREALOPS
);
208 //===========================================================================
209 static QCC_def_t
*QCC_MakeDummyIntConst (void) {
211 // allocate a new one
212 cn
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
214 pr
.def_tail
->next
= cn
;
216 cn
->type
= type_integer
;
217 cn
->name
= "IMMEDIATE";
218 cn
->constant
= qcc_true
;
220 cn
->scope
= NULL
; // always share immediates
222 // copy the immediate to the global area
223 cn
->ofs
= QCC_GetFreeOffsetSpace(type_size
[type_integer
->type
]);
224 G_INT(cn
->ofs
) = 666;
229 static QCC_def_t
*QCC_MakeIntConst (int value
) {
231 // check for a constant with the same value
232 for (cn
= pr
.def_head
.next
; cn
!= NULL
; cn
= cn
->next
) {
234 if (!cn
->initialized
) continue;
235 if (!cn
->constant
) continue;
237 if (cn
->type
!= type_integer
) continue;
239 if (G_INT(cn
->ofs
) == value
) return cn
;
241 // allocate a new one
242 cn
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
244 pr
.def_tail
->next
= cn
;
246 cn
->type
= type_integer
;
247 cn
->name
= "IMMEDIATE";
248 cn
->constant
= qcc_true
;
250 cn
->scope
= NULL
; // always share immediates
255 // copy the immediate to the global area
256 cn
->ofs
= QCC_GetFreeOffsetSpace(type_size
[type_integer
->type
]);
257 G_INT(cn
->ofs
) = value
;
263 static QCC_def_t
*QCC_MakeVectorConst (float a
, float b
, float c
) {
265 // check for a constant with the same value
266 for (cn
= pr
.def_head
.next
; cn
!= NULL
; cn
= cn
->next
) {
268 if (!cn
->initialized
) continue;
269 if (!cn
->constant
) continue;
271 if (cn
->type
!= type_vector
) continue;
273 if (G_FLOAT(cn
->ofs
+0) == a
&& G_FLOAT(cn
->ofs
+1) == b
&& G_FLOAT(cn
->ofs
+2) == c
) return cn
;
275 // allocate a new one
276 cn
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
278 pr
.def_tail
->next
= cn
;
280 cn
->type
= type_vector
;
281 cn
->name
= "IMMEDIATE";
282 cn
->constant
= qcc_true
;
284 cn
->scope
= NULL
; // always share immediates
286 // copy the immediate to the global area
287 cn
->ofs
= QCC_GetFreeOffsetSpace(type_size
[type_vector
->type
]);
288 G_FLOAT(cn
->ofs
+0) = a
;
289 G_FLOAT(cn
->ofs
+1) = b
;
290 G_FLOAT(cn
->ofs
+2) = c
;
295 static QCC_def_t
*QCC_MakeFloatConst (float value
) {
296 union QGG_GCC_PACKED
{
301 QCC_def_t
*cn
= Hash_GetKey(&floatconstdefstable
, fi
.i
);
303 // allocate a new one
304 cn
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
306 pr
.def_tail
->next
= cn
;
309 cn
->s_line
= pr_source_line
;
310 cn
->type
= type_float
;
311 cn
->name
= "IMMEDIATE";
312 cn
->constant
= qcc_true
;
314 cn
->scope
= NULL
; // always share immediates
316 // copy the immediate to the global area
317 cn
->ofs
= QCC_GetFreeOffsetSpace(type_size
[type_integer
->type
]);
318 Hash_AddKey(&floatconstdefstable
, fi
.i
, cn
, qccHunkAlloc(sizeof(hashtable_bucket_t
)));
319 G_FLOAT(cn
->ofs
) = value
;
324 static QCC_def_t
*QCC_MakeStringConstInternal (const char *value
, qccbool translate
) {
326 QCC_def_t
*cn
= Hash_Get(translate
?&stringconstdefstable_trans
:&stringconstdefstable
, value
);
328 // allocate a new one
331 snprintf(buf
, sizeof(buf
), "dotranslate_%d", ++dotranslate_count
);
332 cn
= (void *)qccHunkAlloc(sizeof(QCC_def_t
)+strlen(buf
)+1);
333 cn
->name
= (char *)(cn
+1);
334 strcpy(cn
->name
, buf
);
336 cn
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
337 cn
->name
= "IMMEDIATE";
340 pr
.def_tail
->next
= cn
;
342 cn
->type
= type_string
;
343 cn
->constant
= qcc_true
;
345 cn
->scope
= NULL
; // always share immediates
347 // copy the immediate to the global area
348 cn
->ofs
= QCC_GetFreeOffsetSpace(type_size
[type_integer
->type
]);
349 string
= QCC_CopyString(value
);
350 Hash_Add((translate
? &stringconstdefstable_trans
: &stringconstdefstable
), strings
+string
, cn
, qccHunkAlloc(sizeof(hashtable_bucket_t
)));
351 G_INT(cn
->ofs
) = string
;
356 static QCC_def_t
*QCC_MakeStringConst (const char *value
) {
357 return QCC_MakeStringConstInternal(value
, qcc_false
);
361 static QCC_def_t
*QCC_MakeTranslateStringConst (const char *value
) {
362 return QCC_MakeStringConstInternal(value
, qcc_true
);
366 //===========================================================================
367 //assistant functions. This can safly be bipassed with the old method for more complex things.
368 static gofs_t
QCC_GetFreeOffsetSpace (unsigned int size
) {
370 if (opt_locals_marshalling
) {
371 freeoffset_t
*fofs
, *prev
;
372 for (fofs
= qcc_freeofs
, prev
= NULL
; fofs
!= NULL
; fofs
= fofs
->next
) {
373 if (fofs
->size
== size
) {
374 if (prev
) prev
->next
= fofs
->next
; else qcc_freeofs
= fofs
->next
;
379 for (fofs
= qcc_freeofs
, prev
= NULL
; fofs
!= NULL
; fofs
= fofs
->next
) {
380 if (fofs
->size
> size
) {
383 return fofs
->ofs
-size
;
389 numpr_globals
+= size
;
390 if (numpr_globals
>= MAX_REGS
) {
391 if (!opt_overlaptemps
|| !opt_locals_marshalling
) {
392 QCC_Error(ERR_TOOMANYGLOBALS
, "numpr_globals exceeded MAX_REGS - you'll need to use more optimisations");
394 QCC_Error(ERR_TOOMANYGLOBALS
, "numpr_globals exceeded MAX_REGS");
401 static void QCC_FreeOffset (gofs_t ofs
, unsigned int size
) {
404 if (ofs+size == numpr_globals) {
405 //FIXME: is this a bug?
406 //k8: this SHOULD be a bug, i think: we need to allocate the
407 // whole chunk of 'globals', or some writes will miss
408 //numpr_globals -= size;
412 for (fofs
= qcc_freeofs
; fofs
!= NULL
; fofs
= fofs
->next
) {
413 //FIXME: if this means the last block becomes free, free them all.
414 if (fofs
->ofs
== ofs
+size
) {
419 if (fofs
->ofs
+fofs
->size
== ofs
) {
424 fofs
= qccHunkAlloc(sizeof(freeoffset_t
));
425 fofs
->next
= qcc_freeofs
;
433 static QCC_def_t
*QCC_GetTemp (QCC_type_t
*type
) {
434 QCC_def_t
*var_c
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
435 memset(var_c
, 0, sizeof(QCC_def_t
));
437 var_c
->name
= "temp";
438 if (opt_overlaptemps
|| opt_locals_marshalling
) {
439 temp_t
*t
= NULL
; // always allocate new one for opt_locals_marshalling
440 if (opt_overlaptemps
) {
441 // don't exceed; this lets us allocate a huge block, and still be able to compile smegging big funcs
442 for (t
= functemps
; t
; t
= t
->next
) if (!t
->used
&& t
->size
== type
->size
) break;
443 if (t
&& t
->scope
&& t
->scope
!= pr_scope
) QCC_Error(ERR_INTERNAL
, "Internal error temp has scope not equal to current scope");
444 if (t
) optres_overlaptemps
+= t
->size
;
448 t
= qccHunkAlloc(sizeof(temp_t
));
449 t
->size
= type
->size
;
452 t
->ofs
= QCC_GetFreeOffsetSpace(t
->size
);
457 t
->lastfunc
= pr_scope
;
459 // we're not going to reallocate any temps so allocate permanently
460 var_c
->ofs
= QCC_GetFreeOffsetSpace(type
->size
);
461 numtemps
+= type
->size
;
463 var_c
->s_file
= s_file
;
464 var_c
->s_line
= pr_source_line
;
465 if (var_c
->temp
) var_c
->temp
->used
= qcc_true
;
470 // nothing else references this temp.
471 static void QCC_FreeTemp (QCC_def_t
*t
) {
472 if (t
&& t
->temp
) t
->temp
->used
= qcc_false
;
476 static void QCC_UnFreeTemp (QCC_def_t
*t
) {
477 if (t
->temp
) t
->temp
->used
= qcc_true
;
481 // we've just parsed a statement
482 // we can gaurentee that any used temps are now not used
483 // this is just a debugging check, can be turned off
484 static void QCC_FreeTemps (void) {
485 if (def_ret
.temp
&& def_ret
.temp
->used
) {
486 QCC_PR_ParseWarning(WARN_DEBUGGING
, "Return value still in use in %s", pr_scope
->name
);
487 def_ret
.temp
->used
= qcc_false
;
489 for (temp_t
*t
= functemps
; t
!= NULL
; t
= t
->next
) {
490 if (t
->used
&& !pr_error_count
) {
491 // don't print this after an error jump out
492 QCC_PR_ParseWarning(WARN_DEBUGGING
, "Temp was used in %s", pr_scope
->name
);
499 void QCC_PurgeTemps (void) {
504 //temps that are still in use over a function call can be considered dodgy.
505 //we need to remap these to locally defined temps, on return from the function so we know we got them all.
506 static void QCC_LockActiveTemps (void) {
507 for (temp_t
*t
= functemps
; t
!= NULL
; t
= t
->next
) if (t
->used
) t
->scope
= pr_scope
;
511 static void QCC_LockTemp (QCC_def_t
*d
) {
512 if (d
->temp
&& d
->temp
->used
) d
->temp
->scope
= pr_scope
;
516 static void QCC_RemapLockedTemp (temp_t
*t
, int firststatement
, int laststatement
) {
522 QCC_dstatement_t
*st
;
525 for (i
= firststatement
, st
= &statements
[i
]; i
< laststatement
; ++i
, ++st
) {
526 if (pr_opcodes
[st
->op
].type_a
&& st
->a
== t
->ofs
) {
528 newofs
= QCC_GetFreeOffsetSpace(t
->size
);
530 def
= QCC_PR_DummyDef(type_float
, NULL
, pr_scope
, t
->size
, newofs
, qcc_false
, qcc_false
);
531 def
->nextlocal
= pr
.localvars
;
532 def
->constant
= qcc_false
;
534 snprintf(buffer
, sizeof(buffer
), "locked_%d", t
->ofs
);
535 def
->name
= qccHunkDupStr(buffer
);
541 if (pr_opcodes
[st
->op
].type_b
&& st
->b
== t
->ofs
) {
543 newofs
= QCC_GetFreeOffsetSpace(t
->size
);
545 def
= QCC_PR_DummyDef(type_float
, NULL
, pr_scope
, t
->size
, newofs
, qcc_false
, qcc_false
);
546 def
->nextlocal
= pr
.localvars
;
547 def
->constant
= qcc_false
;
549 snprintf(buffer
, sizeof(buffer
), "locked_%d", t
->ofs
);
550 def
->name
= qccHunkDupStr(buffer
);
556 if (pr_opcodes
[st
->op
].type_c
&& st
->c
== t
->ofs
) {
558 newofs
= QCC_GetFreeOffsetSpace(t
->size
);
560 def
= QCC_PR_DummyDef(type_float
, NULL
, pr_scope
, t
->size
, newofs
, qcc_false
, qcc_false
);
561 def
->nextlocal
= pr
.localvars
;
562 def
->constant
= qcc_false
;
564 snprintf(buffer
, sizeof(buffer
), "locked_%d", t
->ofs
);
565 def
->name
= qccHunkDupStr(buffer
);
575 static void QCC_RemapLockedTemps (int firststatement
, int laststatement
) {
576 for (temp_t
*t
= functemps
; t
!= NULL
; t
= t
->next
) {
577 if (t
->scope
|| opt_locals_marshalling
) {
578 QCC_RemapLockedTemp(t
, firststatement
, laststatement
);
586 static void QCC_fprintfLocals (FILE *f
, gofs_t paramstart
, gofs_t paramend
) {
588 for (const QCC_def_t
*var
= pr
.localvars
; var
!= NULL
; var
= var
->nextlocal
) {
589 if (var
->ofs
>= paramstart
&& var
->ofs
< paramend
) continue;
590 if (var
->arraysize
!= 1) {
591 fprintf(f
, "local %s %s[%d]; /* at %d */\n", QCC_TypeName(var
->type
), var
->name
, var
->arraysize
, var
->ofs
);
593 fprintf(f
, "local %s %s; /* at %d */\n", QCC_TypeName(var
->type
), var
->name
, var
->ofs
);
596 for (const temp_t
*t
= functemps
; t
!= NULL
; t
= t
->next
, ++i
) {
597 if (t
->lastfunc
== pr_scope
) {
598 fprintf(f
, "local %s temp_%d; /* at %d */\n", (t
->size
== 1 ? "float" : "vector"), i
, t
->ofs
);
605 static const char *QCC_VarAtOffset (unsigned int ofs
, unsigned int size
) {
606 static char message
[1024];
611 for (t
= functemps
, i
= 0; t
!= NULL
; t
= t
->next
, ++i
) {
612 if (ofs
>= t
->ofs
&& ofs
< t
->ofs
+t
->size
) {
613 if (size
< t
->size
) {
614 snprintf(message
, sizeof(message
), "temp_%i_%c", t
->ofs
, 'x'+(ofs
-t
->ofs
)%3);
616 snprintf(message
, sizeof(message
), "temp_%d", t
->ofs
);
621 for (var
= pr
.localvars
; var
!= NULL
; var
= var
->nextlocal
) {
622 if (var
->scope
&& var
->scope
!= pr_scope
) continue; // this should be an error
623 if (ofs
>= var
->ofs
&& ofs
< var
->ofs
+var
->type
->size
) {
625 if (!strcmp(var
->name
, "IMMEDIATE")) continue; // continue, don't get bogged down by multiple bits of code
626 if (size
< var
->type
->size
) {
627 snprintf(message
, sizeof(message
), "%s_%c", var
->name
, 'x'+(ofs
-var
->ofs
)%3);
629 snprintf(message
, sizeof(message
), "%s", var
->name
);
635 for (var
= pr
.def_head
.next
; var
!= NULL
; var
= var
->next
) {
636 if (var
->scope
&& var
->scope
!= pr_scope
) continue;
637 if (ofs
>= var
->ofs
&& ofs
< var
->ofs
+var
->type
->size
) {
639 if (!strcmp(var
->name
, "IMMEDIATE")) {
640 switch (var
->type
->type
) {
642 snprintf(message
, sizeof(message
), "\"%.1020s\"", &strings
[((const int *)qcc_pr_globals
)[var
->ofs
]]);
645 snprintf(message
, sizeof(message
), "%d", ((const int *)qcc_pr_globals
)[var
->ofs
]);
648 snprintf(message
, sizeof(message
), "%f", qcc_pr_globals
[var
->ofs
]);
651 snprintf(message
, sizeof(message
), "'%f %f %f'", qcc_pr_globals
[var
->ofs
], qcc_pr_globals
[var
->ofs
+1], qcc_pr_globals
[var
->ofs
+2]);
654 snprintf(message
, sizeof(message
), "IMMEDIATE");
658 if (size
< var
->type
->size
) {
659 snprintf(message
, sizeof(message
), "%s_%c", var
->name
, 'x'+(ofs
-var
->ofs
)%3);
661 snprintf(message
, sizeof(message
), "%s", var
->name
);
668 if (ofs
>= OFS_RETURN
&& ofs
< OFS_PARM0
) snprintf(message
, sizeof(message
), "return");
669 else if (ofs
>= OFS_PARM0
&& ofs
< OFS_PARM7
) snprintf(message
, sizeof(message
), "parm%d", (ofs
-OFS_PARM0
)/3);
670 else if (ofs
== OFS_PARMTHIS
) snprintf(message
, sizeof(message
), "parmthis");
671 else snprintf(message
, sizeof(message
), "offset_%d", ofs
);
673 if (ofs
>= OFS_RETURN
&& ofs
< OFS_PARM0
) snprintf(message
, sizeof(message
), "return_%c", 'x'+ofs
-OFS_RETURN
);
674 else if (ofs
>= OFS_PARM0
&& ofs
< OFS_PARM7
) snprintf(message
, sizeof(message
), "parm%i_%c", (ofs
-OFS_PARM0
)/3, 'x'+(ofs
-OFS_PARM0
)%3);
675 else if (ofs
== OFS_PARMTHIS
) snprintf(message
, sizeof(message
), "parmthis_shit");
676 else snprintf(message
, sizeof(message
), "offset_%d", ofs
);
683 #include "qcc_pr_comp_primstat.c"
690 Looks for a preexisting constant
693 static QCC_def_t
*QCC_PR_ParseImmediate (void) {
695 if (pr_immediate_type
== type_float
) {
696 cn
= QCC_MakeFloatConst(pr_immediate
._float
);
700 if (pr_immediate_type
== type_integer
) {
701 cn
= QCC_MakeIntConst(pr_immediate
._int
);
705 if (pr_immediate_type
== type_string
) {
707 if (strlen(pr_immediate_string
) > sizeof(tmp
)-1) QCC_PR_ParseError(ERR_INVALIDSTRINGIMMEDIATE
, "string too long");
708 snprintf(tmp
, sizeof(tmp
), "%s", pr_immediate_string
);
711 if (pr_token_type
== TT_IMMED
&& pr_token_type
== TT_IMMED
) {
712 if (strlen(tmp
)+strlen(pr_immediate_string
) > sizeof(tmp
)-1) {
713 QCC_PR_ParseError(ERR_INVALIDSTRINGIMMEDIATE
, "string too long");
715 strcat(tmp
, pr_immediate_string
);
721 cn
= QCC_MakeStringConst(tmp
);
724 // check for a constant with the same value
726 for (cn
= pr
.def_head
.next
; cn
!= NULL
; cn
= cn
->next
) {
727 if (!cn
->initialized
) continue;
728 if (!cn
->constant
) continue;
729 if (cn
->type
!= pr_immediate_type
) continue;
730 if (pr_immediate_type
== type_string
) {
731 if (strcmp(G_STRING(cn
->ofs
), pr_immediate_string
) == 0) {
735 } else if (pr_immediate_type
== type_float
) {
736 if (G_FLOAT(cn
->ofs
) == pr_immediate
._float
) {
740 } else if (pr_immediate_type
== type_integer
) {
741 if (G_INT(cn
->ofs
) == pr_immediate
._int
) {
745 } else if (pr_immediate_type
== type_vector
) {
746 if ((G_FLOAT(cn
->ofs
) == pr_immediate
.vector
[0]) &&
747 (G_FLOAT(cn
->ofs
+1) == pr_immediate
.vector
[1]) &&
748 (G_FLOAT(cn
->ofs
+2) == pr_immediate
.vector
[2])) {
753 QCC_PR_ParseError(ERR_BADIMMEDIATETYPE
, "weird immediate type");
756 // allocate a new one
757 cn
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
759 pr
.def_tail
->next
= cn
;
761 cn
->type
= pr_immediate_type
;
762 cn
->name
= "IMMEDIATE";
763 cn
->constant
= qcc_true
;
765 cn
->scope
= NULL
; // always share immediates
766 // copy the immediate to the global area
767 cn
->ofs
= QCC_GetFreeOffsetSpace(type_size
[pr_immediate_type
->type
]);
768 if (pr_immediate_type
== type_string
) pr_immediate
.string
= QCC_CopyString(pr_immediate_string
);
769 memcpy (qcc_pr_globals
+cn
->ofs
, &pr_immediate
, 4*type_size
[pr_immediate_type
->type
]);
775 // warning, the func could have no name set if it's a field call
776 static QCC_def_t
*QCC_PR_GenerateFunctionCall (QCC_def_t
*func
, QCC_def_t
*arglist
[], int argcount
, QCC_def_t
*newself
) {
777 QCC_def_t
*d
, *oldret
, *oself
;
779 QCC_dstatement_t
*st
;
783 if (t
->type
!= ev_function
) QCC_PR_ParseErrorPrintDef(ERR_NOTAFUNCTION
, func
, "not a function");
784 // copy the arguments to the global parameter variables
785 if (newself
!= NULL
) {
786 // we're entering OO code with a different self
787 // eg: other::touch(self)
788 // note: we will allocate 'self' if there is none
789 d
= QCC_PR_GetDef(type_entity
, "self", NULL
, qcc_true
, 1, qcc_false
);
790 oself
= QCC_GetTemp(type_entity
);
792 QCC_PR_SimpleStatement(OP_STORE_ENT
, d
->ofs
, oself
->ofs
, 0, qcc_false
);
795 QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement-1].a, d->ofs, 0, qcc_false);
797 QCC_PR_Statement(&pr_opcodes
[OP_STORE_ENT
], newself
, d
, QCC_STAT_NOCONV
);
798 // if the args refered to self, update them to refer to oself instead (as self is now set to 'other')
799 for (int i
= 0; i
< argcount
; ++i
) if (arglist
[i
]->ofs
== d
->ofs
) arglist
[i
] = oself
;
805 // write the arguments
806 for (int i
= 0; i
< argcount
; ++i
) {
807 d
= (i
>= MAX_PARMS
? extra_parms
[i
-MAX_PARMS
] : &def_parms
[i
]);
808 if (arglist
[i
]->type
->size
> 1 || !opt_nonvec_parms
) {
809 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_V
], arglist
[i
], d
, QCC_STAT_NOCONV
));
811 d
->type
= arglist
[i
]->type
;
812 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_F
], arglist
[i
], d
, QCC_STAT_NOCONV
));
813 ++optres_nonvec_parms
;
816 // if the return value was in use, save it off now, so that it doesn't get clobbered
817 oldret
= (def_ret
.temp
->used
? QCC_GetTemp(def_ret
.type
) : NULL
);
818 // can free temps used for arguments now
819 if (oldret
&& !def_ret
.temp
->used
) {
820 QCC_FreeTemp(oldret
);
822 } else if (def_ret
.temp
->used
) {
823 if (def_ret
.type
->size
== 3) {
824 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_V
], &def_ret
, oldret
, QCC_STAT_NOCONV
));
826 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_F
], &def_ret
, oldret
, QCC_STAT_NOCONV
));
828 QCC_UnFreeTemp(oldret
);
829 QCC_UnFreeTemp(&def_ret
);
830 //k8:wtf?! QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
834 // we dont need to lock the local containing the function index because its thrown away after the call anyway
835 // (if a function is called in the argument list then it'll be locked as part of that call)
837 QCC_LockActiveTemps(); // any temps before are likely to be used with the return value
838 QCC_UnFreeTemp(func
);
840 if (argcount
> MAX_PARMS
) {
841 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_CALL0
+MAX_PARMS
], func
, 0, &st
));
842 } else if (argcount
) {
843 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_CALL0
+argcount
], func
, 0, &st
));
845 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_CALL0
], func
, 0, &st
));
847 // restore the class owner
849 QCC_PR_SimpleStatement(OP_STORE_ENT
, oself
->ofs
, d
->ofs
, 0, qcc_false
);
854 if (oldret
->temp
&& !oldret
->temp
->used
) QCC_PR_ParseWarning(0, "Ret was freed\n");
855 // if we preserved the ofs_ret global, restore it here
856 d
= QCC_GetTemp(t
->aux_type
);
857 if (t
->aux_type
->size
== 3) {
858 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes
+OP_STORE_V
, &def_ret
, d
, QCC_STAT_NOCONV
));
860 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes
+OP_STORE_F
, &def_ret
, d
, QCC_STAT_NOCONV
));
862 if (def_ret
.type
->size
== 3) {
863 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes
+OP_STORE_V
, oldret
, &def_ret
, QCC_STAT_NOCONV
));
865 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes
+OP_STORE_F
, oldret
, &def_ret
, QCC_STAT_NOCONV
));
867 QCC_FreeTemp(oldret
);
868 QCC_UnFreeTemp(&def_ret
);
872 def_ret
.type
= t
->aux_type
;
873 if (def_ret
.temp
->used
) QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT
, "Return value conflict -- output is inefficient");
874 def_ret
.temp
->used
= qcc_true
;
879 #include "qcc_pr_comp_intrinsics.c"
886 warning, the func could have no name set if it's a field call
887 opening paren should be eaten
890 static QCC_def_t
*QCC_PR_ParseFunctionCall (QCC_def_t
*func
, QCC_def_t
*newself
) {
893 int extraparms
= qcc_false
;
895 QCC_def_t
*param
[MAX_PARMS
+MAX_EXTRA_PARMS
];
899 if (t
->type
!= ev_function
) QCC_PR_ParseErrorPrintDef(ERR_NOTAFUNCTION
, func
, "not a function");
901 // these base functions have variable arguments. I would check for (...) args too,
902 // but that might be used for extended builtin functionality.
903 // (this code wouldn't compile otherwise)
905 for (size_t f
= 0; f
< sizeof(intrlist
)/sizeof(intrlist
[0]); ++f
) {
906 if (strcmp(func
->name
, intrlist
[f
].name
) == 0) return intrlist
[f
].fn(func
);
909 // so it's not an intrinsic
910 // copy the arguments to the global parameter variables
912 if (t
->num_parms
< 0) {
913 extraparms
= qcc_true
;
914 np
= -t
->num_parms
-1;
918 // any temps referenced to build the parameters don't need to be locked
919 if (!QCC_PR_EatDelim(")")) {
920 int dont_advance
= 0;
923 if (extraparms
&& arg
>= MAX_PARMS
) {
924 QCC_PR_ParseErrorPrintDef(ERR_TOOMANYPARAMETERSVARARGS
, func
, "More than %d parameters on varargs function", MAX_PARMS
);
925 } else if (arg
>= MAX_PARMS
+MAX_EXTRA_PARMS
) {
926 QCC_PR_ParseErrorPrintDef(ERR_TOOMANYTOTALPARAMETERS
, func
, "More than %d parameters", MAX_PARMS
+MAX_EXTRA_PARMS
);
928 if (!extraparms
&& arg
>= t
->num_parms
&& !p
) {
929 QCC_PR_ParseWarning(WARN_TOOMANYPARAMETERSFORFUNC
, "too many parameters");
930 QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC
, func
);
932 // with vectorcalls, we store the vector into the args as individual floats
933 // this allows better reuse of vector constants
934 // copy it into the offset now, because we can
935 if (opt_vectorcalls
&& pr_token_type
== TT_IMMED
&& pr_immediate_type
== type_vector
&&
936 arg
< MAX_PARMS
&& !def_parms
[arg
].temp
->used
) {
938 e
->ofs
= OFS_PARM0
+0;
939 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_F
], QCC_MakeFloatConst(pr_immediate
.vector
[0]), e
, QCC_STAT_NOCONV
));
940 e
->ofs
= OFS_PARM0
+1;
941 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_F
], QCC_MakeFloatConst(pr_immediate
.vector
[1]), e
, QCC_STAT_NOCONV
));
942 e
->ofs
= OFS_PARM0
+2;
943 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_F
], QCC_MakeFloatConst(pr_immediate
.vector
[2]), e
, QCC_STAT_NOCONV
));
947 e
= QCC_PR_Expression(TOP_PRIORITY
, EXPR_DISALLOW_COMMA
);
949 if (arg
>= MAX_PARMS
) {
950 if (!extra_parms
[arg
-MAX_PARMS
]) {
951 d
= (QCC_def_t
*)qccHunkAlloc(sizeof(QCC_def_t
));
952 d
->name
= "extra parm";
953 d
->ofs
= QCC_GetFreeOffsetSpace(3);
954 extra_parms
[arg
-MAX_PARMS
] = d
;
956 d
= extra_parms
[arg
-MAX_PARMS
];
962 if (e->type->type != ev_integer && p->type != ev_function)
963 if (e->type->type != ev_function && p->type != ev_integer)
964 if ( e->type->type != p->type )
966 if (qcc_typecmp(e
->type
, p
)) {
967 if (p
->type
== ev_string
) {
968 // convert number to string
969 if (e
->type
->type
== ev_integer
) e
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_ITOS
], e
, NULL
, NULL
);
970 else if (e
->type
->type
== ev_float
) e
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_FTOS
], e
, NULL
, NULL
);
971 else if (e
->type
->type
== ev_vector
) e
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_VTOS
], e
, NULL
, NULL
);
972 else if (e
->type
->type
== ev_entity
) e
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_ETOS
], e
, NULL
, NULL
);
973 } else if (p
->type
== ev_integer
&& e
->type
->type
== ev_float
) {
974 // convert float -> int... is this a constant?
975 //fprintf(stderr, "(%d)FCALL: f->i\n", arg);
976 e
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_FTOI
], e
, NULL
, NULL
);
977 //fprintf(stderr, "(%d)FCALL: f->i: done\n", arg);
978 } else if (p
->type
== ev_float
&& e
->type
->type
== ev_integer
) {
979 // convert int -> float... is this a constant?
980 //fprintf(stderr, "(%d)FCALL: i->f\n", arg);
981 e
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_ITOF
], e
, NULL
, NULL
);
982 //fprintf(stderr, "(%d)FCALL: i->f: done\n", arg);
983 } else if (p
->type
== ev_function
&& e
->type
->type
== ev_integer
&& e
->constant
&& !((qccint
*)qcc_pr_globals
)[e
->ofs
]) {
984 // you're allowed to use int 0 to pass a null function pointer
985 // this is basically because __NULL__ is defined as ~0 (int 0)
989 //fprintf(stderr, "fcall: num_parms=%d; arg=%d; np=%d; p=%p; p->next=%p; da=%d\n", t->num_parms, arg, np, p, p->next, dont_advance);
990 if (t
->num_parms
< 0) {
991 // handle special case: typed vaargs
993 if (arg
== np
&& p
->next
== NULL
) dont_advance
= 1;
995 if (!dont_advance
) p
= p
->next
;
1000 // a vector copy will copy everything
1001 d
->type
= type_void
;
1005 if (e->type->size > 1) {
1006 QCC_PR_Statement(&pr_opcodes[OP_STORE_V], e, d, (QCC_dstatement_t **)0xffffffff);
1008 QCC_PR_Statement(&pr_opcodes[OP_STORE_F], e, d, (QCC_dstatement_t **)0xffffffff);
1012 } while (QCC_PR_EatDelim(","));
1013 if (t
->num_parms
!= -1 && arg
< np
) QCC_PR_ParseWarning(WARN_TOOFEWPARAMS
, "too few parameters on call to %s", func
->name
);
1016 QCC_PR_ParseWarning(WARN_TOOFEWPARAMS
, "%s: Too few parameters", func
->name
);
1017 QCC_PR_ParsePrintDef(WARN_TOOFEWPARAMS
, func
);
1019 return QCC_PR_GenerateFunctionCall(func
, param
, arg
, newself
);
1023 QCC_type_t
*QCC_PointerTypeTo (QCC_type_t
*type
) {
1024 QCC_type_t
*newtype
= QCC_PR_NewType("ptr", ev_pointer
);
1025 newtype
->aux_type
= type
;
1034 Returns the global ofs for the current token
1037 static QCC_def_t
*QCC_PR_ParseValue (qccbool allowarrayassign
) {
1038 QCC_def_t
*d
, *tmp
, *idx
;
1041 // if the token is an immediate, allocate a constant for it
1042 if (pr_token_type
== TT_IMMED
) return QCC_PR_ParseImmediate();
1043 name
= QCC_PR_ParseName();
1044 // look through the defs
1045 d
= QCC_PR_GetDef(NULL
, name
, pr_scope
, qcc_false
, 0, qcc_false
);
1047 // intrinsics? any old function with no args will do
1049 for (size_t f
= 0; f
< sizeof(intrlist
)/sizeof(intrlist
[0]); ++f
) {
1050 if (strcmp(name
, intrlist
[f
].name
) == 0) { intrfound
= 1; break; }
1052 if (!intrfound
) QCC_PR_ParseError(ERR_UNKNOWNVALUE
, "Unknown value \"%s\"", name
);
1053 d
= QCC_PR_GetDef(type_function
, name
, NULL
, qcc_true
, 1, qcc_false
);
1059 //if ((t->type == ev_vector || (t->type == ev_field && t->aux_type->type == ev_vector)) && d->arraysize == 1) goto skipit;
1061 if (d
->arraysize
== 1 && t
->type
!= ev_pointer
) goto skipit
;
1064 if (QCC_PR_EatDelim("[")) {
1065 tmp
= QCC_PR_Expression(TOP_PRIORITY
, 0);
1067 //fprintf(stderr, "%d idx=%p, tmp=%p\n", t->type, idx, tmp);
1068 if (!idx
&& t
->type
== ev_pointer
&& d
->arraysize
== 1) t
= t
->aux_type
;
1070 if (t->type == ev_string && d->arraysize == 1) {
1071 //QCC_PR_ParseErrorPrintDef(0, d, "TODO: no string indexing yet");
1072 //fprintf(stderr, "indexing string\n");
1073 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, tmp, NULL);
1076 tmp = QCC_SupplyConversion(tmp, ev_float, qcc_true);
1077 res = QCC_GetTemp(type_float);
1078 QCC_PR_SimpleStatement(OP_LOADP_C, d->ofs, tmp->ofs, res->ofs, qcc_false);
1086 if (!idx
&& d
->type
->type
== ev_pointer
) {
1088 } else if (tmp
->constant
) {
1090 if (tmp
->type
->type
== ev_integer
) i
= G_INT(tmp
->ofs
);
1091 else if (tmp
->type
->type
== ev_float
) i
= G_FLOAT(tmp
->ofs
);
1092 else abort(); //k8:!!!
1093 if (i
< 0 || i
>= (!idx
? d
->arraysize
: t
->arraysize
)) QCC_PR_ParseErrorPrintDef(0, d
, "(constant) array index out of bounds");
1095 tmp
= QCC_SupplyConversion(tmp
, ev_integer
, qcc_true
);
1096 QCC_PR_SimpleStatement(OP_BOUNDCHECK
, tmp
->ofs
, (!idx
? d
->arraysize
: t
->arraysize
), 0, qcc_false
);
1098 // don't multiply by type size if the instruction/emulation will do that instead
1099 // k8: was (idx || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
1100 if (t
->size
!= 1 && idx
!= 0) {
1101 if (tmp
->type
->type
== ev_float
) {
1102 tmp
= QCC_PR_Statement(&pr_opcodes
[OP_MUL_F
], tmp
, QCC_MakeFloatConst(t
->size
), NULL
);
1104 tmp
= QCC_PR_Statement(&pr_opcodes
[OP_MUL_I
], tmp
, QCC_MakeIntConst(t
->size
), NULL
);
1107 idx
= (idx
? QCC_PR_Statement(&pr_opcodes
[OP_ADD_I
], idx
, QCC_SupplyConversion(tmp
, ev_integer
, qcc_true
), NULL
) : tmp
);
1111 if (t
->type
== ev_pointer
&& QCC_PR_EatDelim(".")) {
1112 if (!idx
&& t
->type
== ev_pointer
&& d
->arraysize
== 1) t
= t
->aux_type
;
1113 for (t
= t
->param
; t
; t
= t
->next
) if (QCC_PR_EatId(t
->name
)) break;
1114 if (!t
) QCC_PR_ParseError(0, "'%s' is not a member", pr_token
);
1115 tmp
= QCC_MakeIntConst(t
->ofs
);
1116 idx
= (idx
? QCC_PR_Statement(&pr_opcodes
[OP_ADD_I
], idx
, tmp
, NULL
) : tmp
);
1125 if (d
->type
->type
== ev_pointer
) {
1128 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_I
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1131 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_F
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1134 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_I
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1137 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_S
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1140 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_V
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1143 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_ENT
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1146 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_FLD
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1149 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_FNC
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1152 QCC_PR_ParseError(ERR_NOVALIDOPCODES
, "No op available");
1156 // don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign
1157 // source type is a struct, or its an array, or something that can otherwise be directly accessed
1160 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_I
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1163 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_F
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1166 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_I
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1169 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_S
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1172 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_V
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1175 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_ENT
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1178 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_FLD
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1181 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADA_FNC
], d
, QCC_SupplyConversion(idx
, ev_integer
, qcc_true
), NULL
);
1184 QCC_PR_ParseError(ERR_NOVALIDOPCODES
, "No op available");
1191 if (t
->type
== ev_vector
|| (t
->type
== ev_field
&& t
->aux_type
->type
== ev_vector
)) {
1192 if (QCC_PR_EatDelim(".")) {
1194 char *name
= alloca(strlen(d
->name
)+4), ech
;
1196 if (QCC_PR_EatId("x")) ech
= 'x';
1197 else if (QCC_PR_EatId("y")) ech
= 'y';
1198 else if (QCC_PR_EatId("z")) ech
= 'z';
1199 else QCC_PR_ParseError(0, "'%s' is not a vector member", pr_token
);
1200 sprintf(name
, "%s.%c", d
->name
, ech
);
1201 //fprintf(stderr, "accesing vector member: [%s]\n", name);
1202 d
= QCC_PR_GetDef(type_float
, name
, pr_scope
, qcc_false
, 0, qcc_false
);
1203 if (d
== NULL
) QCC_PR_ParseError(ERR_UNKNOWNVALUE
, "WTF?!! (00) [%s]", name
);
1204 } else if (QCC_PR_EatDelim("[")) {
1205 // array-like vector indexing
1206 tmp
= QCC_PR_Expression(TOP_PRIORITY
, 0);
1209 } else if (t
->type
== ev_string
|| (t
->type
== ev_field
&& t
->aux_type
->type
== ev_string
)) {
1210 if (QCC_PR_EatDelim("[")) {
1212 tmp
= QCC_PR_Expression(TOP_PRIORITY
, 0);
1214 d
= QCC_PR_Statement(&pr_opcodes
[OP_LOADP_C
], d
, tmp
, NULL
);
1223 #include "qcc_pr_comp_expr.c"
1226 int QCC_PR_IntConstExpr (void) {
1227 QCC_def_t
*def
= QCC_PR_Expression(TOP_PRIORITY
, 0);
1228 if (def
->constant
) {
1230 if (def
->type
->type
== ev_integer
) return G_INT(def
->ofs
);
1231 if (def
->type
->type
== ev_float
) {
1232 int i
= G_FLOAT(def
->ofs
);
1233 if ((float)i
== G_FLOAT(def
->ofs
)) return i
;
1236 QCC_PR_ParseError(ERR_NOTACONSTANT
, "Value is not an integer constant");
1241 static void QCC_PR_GotoStatement (QCC_dstatement_t
*patch2
, const char *labelname
) {
1242 if (num_gotos
>= max_gotos
) {
1244 pr_gotos
= realloc(pr_gotos
, sizeof(*pr_gotos
)*max_gotos
);
1246 strncpy(pr_gotos
[num_gotos
].name
, labelname
, sizeof(pr_gotos
[num_gotos
].name
)-1);
1247 pr_gotos
[num_gotos
].lineno
= pr_source_line
;
1248 pr_gotos
[num_gotos
].statementno
= patch2
- statements
;
1253 static qccbool
QCC_PR_StatementBlocksMatch (const QCC_dstatement_t
*p1
, int p1count
, const QCC_dstatement_t
*p2
, int p2count
) {
1254 if (p1count
!= p2count
) return qcc_false
;
1255 while (p1count
-- > 0) {
1256 if (p1
->op
!= p2
->op
) return qcc_false
;
1257 if (p1
->a
!= p2
->a
) return qcc_false
;
1258 if (p1
->b
!= p2
->b
) return qcc_false
;
1259 if (p1
->c
!= p2
->c
) return qcc_false
;
1267 #include "qcc_pr_comp_statements.c"
1270 //FIXME: CONDITIONAL JUMPS TOO?
1271 static qccbool
QCC_FuncJumpsTo (int first
, int last
, int statement
) {
1272 for (int st
= first
; st
< last
; ++st
) {
1273 if (is_branch_op(statements
[st
].op
)) {
1274 int pc
= branch_dest(st
);
1275 if (pc
== statement
) {
1277 if (statements
[st
-1].op
== OP_RETURN
) break;
1278 if (statements
[st
-1].op
== OP_DONE
) break;
1288 static void QCC_CompoundJumps (int first
, int last
) {
1289 // jumps to jumps are reordered so they become jumps to the final target
1290 for (int st
= first
; st
< last
; ++st
) {
1291 if (is_branch_op(statements
[st
].op
)) {
1292 int argn
= (statements
[st
].op
== OP_GOTO
? 0 : 1);
1293 int dest
= branch_dest(st
);
1295 int dest = st+(signed int)statements[st].args[argn];
1297 if (statements
[st
].op
== OP_GOTO
&& (statements
[dest
].op
== OP_RETURN
|| statements
[dest
].op
== OP_DONE
)) {
1298 // goto leads to return: copy the command out to remove the goto
1299 statements
[st
] = statements
[dest
];
1300 ++optres_compound_jumps
;
1303 // traverse 'goto' chain
1304 while (statements
[dest
].op
== OP_GOTO
) {
1305 if (infloop
-- == 0) { QCC_PR_ParseWarning(0, "Infinite loop detected"); break; }
1306 statements
[st
].sargs
[argn
] = statements
[dest
].sa
+dest
-st
;
1307 dest
= st
+statements
[st
].sargs
[argn
];
1308 ++optres_compound_jumps
;
1316 //QCC_CheckForDeadAndMissingReturns()
1317 #include "qcc_pr_comp_retcheck.c"
1320 // only the unconditionals
1321 static inline qccbool
QCC_StatementIsAJump (int stnum
, int notifdest
) {
1322 switch (statements
[stnum
].op
) {
1323 case OP_RETURN
: case OP_DONE
: return qcc_true
;
1324 case OP_GOTO
: return (branch_dest(stnum
) != notifdest
);
1330 static int QCC_AStatementJumpsTo (int targ
, int first
, int last
) {
1331 for (int st
= first
; st
< last
; ++st
) {
1332 if (is_branch_op(statements
[st
].op
) && branch_dest(st
) == targ
) return qcc_true
;
1334 // assume it's used if it is labeled
1335 for (int st
= 0; st
< num_labels
; ++st
) if (pr_labels
[st
].statementno
== targ
) return qcc_true
;
1340 void QCC_RemapOffsets (unsigned int firststatement
, unsigned int laststatement
, unsigned int min
,
1341 unsigned int max
, unsigned int newmin
)
1343 QCC_dstatement_t
*st
;
1345 for (i
= firststatement
, st
= &statements
[i
]; i
< laststatement
; ++i
, ++st
) {
1346 for (int c
= 0; c
< 3; ++c
) {
1347 if (pr_opcodes
[st
->op
].types
[c
] && st
->args
[c
] >= min
&& st
->args
[c
] < max
) st
->args
[c
] = st
->args
[c
]-min
+newmin
;
1353 static void QCC_Marshal_Locals (int first
, int laststatement
) {
1355 unsigned int newofs
;
1356 // clear these after each function. we arn't overlapping them so why do we need to keep track of them?
1357 //if (!opt_overlaptemps) {
1359 // for (t = functemps; t; t = t->next)
1360 // QCC_FreeOffset(t->ofs, t->size);
1361 // functemps = NULL;
1363 // nothing to marshal
1364 if (!pr
.localvars
) {
1365 locals_start
= locals_end
= 0;/*numpr_globals;*/
1368 if (!opt_locals_marshalling
) {
1369 pr
.localvars
= pr
.prevlocvars
= NULL
;
1372 // initial backwards bounds
1373 locals_start
= MAX_REGS
;
1375 newofs
= MAX_REGS
; // this is a handy place to put it. :)
1376 // the params need to be in the order that they were allocated
1377 // so we allocate in a backwards order
1378 for (local
= pr
.localvars
; local
; local
= local
->nextlocal
) {
1379 if (local
->constant
) continue;
1380 newofs
+= local
->type
->size
*local
->arraysize
;
1381 if (local
->arraysize
> 1) ++newofs
;
1383 locals_start
= MAX_REGS
;
1384 locals_end
= newofs
;
1385 optres_locals_marshalling
+= newofs
-MAX_REGS
;
1386 for (local
= pr
.localvars
; local
; local
= local
->nextlocal
) {
1387 if (local
->constant
) continue;
1388 if (((const int *)qcc_pr_globals
)[local
->ofs
]) QCC_PR_ParseError(ERR_INTERNAL
, "Marshall of a set value");
1389 newofs
-= local
->type
->size
*local
->arraysize
;
1390 if (local
->arraysize
> 1) --newofs
;
1391 QCC_RemapOffsets(first
, laststatement
, local
->ofs
, local
->ofs
+local
->type
->size
*local
->arraysize
, newofs
);
1392 QCC_FreeOffset(local
->ofs
, local
->type
->size
*local
->arraysize
);
1393 local
->ofs
= newofs
;
1395 pr
.localvars
= pr
.prevlocvars
= NULL
;
1400 static void QCC_WriteAsmFunction (QCC_def_t
*sc
, unsigned int firststatement
, gofs_t firstparm
) {
1405 if (!asmfile
) return;
1407 fprintf(asmfile
, "%s(", QCC_TypeName(type
->aux_type
));
1408 p
= type
->num_parms
;
1409 for (o
= firstparm
, i
= 0, type
= type
->param
; i
< p
; ++i
, type
= type
->next
) {
1410 if (i
) fprintf(asmfile
, ", ");
1411 for (param
= pr
.localvars
; param
; param
= param
->nextlocal
) if (param
->ofs
== o
) break;
1413 fprintf(asmfile
, "%s %s /* at %d */", QCC_TypeName(type
), param
->name
, o
);
1415 fprintf(asmfile
, "%s /* at %d */", QCC_TypeName(type
), o
);
1419 fprintf(asmfile
, ") %s = asm {\n", sc
->name
);
1420 QCC_fprintfLocals(asmfile
, firstparm
, o
);
1421 for (i
= firststatement
; i
< (unsigned int)numstatements
; ++i
) {
1422 fprintf(asmfile
, " %-7s ", pr_opcodes
[statements
[i
].op
].opname
);
1423 if (pr_opcodes
[statements
[i
].op
].type_a
!= &type_void
) {
1424 if (pr_opcodes
[statements
[i
].op
].type_a
) {
1425 fprintf(asmfile
, "%s", QCC_VarAtOffset(statements
[i
].a
, (*pr_opcodes
[statements
[i
].op
].type_a
)->size
));
1427 fprintf(asmfile
, "%d", statements
[i
].a
);
1429 if (pr_opcodes
[statements
[i
].op
].type_b
!= &type_void
) {
1430 if (pr_opcodes
[statements
[i
].op
].type_b
) {
1431 fprintf(asmfile
, ", %s", QCC_VarAtOffset(statements
[i
].b
, (*pr_opcodes
[statements
[i
].op
].type_b
)->size
));
1433 fprintf(asmfile
, ", %d", statements
[i
].b
);
1435 if (pr_opcodes
[statements
[i
].op
].type_c
!= &type_void
&& pr_opcodes
[statements
[i
].op
].associative
== ASSOC_LEFT
) {
1436 if (pr_opcodes
[statements
[i
].op
].type_c
) {
1437 fprintf(asmfile
, ", %s", QCC_VarAtOffset(statements
[i
].c
, (*pr_opcodes
[statements
[i
].op
].type_c
)->size
));
1439 fprintf(asmfile
, ", %d", statements
[i
].c
);
1443 if (pr_opcodes
[statements
[i
].op
].type_c
!= &type_void
) {
1444 if (pr_opcodes
[statements
[i
].op
].type_c
) {
1445 fprintf(asmfile
, ", %s", QCC_VarAtOffset(statements
[i
].c
, (*pr_opcodes
[statements
[i
].op
].type_c
)->size
));
1447 fprintf(asmfile
, ", %d", statements
[i
].c
);
1452 fprintf(asmfile
, "; /*%d*/\n", statement_linenums
[i
]);
1454 fprintf(asmfile
, "}\n\n");
1461 PR_ParseImmediateStatements
1463 Parse a function body
1466 static QCC_function_t
*QCC_PR_ParseImmediateStatements (QCC_type_t
*type
) {
1468 QCC_def_t
*defs
[MAX_PARMS
+MAX_EXTRA_PARMS
], *e2
;
1470 qccbool needsdone
= qcc_false
;
1471 freeoffset_t
*oldfofs
;
1473 expandedemptymacro
= qcc_false
;
1474 f
= (void *)qccHunkAlloc(sizeof(QCC_function_t
));
1475 if (type
->num_parms
< 0) QCC_PR_ParseError(ERR_FUNCTIONWITHVARGS
, "QC function with variable arguments and function body");
1478 locals_start
= locals_end
= numpr_globals
;
1479 oldfofs
= qcc_freeofs
;
1482 for (int i
= 0 ; i
< type
->num_parms
; ++i
) {
1483 if (!*pr_parm_names
[i
]) QCC_PR_ParseError(ERR_PARAMWITHNONAME
, "Parameter is not named");
1484 defs
[i
] = QCC_PR_GetDef(parm
, pr_parm_names
[i
], pr_scope
, qcc_true
, 1, qcc_false
);
1485 ++defs
[i
]->references
;
1486 if (i
< MAX_PARMS
) {
1487 f
->parm_ofs
[i
] = defs
[i
]->ofs
;
1488 if (i
> 0 && f
->parm_ofs
[i
] < f
->parm_ofs
[i
-1]) QCC_Error(ERR_BADPARAMORDER
, "bad parm order");
1489 if (i
> 0 && f
->parm_ofs
[i
] != f
->parm_ofs
[i
-1]+defs
[i
-1]->type
->size
) QCC_Error(ERR_BADPARAMORDER
, "parms not packed");
1493 if (type
->num_parms
) locals_start
= locals_end
= defs
[0]->ofs
;
1494 qcc_freeofs
= oldfofs
;
1495 f
->code
= numstatements
;
1496 if (type
->num_parms
> MAX_PARMS
) {
1497 for (int i
= MAX_PARMS
; i
< type
->num_parms
; ++i
) {
1498 if (!extra_parms
[i
-MAX_PARMS
]) {
1499 e2
= (QCC_def_t
*)qccHunkAlloc(sizeof(QCC_def_t
));
1500 e2
->name
= "extra parm";
1501 e2
->ofs
= QCC_GetFreeOffsetSpace(3);
1502 extra_parms
[i
- MAX_PARMS
] = e2
;
1504 extra_parms
[i
-MAX_PARMS
]->type
= defs
[i
]->type
;
1505 if (defs
[i
]->type
->type
!= ev_vector
) {
1506 QCC_PR_Statement(&pr_opcodes
[OP_STORE_F
], extra_parms
[i
-MAX_PARMS
], defs
[i
], NULL
);
1508 QCC_PR_Statement(&pr_opcodes
[OP_STORE_V
], extra_parms
[i
-MAX_PARMS
], defs
[i
], NULL
);
1512 QCC_RemapLockedTemps(-1, -1);
1514 // parse regular statements
1515 while (!QCC_PR_EatDelim("}")) {
1516 QCC_PR_ParseStatement(qcc_false
);
1520 if (f
->code
== numstatements
) {
1521 needsdone
= qcc_true
;
1522 } else if (statements
[numstatements
-1].op
!= OP_RETURN
&& statements
[numstatements
-1].op
!= OP_DONE
) {
1523 needsdone
= qcc_true
;
1526 for (int i
= 0; i
< num_gotos
; ++i
) {
1528 for (j
= 0; j
< num_labels
; ++j
) {
1529 if (strcmp(pr_gotos
[i
].name
, pr_labels
[j
].name
) == 0) {
1530 if (!pr_opcodes
[statements
[pr_gotos
[i
].statementno
].op
].type_a
) {
1531 statements
[pr_gotos
[i
].statementno
].a
+= pr_labels
[j
].statementno
-pr_gotos
[i
].statementno
;
1532 } else if (!pr_opcodes
[statements
[pr_gotos
[i
].statementno
].op
].type_b
) {
1533 statements
[pr_gotos
[i
].statementno
].b
+= pr_labels
[j
].statementno
-pr_gotos
[i
].statementno
;
1535 statements
[pr_gotos
[i
].statementno
].c
+= pr_labels
[j
].statementno
-pr_gotos
[i
].statementno
;
1540 if (j
== num_labels
) {
1542 QCC_PR_ParseError(ERR_NOLABEL
, "Goto statement with no matching label \"%s\"", pr_gotos
[i
].name
);
1547 if (!needsdone
) needsdone
= QCC_FuncJumpsTo(f
->code
, numstatements
, numstatements
);
1548 // emit an end of statements opcode
1549 if (needsdone
) QCC_PR_Statement(pr_opcodes
, 0,0, NULL
);
1550 QCC_CheckForDeadAndMissingReturns(f
->code
, numstatements
, type
->aux_type
->type
);
1551 if (opt_compound_jumps
) QCC_CompoundJumps(f
->code
, numstatements
);
1552 QCC_RemapLockedTemps(f
->code
, numstatements
);
1553 locals_end
= numpr_globals
;
1554 QCC_Marshal_Locals(f
->code
, numstatements
);
1555 QCC_WriteAsmFunction(pr_scope
, f
->code
, locals_start
);
1556 if (num_labels
) num_labels
= 0;
1557 if (num_continues
) {
1559 QCC_PR_ParseError(ERR_ILLEGALCONTINUES
, "%s: function contains illegal continues", pr_scope
->name
);
1563 QCC_PR_ParseError(ERR_ILLEGALBREAKS
, "%s: function contains illegal breaks", pr_scope
->name
);
1567 QCC_PR_ParseError(ERR_ILLEGALCASES
, "%s: function contains illegal cases", pr_scope
->name
);
1573 // register a def, and all of it's sub parts.
1574 // only the main def is of use to the compiler.
1575 // the subparts are emitted to the compiler and allow correct saving/loading
1576 // be careful with fields, this doesn't allocated space, so will it allocate fields. It only creates defs at specified offsets.
1577 static QCC_def_t
*QCC_PR_DummyDef (QCC_type_t
*type
, const char *name
, QCC_def_t
*scope
, int arraysize
, unsigned int ofs
, int referable
, qccbool saved
) {
1578 static const char *reserved_words
[] = {
1599 char array
[64], newname
[256];
1600 QCC_def_t
*def
, *first
= NULL
;
1602 for (size_t f
= 0; f
< sizeof(reserved_words
)/sizeof(reserved_words
[0]); ++f
) {
1603 if (strcmp(name
, reserved_words
[f
]) == 0) {
1604 QCC_PR_ParseError(ERR_KEYWORDDISABLED
, "'%s' keyword used as variable name", name
);
1608 //fprintf(stderr, "arraysize=%d\n", arraysize);
1609 for (int a
= 0; a
< arraysize
; ++a
) {
1610 if (a
== 0) array
[0] = 0; else snprintf(array
, sizeof(array
), "[%d]", a
);
1612 snprintf(newname
, sizeof(newname
), "%s%s", name
, array
);
1617 // allocate a new def
1618 def
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
1619 memset(def
, 0, sizeof(*def
));
1621 def
->arraysize
= arraysize
;
1623 pr
.def_tail
->next
= def
;
1626 if (a
> 0) ++def
->references
;
1627 def
->s_line
= pr_source_line
;
1628 def
->s_file
= s_file
;
1629 if (a
) def
->initialized
= 1;
1630 def
->name
= qccHunkDupStr(newname
);
1634 def
->constant
= qcc_true
; // if (type->type = ev_field)
1635 if (type
->type
!= ev_function
) {
1636 if (ofs
+type
->size
*a
>= MAX_REGS
) QCC_Error(ERR_TOOMANYGLOBALS
, "MAX_REGS is too small");
1637 def
->ofs
= ofs
+type
->size
*a
;
1641 if (!first
) first
= def
;
1642 //qcc_printf("Emited %s\n", newname);
1643 if (arraysize
== 1 && (type
->type
== ev_vector
|| (type
->type
== ev_field
&& type
->aux_type
->type
== ev_vector
))) {
1644 // do the vector thing
1645 QCC_type_t
*vt
= (type
->type
== ev_vector
? type_float
: type_floatfield
);
1646 //fprintf(stderr, "creating vector fielddefs: [%s]\n", name);
1647 // don't warn about unreferenced vector parts
1648 snprintf(newname
, sizeof(newname
), "%s.x", name
);
1649 QCC_PR_DummyDef(vt
, newname
, scope
, 1, ofs
+type
->size
*a
+0, referable
, qcc_false
)->references
+= 1;
1650 snprintf(newname
, sizeof(newname
), "%s.y", name
);
1651 QCC_PR_DummyDef(vt
, newname
, scope
, 1, ofs
+type
->size
*a
+1, referable
, qcc_false
)->references
+= 1;
1652 snprintf(newname
, sizeof(newname
), "%s.z", name
);
1653 QCC_PR_DummyDef(vt
, newname
, scope
, 1, ofs
+type
->size
*a
+2, referable
, qcc_false
)->references
+= 1;
1655 first
->deftail
= pr
.def_tail
;
1659 // anything above needs to be left in, and so warning about not using it is just going to pee people off
1660 if (!Hash_Get(&globalstable
, "end_sys_fields")) ++first
->references
;
1661 if (arraysize
<= 1 && first
->type
->type
!= ev_field
) first
->constant
= qcc_false
;
1663 Hash_Add(&localstable
, first
->name
, first
, qccHunkAlloc(sizeof(hashtable_bucket_t
)));
1665 Hash_Add(&globalstable
, first
->name
, first
, qccHunkAlloc(sizeof(hashtable_bucket_t
)));
1667 if (!scope
&& asmfile
) fprintf(asmfile
, "%s %s; /* at %d */\n", QCC_TypeName(first
->type
), first
->name
, first
->ofs
);
1677 If type is NULL, it will match any type
1678 If allocate is qcc_true, a new def will be allocated if it can't be found
1681 QCC_def_t
*QCC_PR_GetDef (QCC_type_t
*type
, const char *name
, QCC_def_t
*scope
, qccbool allocate
, int arraysize
, qccbool saved
) {
1684 //char element[MAX_NAME];
1686 QCC_def_t
*foundstatic
= NULL
;
1687 //fprintf(stderr, "QCC_PR_GetDef: [%s] scope=%p; allocate=%d\n", name, scope, allocate);
1689 def
= Hash_Get(&localstable
, name
);
1690 while (def
!= NULL
) {
1691 if (def
->scope
&& def
->scope
!= scope
) {
1692 def
= Hash_GetNext(&localstable
, name
, def
);
1693 continue; // in a different function
1695 if (type
&& qcc_typecmp(def
->type
, type
)) {
1696 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHREDEC
, def
, "Type mismatch on redeclaration of %s. %s, should be %s", name
, QCC_TypeName(type
), QCC_TypeName(def
->type
));
1697 } if (def
->arraysize
!= arraysize
&& arraysize
) {
1698 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE
, def
, "Array sizes for redecleration of %s do not match", name
);
1702 //fprintf(stderr, "LALLOCATE: [%s] %d\n", name, (def->scope == scope && pr_subscopedlocals));
1703 qccbool fuckme
= qcc_false
;
1704 if (def
->scope
== scope
) {
1705 // check if this definition is just a shadowed local
1706 //fprintf(stderr, "lv=%p; plv=%p\n", pr.localvars, pr.prevlocvars);
1707 for (QCC_def_t
*e
= pr
.localvars
; e
!= pr
.prevlocvars
; e
= e
->nextlocal
) {
1708 //fprintf(stderr, "[%s] (%s)\n", def->name, e->name);
1709 if (strcmp(def
->name
, e
->name
) == 0) { fuckme
= qcc_true
; break; }
1712 if (!fuckme
) { def
= NULL
; break; }
1714 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION
, "%s duplicate definition ignored", name
);
1715 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION
, def
);
1716 //if (!scope) QCC_PR_ParsePrintDef(def);
1721 def
= Hash_Get(&globalstable
, name
);
1722 while (def
!= NULL
) {
1723 if (def
->scope
&& def
->scope
!= scope
) {
1724 def
= Hash_GetNext(&globalstable
, name
, def
);
1725 continue; // in a different function
1728 if (def
->isstatic
&& def
->s_file
!= s_file
) {
1729 // warn? or would that be pointless?
1731 def
= Hash_GetNext(&globalstable
, name
, def
);
1732 continue; // in a different function
1735 if (type
&& qcc_typecmp(def
->type
, type
)) {
1737 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHREDEC
, def
, "Type mismatch on redeclaration of %s. %s, should be %s", name
, QCC_TypeName(type
), QCC_TypeName(def
->type
));
1740 if (def
->arraysize
!= arraysize
&& arraysize
) {
1741 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE
, def
, "Array sizes for redecleration of %s do not match", name
);
1743 if (allocate
&& scope
) {
1745 // warn? or would that be pointless?
1746 def
= Hash_GetNext(&globalstable
, name
, def
);
1747 continue; // in a different function
1749 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION
, "%s duplicate definition ignored", name
);
1750 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION
, def
);
1751 //if (!scope) QCC_PR_ParsePrintDef(def);
1755 // do we want to try case insensitive too?
1756 if (Hash_Get
!= &Hash_Get
&& !allocate
) {
1758 def
= Hash_Get(&localstable
, name
);
1759 while (def
!= NULL
) {
1760 if (def
->scope
&& def
->scope
!= scope
) {
1761 def
= Hash_GetNext(&localstable
, name
, def
);
1762 continue; // in a different function
1764 if (type
&& qcc_typecmp(def
->type
, type
)) {
1765 QCC_PR_ParseError(ERR_TYPEMISMATCHREDEC
, "Type mismatch on redeclaration of %s. %s, should be %s", name
, QCC_TypeName(type
), QCC_TypeName(def
->type
));
1767 if (def
->arraysize
!= arraysize
&& arraysize
) {
1768 QCC_PR_ParseError(ERR_TYPEMISMATCHARRAYSIZE
, "Array sizes for redecleration of %s do not match", name
);
1770 if (allocate
&& scope
) {
1771 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION
, "%s duplicate definition ignored", name
);
1772 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION
, def
);
1773 //if (!scope) QCC_PR_ParsePrintDef(def);
1778 def
= Hash_Get(&globalstable
, name
);
1779 while (def
!= NULL
) {
1780 if (def
->scope
&& def
->scope
!= scope
) {
1781 def
= Hash_GetNext(&globalstable
, name
, def
);
1782 continue; // in a different function
1784 if (def
->isstatic
&& def
->s_file
!= s_file
) {
1785 // warn? or would that be pointless?
1787 def
= Hash_GetNext(&globalstable
, name
, def
);
1788 continue; // in a different function
1790 if (type
&& qcc_typecmp(def
->type
, type
)) {
1792 QCC_PR_ParseError(ERR_TYPEMISMATCHREDEC
, "Type mismatch on redeclaration of %s. %s, should be %s", name
, QCC_TypeName(type
), QCC_TypeName(def
->type
));
1795 if (def
->arraysize
!= arraysize
&& arraysize
) {
1796 QCC_PR_ParseError(ERR_TYPEMISMATCHARRAYSIZE
, "Array sizes for redecleration of %s do not match", name
);
1798 if (allocate
&& scope
) {
1800 //warn? or would that be pointless?
1801 def
= Hash_GetNext(&globalstable
, name
, def
);
1802 continue; // in a different function
1804 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION
, "%s duplicate definition ignored", name
);
1805 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION
, def
);
1806 //if (!scope) QCC_PR_ParsePrintDef(def);
1811 if (foundstatic
&& !allocate
) {
1812 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION
, "%s defined static", name
);
1813 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION
, foundstatic
);
1815 if (!allocate
) return NULL
;
1816 // allocate new definition
1817 if (arraysize
< 1) QCC_PR_ParseError(ERR_ARRAYNEEDSSIZE
, "First declaration of array %s with no size",name
);
1819 if (QCC_PR_GetDef(type
, name
, NULL
, qcc_false
, arraysize
, qcc_false
)) {
1820 QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL
, "Local \"%s\" defined with name of a global", name
);
1823 //if (type->type == ev_function) fprintf(stderr, "ALLOCATING GLOBAL FOR FUNCTION: [%s]\n", name);
1824 if (type
->type
!= ev_function
) {
1825 ofs
= numpr_globals
;
1826 if (arraysize
> 1) {
1827 // write the array size
1828 ofs
= QCC_GetFreeOffsetSpace(1+(type
->size
*arraysize
));
1829 ((qccint
*)qcc_pr_globals
)[ofs
] = arraysize
-1; // an array needs the size written first: this is a hexen2 opcode thing
1832 ofs
= QCC_GetFreeOffsetSpace(type
->size
*arraysize
);
1835 // don't allocate global for function
1838 def
= QCC_PR_DummyDef(type
, name
, scope
, arraysize
, ofs
, qcc_true
, saved
);
1840 if (type
->type
== ev_field
&& allocate
!= 2) {
1841 // make arrays of fields work
1843 for (i
= 0; i
< type
->size
*arraysize
; ++i
) *(qccint
*)&qcc_pr_globals
[def
->ofs
+i
] = pr
.size_fields
+i
;
1844 pr
.size_fields
+= i
;
1847 def
->nextlocal
= pr
.localvars
;
1854 QCC_def_t
*QCC_PR_DummyFieldDef (QCC_type_t
*type
, char *name
, QCC_def_t
*scope
, int arraysize
, unsigned int *fieldofs
, qccbool saved
) {
1858 QCC_def_t
*def
, *first
= NULL
;
1859 unsigned int maxfield
, startfield
;
1860 startfield
= *fieldofs
;
1861 maxfield
= startfield
;
1862 for (a
= 0; a
< arraysize
; ++a
) {
1863 if (a
== 0) *array
= '\0'; else snprintf(array
, sizeof(array
), "[%d]", a
);
1865 snprintf(newname
, sizeof(newname
), "%s%s", name
, array
);
1866 // allocate a new def
1867 def
= (void *)qccHunkAlloc(sizeof(QCC_def_t
));
1868 memset(def
, 0, sizeof(*def
));
1870 def
->arraysize
= arraysize
;
1871 pr
.def_tail
->next
= def
;
1873 def
->s_line
= pr_source_line
;
1874 def
->s_file
= s_file
;
1875 def
->name
= qccHunkDupStr(newname
);
1878 def
->ofs
= QCC_GetFreeOffsetSpace(1);
1879 ((qccint
*)qcc_pr_globals
)[def
->ofs
] = *fieldofs
;
1881 if (!first
) first
= def
;
1885 //qcc_printf("Emited %s\n", newname);
1887 *fieldofs
= maxfield
; // final size of the union
1892 static void QCC_PR_ParseInitializerType (int arraysize
, QCC_def_t
*def
, QCC_type_t
*type
, int offset
) {
1895 if (arraysize
> 1) {
1896 //arrays go recursive
1898 for (i
= 0; i
< arraysize
; ++i
) {
1899 QCC_PR_ParseInitializerType(1, def
, type
, offset
+i
*type
->size
);
1900 if (!QCC_PR_EatDelim(",")) break;
1905 if (type
->type
== ev_function
&& (pr_token_type
== TT_DELIM
|| strcmp(pr_token
, "builtin") == 0)) {
1906 // begin function special case
1907 QCC_def_t
*parentfunc
= pr_scope
;
1909 QCC_dfunction_t
*df
;
1913 if (QCC_PR_EatKeyword("builtin")) {
1914 f
= (void *)qccHunkAlloc(sizeof(QCC_function_t
));
1916 locals_start
= locals_end
= 0;
1918 f
= QCC_PR_ParseImmediateStatements(type
);
1922 pr_scope
= parentfunc
;
1923 //tmp = QCC_MakeIntConst(numfunctions);
1924 //fprintf(stderr, "FUNC: [%s]: ofs=%u\n", def->name, def->ofs);
1926 f
->funcnum
= numfunctions
;
1927 if (def
->func
!= NULL
&& def
->func
!= f
) {
1928 qcc_printf("FATAL: WTF?!! (000)\n");
1934 // this function was forward-declared and now it is defined, so fix global literal
1935 G_INT(def
->ofs
) = f
->funcnum
;
1937 if (numfunctions
>= MAX_FUNCTIONS
) QCC_Error(ERR_INTERNAL
, "Too many function defs");
1938 // fill in the dfunction
1939 df
= &functions
[numfunctions
++];
1940 df
->first_statement
= (f
->builtin
? -f
->builtin
: f
->code
);
1941 df
->s_name
= QCC_CopyString(f
->def
->name
);
1942 df
->s_file
= s_file2
;
1943 df
->numparms
= f
->def
->type
->num_parms
;
1944 if (locals_end
== locals_start
) locals_end
= locals_start
= 0;
1945 df
->locals
= locals_end
-locals_start
;
1946 df
->parm_start
= locals_start
;
1947 //fprintf(stderr, "df->numparms=%d\n", df->numparms);
1949 if (np
< 0) np
= (np
== -1 ? MAX_PARMS
: -np
-1);
1950 for (i
= 0, parm
= type
->param
; /*i < df->numparms*/parm
!= NULL
; ++i
, parm
= parm
->next
) {
1951 //fprintf(stderr, " i=%d, parm=%p\n", i, parm);
1952 // k8: void print (string, ...): second parm is NULL (wtf?!)
1954 if (i
!= abs(df
->numparms
)-1) QCC_PR_ParseError(0, "internal compiler error in QCC_PR_ParseInitializerType()");
1955 df
->parm_size
[i
] = 0;
1958 df
->parm_size
[i
] = parm
->size
|(parm
->type
<<8); // record argument type too
1959 if (parm
->type
== ev_field
&& parm
->aux_type
) {
1960 //fprintf(stderr, "arg #%d: field, ofs=%u\n", i, parm->ofs);
1961 df
->parm_size
[i
] |= parm
->aux_type
->type
<<16;
1965 while (i
< np
) df
->parm_size
[i
++] = 0;
1966 // end function special case
1968 } else if (type
->type
== ev_string
&& QCC_PR_EatId("_")) {
1971 if (pr_token_type
!= TT_IMMED
|| pr_immediate_type
->type
!= ev_string
) QCC_PR_ParseError(0, "_() intrinsic accepts only a string immediate");
1972 tmp
= QCC_MakeStringConst(pr_immediate_string
);
1975 if (!pr_scope
|| def
->constant
) {
1977 snprintf(trname
, sizeof(trname
), "dotranslate_%d", ++dotranslate_count
);
1978 dt
= QCC_PR_DummyDef(type_string
, trname
, pr_scope
, 1, offset
, qcc_true
, qcc_true
);
1981 dt
->initialized
= 1;
1984 tmp
= QCC_PR_Expression(TOP_PRIORITY
, EXPR_DISALLOW_COMMA
);
1985 if (qcc_typecmp(type
, tmp
->type
)) {
1986 // you can cast from const 0 to anything
1987 if (tmp
->type
->size
== type
->size
&& (tmp
->type
->type
== ev_integer
|| tmp
->type
->type
== ev_float
) && tmp
->constant
&& !G_INT(tmp
->ofs
)) {
1988 } else if (type
->type
== ev_float
&& tmp
->type
->type
== ev_integer
) {
1989 // cast from int->float will convert
1990 tmp
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_ITOF
], tmp
, 0, NULL
);
1991 } else if (type
->type
== ev_integer
&& tmp
->type
->type
== ev_float
) {
1992 // cast from float->int will convert
1993 tmp
= QCC_PR_Statement(&pr_opcodes
[OP_CONV_FTOI
], tmp
, 0, NULL
);
1995 QCC_PR_ParseErrorPrintDef(ERR_BADIMMEDIATETYPE
, def
, "wrong initializer type");
2000 if (!pr_scope
|| def
->constant
) {
2001 if (tmp
!= NULL
&& !tmp
->constant
) QCC_PR_ParseErrorPrintDef(ERR_BADIMMEDIATETYPE
, def
, "initializer is not constant");
2002 if (def
->initialized
&& tmp
!= NULL
) {
2003 for (i
= 0; (unsigned int)i
< type
->size
; ++i
) {
2004 if (G_INT(offset
+i
) != G_INT(tmp
->ofs
+i
)) QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION
, def
, "incompatible redeclaration");
2006 } else if (tmp
!= NULL
) {
2007 for (i
= 0; (unsigned int)i
< type
->size
; ++i
) G_INT(offset
+i
) = G_INT(tmp
->ofs
+i
);
2009 } else if (tmp
!= NULL
) {
2011 if (def
->initialized
) QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION
, def
, "%s initialised twice", def
->name
);
2012 memset(&lhs
, 0, sizeof(lhs
));
2013 memset(&rhs
, 0, sizeof(rhs
));
2015 for (i
= 0; (unsigned)i
< type
->size
; ) {
2016 rhs
.type
= lhs
.type
= type_float
;
2019 rhs
.ofs
= tmp
->ofs
+i
;
2020 if (type
->size
-i
>= 3) {
2021 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_V
], &rhs
, &lhs
, NULL
));
2024 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes
[OP_STORE_F
], &rhs
, &lhs
, NULL
));
2029 if (tmp
!= NULL
) QCC_FreeTemp(tmp
);
2034 void QCC_PR_ParseInitializerDef (QCC_def_t
*def
, qccbool isvar
, qccbool isconst
) {
2035 def
->constant
= (isconst
|| (!isvar
&& !pr_scope
));
2036 QCC_PR_ParseInitializerType(def
->arraysize
, def
, def
->type
, def
->ofs
);
2037 if (!def
->initialized
) def
->initialized
= 1;
2045 Parse enum definition
2048 static void QCC_PR_ParseEnum (void) {
2051 int isint
= QCC_PR_EatKeyword("int");
2052 if (!isint
) QCC_PR_EatKeyword("float");
2056 char *name
= QCC_PR_ParseName();
2057 if (QCC_PR_EatDelim("=")) {
2058 if (pr_token_type
!= TT_IMMED
&&
2059 ((isint
&& pr_immediate_type
->type
!= ev_integer
) ||
2060 (!isint
&& pr_immediate_type
->type
!= ev_float
))) {
2061 def
= QCC_PR_GetDef(NULL
, QCC_PR_ParseName(), NULL
, qcc_false
, 0, qcc_false
);
2063 if (!def
->constant
) {
2064 QCC_PR_ParseError(ERR_NOTANUMBER
, "enum - %s is not a constant", def
->name
);
2066 if (isint
) iv
= G_INT(def
->ofs
); else fv
= G_FLOAT(def
->ofs
);
2069 QCC_PR_ParseError(ERR_NOTANUMBER
, "enum - not a number");
2072 if (isint
) iv
= pr_immediate
._int
; else fv
= pr_immediate
._float
;
2076 def
= (isint
? QCC_MakeIntConst(iv
) : QCC_MakeFloatConst(fv
));
2077 Hash_Add(&globalstable
, name
, def
, qccHunkAlloc(sizeof(hashtable_bucket_t
)));
2078 if (isint
) ++iv
; else ++fv
;
2079 if (QCC_PR_EatDelim("}")) break;
2081 if (QCC_PR_EatDelim("}")) break; // accept trailing comma
2089 QCC_PR_ParseEnumFlags
2091 Parse enumflags definition
2094 static void QCC_PR_ParseEnumFlags (void) {
2097 int isint
= QCC_PR_EatKeyword("int");
2098 if (!isint
) QCC_PR_EatKeyword("float");
2103 char *name
= QCC_PR_ParseName();
2104 if (QCC_PR_EatDelim("=")) {
2105 if (pr_token_type
!= TT_IMMED
&&
2106 ((isint
&& pr_immediate_type
->type
!= ev_integer
) ||
2107 (!isint
&& pr_immediate_type
->type
!= ev_float
))) {
2108 def
= QCC_PR_GetDef(NULL
, QCC_PR_ParseName(), NULL
, qcc_false
, 0, qcc_false
);
2110 if (!def
->constant
) {
2111 QCC_PR_ParseError(ERR_NOTANUMBER
, "enumflags - %s is not a constant", def
->name
);
2113 if (isint
) iv
= G_INT(def
->ofs
); else fv
= G_FLOAT(def
->ofs
);
2116 QCC_PR_ParseError(ERR_NOTANUMBER
, "enumflags - not a number");
2119 if (isint
) iv
= pr_immediate
._int
; else fv
= pr_immediate
._float
;
2126 if (((i
>>1)<<1) != i
) ++bits
;
2129 if (bits
> 1) QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY
, "enumflags - value %d not a single bit", (int)iv
);
2130 def
= QCC_MakeIntConst(iv
);
2131 Hash_Add(&globalstable
, name
, def
, qccHunkAlloc(sizeof(hashtable_bucket_t
)));
2136 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER
, "enumflags - %f not an integer", fv
);
2139 if (((i
>>1)<<1) != i
) ++bits
;
2142 if (bits
> 1) QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY
, "enumflags - value %d not a single bit", (int)fv
);
2144 def
= QCC_MakeFloatConst(fv
);
2145 Hash_Add(&globalstable
, name
, def
, qccHunkAlloc(sizeof(hashtable_bucket_t
)));
2148 if (QCC_PR_EatDelim("}")) break;
2159 Called at the outer layer and when a local statement is hit
2160 'nocommas': don't process 2nd and other defs
2163 QCC_def_t
*QCC_PR_ParseDefs (qccbool nocommas
) {
2166 QCC_def_t
*def
, *d
, *res
= NULL
;
2167 qccbool shared
= qcc_false
;
2168 qccbool isstatic
= defaultstatic
;
2169 qccbool externfnc
= qcc_false
;
2170 qccbool isconstant
= qcc_false
;
2171 qccbool isvar
= qcc_false
;
2172 qccbool noref
= defaultnoref
;
2173 qccbool nosave
= qcc_true
;
2174 qccbool allocatenew
= qcc_true
;
2175 qccbool inlinefunction
= qcc_false
;
2176 qccbool nonconst
= qcc_false
;
2180 void QCC_PR_ParseArrayDef (void) {
2181 char *oldprfile
= pr_file_p
;
2183 if (QCC_PR_EatDelim("]")) {
2189 if (pr_token_type
== TT_EOF
) break;
2190 if (QCC_PR_EatDelim(",")) ++arraysize
;
2191 if (QCC_PR_EatDelim("}")) break;
2194 pr_file_p
= oldprfile
;
2197 arraysize
= QCC_PR_IntConstExpr();
2200 if (arraysize
< 1) {
2201 QCC_PR_ParseError (ERR_BADARRAYSIZE
, "Definition of array (%s) size is not of a numerical value", name
);
2202 arraysize
= 0; // grrr...
2207 while (QCC_PR_EatDelim(";")) ;
2209 if (QCC_PR_EatKeyword("enum")) { QCC_PR_ParseEnum(); return NULL
; }
2210 if (QCC_PR_EatKeyword("enumflags")) { QCC_PR_ParseEnumFlags(); return NULL
; }
2212 if (QCC_PR_EatKeyword("typedef")) {
2213 type
= QCC_PR_ParseType(qcc_true
, qcc_false
);
2214 if (!type
) QCC_PR_ParseError(ERR_NOTANAME
, "typedef found unexpected tokens");
2215 type
->name
= QCC_CopyString(pr_token
)+strings
;
2222 if (QCC_PR_EatKeyword("const")) isconstant
= noref
= qcc_true
;
2224 while (QCC_PR_EatDelim("[[")) {
2226 if (QCC_PR_EatKeyword("shared")) {
2228 if (pr_scope
) QCC_PR_ParseError(ERR_NOSHAREDLOCALS
, "Cannot have shared locals");
2230 else if (QCC_PR_EatKeyword("extern")) externfnc
= qcc_true
;
2231 else if (QCC_PR_EatKeyword("const")) isconstant
= noref
= qcc_true
;
2232 else if (QCC_PR_EatKeyword("nonconst")) { isconstant
= qcc_false
; isvar
= nonconst
= qcc_true
; }
2233 else if (QCC_PR_EatKeyword("var")) { isvar
= qcc_true
; isconstant
= qcc_false
; nonconst
= qcc_true
; }
2234 else if (!pr_scope
&& QCC_PR_EatKeyword("static")) isstatic
= qcc_true
;
2235 else if (!pr_scope
&& QCC_PR_EatKeyword("nonstatic")) isstatic
= qcc_false
;
2236 else if (QCC_PR_EatKeyword("noref")) noref
= qcc_true
;
2237 else if (QCC_PR_EatKeyword("save")) nosave
= qcc_false
;
2238 else if (QCC_PR_EatKeyword("nosave")) nosave
= qcc_true
;
2239 else QCC_PR_ParseError(0, "invalid attribute: '%s'", pr_token
);
2240 if (QCC_PR_EatDelim("]]")) break;
2242 if (QCC_PR_EatDelim("]]")) break;
2247 type
= QCC_PR_ParseType(qcc_false
, (nocommas
? qcc_true
: qcc_false
));
2248 if (type
== NULL
) return NULL
; // ignore
2250 inlinefunction
= type_inlinefunction
;
2252 if (nocommas
&& (type
->type
== ev_function
|| type
->type
== ev_field
)) {
2253 QCC_PR_ParseError(0, "function or field declaration is not allowed here");
2256 if (externfnc
&& type
->type
!= ev_function
) {
2257 qcc_printf("Only functions may be defined as external (yet)\n");
2258 externfnc
= qcc_false
;
2261 //if (pr_scope && type->type == ev_field) QCC_PR_ParseError("Fields must be global");
2263 if (count
++ == 1 && nocommas
) break;
2265 if (QCC_PR_EatDelim(";")) {
2266 QCC_PR_ParseError(ERR_TYPEWITHNONAME
, "type with no name");
2269 name
= QCC_PR_ParseName();
2270 //fprintf(stderr, "type: %s; name: %s\n", type->name, name);
2272 // check for an array
2273 if (QCC_PR_EatDelim("[")) {
2274 if (nocommas
) QCC_PR_ParseError(0, "array declaration is not allowed here");
2275 QCC_PR_ParseArrayDef();
2279 //fprintf(stderr, "nonc: %d [%s]\n", nonconst, name);
2280 // names consists of [A-Z0-9_] are consts and norefs
2281 if (type
->type
== ev_field
) {
2282 //noref = qcc_true; // assume that all fields are referenced
2283 } else if (!nocommas
&& arraysize
== 1 && !nonconst
) {
2284 qccbool isup
= qcc_true
;
2285 for (const char *n
= name
; *n
; ++n
) {
2286 if (!isdigit(*n
) && !(*n
>= 'A' && *n
<= 'Z') && *n
!= '_') { isup
= qcc_false
; break; }
2288 if (isup
) isconstant
= noref
= qcc_true
;
2291 if (QCC_PR_EatDelim("(")) {
2292 if (nocommas
) QCC_PR_ParseError(0, "function declaration is not allowed here");
2293 if (inlinefunction
) {
2294 QCC_PR_ParseWarning(WARN_UNSAFEFUNCTIONRETURNTYPE
, "Function returning function. Is this what you meant? (suggestion: use typedefs)");
2296 inlinefunction
= qcc_false
;
2297 type
= QCC_PR_ParseFunctionType(qcc_false
, type
);
2300 def
= QCC_PR_GetDef(type
, name
, pr_scope
, allocatenew
, arraysize
, !nosave
);
2301 if (!def
) QCC_PR_ParseError(ERR_NOTANAME
, "%s is not part of someshit", name
);
2302 if (noref
) ++def
->references
;
2303 if (!def
->initialized
&& shared
) {
2304 // shared count as initiialised
2305 def
->shared
= shared
;
2306 def
->initialized
= qcc_true
;
2308 if (externfnc
) def
->initialized
= 2;
2310 if (def
->s_file
== s_file
) {
2311 def
->isstatic
= isstatic
;
2312 } else { //if (type->type != ev_function && defaultstatic) // functions don't quite consitiute a definition
2313 QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION
, def
, "can't redefine non-static as static");
2316 // check for an initialization
2317 if (type
->type
== ev_function
&& pr_scope
) {
2318 if (QCC_PR_EatDelim("=") || QCC_PR_EatDelim("{")) QCC_PR_ParseError(ERR_INITIALISEDLOCALFUNCTION
, "local functions may not be initialised");
2320 while (d
!= def
->deftail
) {
2322 d
->initialized
= 1; // fake function
2323 //k8:WTF?! G_FUNCTION(d->ofs) = 0;
2328 ((type
->type
== ev_function
&& (strchr("\x7b[:", *pr_token
) || strcmp(pr_token
, "builtin") == 0)) ||
2329 QCC_PR_EatDelim("="))) {
2330 // this is an initialisation (or a function)
2331 if (def
->shared
) QCC_PR_ParseError(ERR_SHAREDINITIALISED
, "shared values may not be assigned an initial value");
2333 if (def->initialized == 1) {
2334 if (def->type->type == ev_function) {
2335 i = G_FUNCTION(def->ofs);
2337 QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
2339 QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
2343 QCC_PR_ParseInitializerDef(def
, isvar
, isconstant
);
2345 if (type
->type
== ev_function
&& isvar
) {
2346 isconstant
= !isvar
;
2347 def
->initialized
= 1;
2349 if (type
->type
== ev_field
) {
2350 if (isconstant
) def
->constant
= 2; // special flag on fields, 2, makes the pointer obtained from them also constant
2351 else if (isvar
) def
->constant
= 0;
2352 else def
->constant
= 1;
2354 def
->constant
= isconstant
;
2359 while (d
!= def
->deftail
) {
2361 d
->constant
= def
->constant
;
2362 d
->initialized
= def
->initialized
;
2364 if (nocommas
) break;
2365 } while (QCC_PR_EatDelim(","));
2368 if (type
->type
== ev_function
) {
2369 // semicolon after function definition is optional
2370 QCC_PR_EatDelim(";");
2372 if (!QCC_PR_EatDelim(";")) QCC_PR_ParseWarning(WARN_UNDESIRABLECONVENTION
, "Missing semicolon at end of definition");
2384 compiles the 0 terminated text, adding defintions to the pr structure
2387 qccbool
QCC_PR_CompileFile (char *string
, const char *filename
) {
2389 if (!pr
.memory
) QCC_Error(ERR_INTERNAL
, "PR_CompileFile: Didn't clear");
2390 compilingfile
= filename
;
2391 s_file
= s_file2
= QCC_CopyString(filename
);
2394 memcpy(&oldjb
, &pr_parse_abort
, sizeof(oldjb
));
2395 if (setjmp(pr_parse_abort
)) {
2396 // dont count it as error
2398 //clock up the first line
2399 QCC_PR_NewLine(qcc_false
);
2400 QCC_PR_Lex(); // read first token
2402 while (pr_token_type
!= TT_EOF
) {
2403 if (setjmp(pr_parse_abort
)) {
2404 if (++pr_error_count
> MAX_ERRORS
) {
2405 memcpy(&pr_parse_abort
, &oldjb
, sizeof(oldjb
));
2411 QCC_PR_SkipToSemicolon();
2412 if (pr_token_type
== TT_EOF
) {
2413 memcpy(&pr_parse_abort
, &oldjb
, sizeof(oldjb
));
2417 pr_scope
= NULL
; // outside all functions
2418 QCC_PR_ParseDefs(0);
2420 memcpy(&pr_parse_abort
, &oldjb
, sizeof(oldjb
));
2421 return (pr_error_count
== 0);
2425 qccbool
QCC_Include (const char *filename
) {
2429 QCC_string_t os_file
, os_file2
;
2430 int opr_source_line
;
2431 const char *ocompilingfile
;
2432 struct qcc_includechunk_s
*oldcurrentchunk
;
2433 extern struct qcc_includechunk_s
*currentchunk
;
2435 ocompilingfile
= compilingfile
;
2438 opr_source_line
= pr_source_line
;
2439 opr_file_p
= pr_file_p
;
2440 oldcurrentchunk
= currentchunk
;
2442 strcpy(fname
, filename
);
2443 QCC_LoadFile(fname
, (void*)&newfile
);
2444 currentchunk
= NULL
;
2445 pr_file_p
= newfile
;
2446 QCC_PR_CompileFile(newfile
, fname
);
2447 currentchunk
= oldcurrentchunk
;
2449 compilingfile
= ocompilingfile
;
2452 pr_source_line
= opr_source_line
;
2453 pr_file_p
= opr_file_p
;
2455 //QCC_PR_IncludeChunk(newfile, qcc_false, fname);
2461 void QCC_Clear_Memory (int dofree
) {
2463 if (pr_breaks
) free(pr_breaks
);
2464 if (pr_continues
) free(pr_continues
);
2465 if (pr_cases
) free(pr_cases
);
2466 if (pr_casesdef
) free(pr_casesdef
);
2467 if (pr_casesdef2
) free(pr_casesdef2
);
2468 if (pr_gotos
) free(pr_gotos
);
2469 if (pr_labels
) free(pr_labels
);
2471 max_breaks
= num_breaks
= 0;
2473 max_cases
= num_cases
= 0;
2475 pr_casesdef
= pr_casesdef2
= NULL
;
2476 max_continues
= num_continues
= 0;
2477 pr_continues
= NULL
;
2478 max_gotos
= num_gotos
= 0;
2480 max_labels
= num_labels
= 0;