fixed switch - preparation for new types

This commit is contained in:
bellard
2001-12-09 00:27:44 +00:00
parent 9b3c96c88e
commit cb693e5318

109
tcc.c
View File

@ -443,6 +443,10 @@ TokenSym *tok_alloc(char *str, int len)
return ts; return ts;
pts = &(ts->hash_next); pts = &(ts->hash_next);
} }
if (tok_ident >= SYM_FIRST_ANOM)
error("memory full");
/* expand token table if needed */ /* expand token table if needed */
i = tok_ident - TOK_IDENT; i = tok_ident - TOK_IDENT;
if ((i % TOK_ALLOC_INCR) == 0) { if ((i % TOK_ALLOC_INCR) == 0) {
@ -451,8 +455,9 @@ TokenSym *tok_alloc(char *str, int len)
error("memory full"); error("memory full");
table_ident = ptable; table_ident = ptable;
} }
ts = malloc(sizeof(TokenSym) + len); ts = malloc(sizeof(TokenSym) + len);
if (!ts || tok_ident >= SYM_FIRST_ANOM) if (!ts)
error("memory full"); error("memory full");
table_ident[i] = ts; table_ident[i] = ts;
ts->tok = tok_ident++; ts->tok = tok_ident++;
@ -1468,7 +1473,7 @@ void macro_subst(int **tok_str, int *tok_len,
} }
/* return next token with macro substitution */ /* return next token with macro substitution */
void next() void next(void)
{ {
int len, *ptr; int len, *ptr;
Sym *nested_list; Sym *nested_list;
@ -2413,46 +2418,87 @@ int struct_decl(int u)
*/ */
int ist(void) int ist(void)
{ {
int t; int t, u;
Sym *s; Sym *s;
t = 0; t = 0;
while(1) { while(1) {
if (tok == TOK_ENUM) { switch(tok) {
t |= struct_decl(VT_ENUM); /* basic types */
} else if (tok == TOK_STRUCT || tok == TOK_UNION) { case TOK_CHAR:
t |= struct_decl(VT_STRUCT); u = VT_BYTE;
} else { basic_type:
if (tok == TOK_CHAR) { next();
t |= VT_BYTE; basic_type1:
} else if (tok == TOK_VOID) { if ((t & VT_BTYPE) != 0)
t |= VT_VOID; error("too many basic types %x", t);
} else if (tok == TOK_SHORT) { t |= u;
t |= VT_SHORT; break;
} else if (tok == TOK_INT | case TOK_VOID:
(tok >= TOK_CONST & tok <= TOK_INLINE)) { u = VT_VOID;
/* ignored types */ goto basic_type;
} else if (tok == TOK_FLOAT || tok == TOK_DOUBLE) { case TOK_SHORT:
/* We allow that to compile standard headers */ u = VT_SHORT;
// warning("floats not supported"); goto basic_type;
} else if (tok == TOK_EXTERN) { case TOK_INT:
t |= VT_EXTERN; next();
} else if (tok == TOK_STATIC) { break;
t |= VT_STATIC; case TOK_LONG:
} else if (tok == TOK_UNSIGNED) { /* 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; t |= VT_UNSIGNED;
} else if (tok == TOK_TYPEDEF) { 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; t |= VT_TYPEDEF;
} else { next();
break;
default:
s = sym_find(tok); s = sym_find(tok);
if (!s || !(s->t & VT_TYPEDEF)) if (!s || !(s->t & VT_TYPEDEF))
break; goto the_end;
t |= (s->t & ~VT_TYPEDEF); t |= (s->t & ~VT_TYPEDEF);
}
next(); next();
break;
} }
t |= 2; t |= 2;
} }
the_end:
return t; return t;
} }
@ -3268,7 +3314,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
case_reg = gv(); case_reg = gv();
skip(')'); skip(')');
a = 0; a = 0;
b = 0; b = gjmp(0); /* jump to first case */
c = 0; c = 0;
block(&a, csym, &b, &c, case_reg); block(&a, csym, &b, &c, case_reg);
/* if no default, jmp after switch */ /* 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(); a = expr_const();
if (!case_sym) if (!case_sym)
expect("switch"); expect("switch");
/* since a case is like a label, we must skip it with a jmp */
b = gjmp(0);
gsym(*case_sym); gsym(*case_sym);
vset(case_reg, 0); vset(case_reg, 0);
vpush(); vpush();
vset(VT_CONST, a); vset(VT_CONST, a);
gen_op(TOK_EQ); gen_op(TOK_EQ);
*case_sym = gtst(1, 0); *case_sym = gtst(1, 0);
gsym(b);
skip(':'); skip(':');
block(bsym, csym, case_sym, def_sym, case_reg); block(bsym, csym, case_sym, def_sym, case_reg);
} else } else