aboutsummaryrefslogtreecommitdiff
path: root/tcc.c
diff options
context:
space:
mode:
authorbellard <bellard>2001-12-09 00:27:44 +0000
committerbellard <bellard>2001-12-09 00:27:44 +0000
commitcb693e53188322761a07a87fd7f848e270190c77 (patch)
tree11117c69a55fd8d12050659bef41a76d4c5b8614 /tcc.c
parent9b3c96c88e1f54e1394a6274fbda1654800b5b5b (diff)
downloadtinycc-cb693e53188322761a07a87fd7f848e270190c77.tar.gz
tinycc-cb693e53188322761a07a87fd7f848e270190c77.tar.bz2
fixed switch - preparation for new types
Diffstat (limited to 'tcc.c')
-rw-r--r--tcc.c119
1 files changed, 84 insertions, 35 deletions
diff --git a/tcc.c b/tcc.c
index 3b1dacf..51447bb 100644
--- a/tcc.c
+++ b/tcc.c
@@ -443,6 +443,10 @@ TokenSym *tok_alloc(char *str, int len)
return ts;
pts = &(ts->hash_next);
}
+
+ if (tok_ident >= SYM_FIRST_ANOM)
+ error("memory full");
+
/* expand token table if needed */
i = tok_ident - TOK_IDENT;
if ((i % TOK_ALLOC_INCR) == 0) {
@@ -451,8 +455,9 @@ TokenSym *tok_alloc(char *str, int len)
error("memory full");
table_ident = ptable;
}
+
ts = malloc(sizeof(TokenSym) + len);
- if (!ts || tok_ident >= SYM_FIRST_ANOM)
+ if (!ts)
error("memory full");
table_ident[i] = ts;
ts->tok = tok_ident++;
@@ -1468,7 +1473,7 @@ void macro_subst(int **tok_str, int *tok_len,
}
/* return next token with macro substitution */
-void next()
+void next(void)
{
int len, *ptr;
Sym *nested_list;
@@ -2413,46 +2418,87 @@ int struct_decl(int u)
*/
int ist(void)
{
- int t;
+ int t, u;
Sym *s;
t = 0;
while(1) {
- if (tok == TOK_ENUM) {
- t |= struct_decl(VT_ENUM);
- } else if (tok == TOK_STRUCT || tok == TOK_UNION) {
- t |= struct_decl(VT_STRUCT);
- } else {
- if (tok == TOK_CHAR) {
- t |= VT_BYTE;
- } else if (tok == TOK_VOID) {
- t |= VT_VOID;
- } else if (tok == TOK_SHORT) {
- t |= VT_SHORT;
- } else if (tok == TOK_INT |
- (tok >= TOK_CONST & tok <= TOK_INLINE)) {
- /* ignored types */
- } else if (tok == TOK_FLOAT || tok == TOK_DOUBLE) {
- /* We allow that to compile standard headers */
- // warning("floats not supported");
- } else if (tok == TOK_EXTERN) {
- t |= VT_EXTERN;
- } else if (tok == TOK_STATIC) {
- t |= VT_STATIC;
- } else if (tok == TOK_UNSIGNED) {
- t |= VT_UNSIGNED;
- } else if (tok == TOK_TYPEDEF) {
- t |= VT_TYPEDEF;
- } else {
- s = sym_find(tok);
- if (!s || !(s->t & VT_TYPEDEF))
- break;
- t |= (s->t & ~VT_TYPEDEF);
- }
+ switch(tok) {
+ /* basic types */
+ case TOK_CHAR:
+ u = VT_BYTE;
+ basic_type:
+ next();
+ basic_type1:
+ if ((t & VT_BTYPE) != 0)
+ error("too many basic types %x", t);
+ t |= u;
+ break;
+ case TOK_VOID:
+ u = VT_VOID;
+ goto basic_type;
+ case TOK_SHORT:
+ u = VT_SHORT;
+ goto basic_type;
+ case TOK_INT:
next();
+ break;
+ case TOK_LONG:
+ /* XXX: add long type */
+ u = VT_INT;
+ goto basic_type;
+ case TOK_FLOAT:
+ case TOK_DOUBLE:
+ /* XXX: add float types */
+ u = VT_INT;
+ goto basic_type;
+ case TOK_ENUM:
+ u = struct_decl(VT_ENUM);
+ goto basic_type1;
+ case TOK_STRUCT:
+ case TOK_UNION:
+ u = struct_decl(VT_STRUCT);
+ goto basic_type1;
+
+ /* type modifiers */
+ case TOK_CONST:
+ case TOK_VOLATILE:
+ case TOK_REGISTER:
+ case TOK_SIGNED:
+ case TOK_AUTO:
+ case TOK_INLINE:
+ case TOK_RESTRICT:
+ next();
+ break;
+ case TOK_UNSIGNED:
+ t |= VT_UNSIGNED;
+ next();
+ break;
+
+ /* storage */
+ case TOK_EXTERN:
+ t |= VT_EXTERN;
+ next();
+ break;
+ case TOK_STATIC:
+ t |= VT_STATIC;
+ next();
+ break;
+ case TOK_TYPEDEF:
+ t |= VT_TYPEDEF;
+ next();
+ break;
+ default:
+ s = sym_find(tok);
+ if (!s || !(s->t & VT_TYPEDEF))
+ goto the_end;
+ t |= (s->t & ~VT_TYPEDEF);
+ next();
+ break;
}
t |= 2;
}
+the_end:
return t;
}
@@ -3268,7 +3314,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
case_reg = gv();
skip(')');
a = 0;
- b = 0;
+ b = gjmp(0); /* jump to first case */
c = 0;
block(&a, csym, &b, &c, case_reg);
/* if no default, jmp after switch */
@@ -3284,12 +3330,15 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
a = expr_const();
if (!case_sym)
expect("switch");
+ /* since a case is like a label, we must skip it with a jmp */
+ b = gjmp(0);
gsym(*case_sym);
vset(case_reg, 0);
vpush();
vset(VT_CONST, a);
gen_op(TOK_EQ);
*case_sym = gtst(1, 0);
+ gsym(b);
skip(':');
block(bsym, csym, case_sym, def_sym, case_reg);
} else