scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 7cfabdc237c6b5e499064d71430c0c82f479e3ee
parent 20617bae7d7e87b7c3a924395850abb957f3aa35
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 25 Oct 2013 18:46:27 +0200

Add integer function

This function parses a integer constant, with all the possible
formats that integers accept.

Diffstat:
Mdecl.c | 8++++----
Mexpr.c | 2+-
Mlex.c | 49++++++++++++++++++++++++++++++++++++++++++++++++-
Msymbol.h | 6+++++-
Mtokens.h | 2+-
5 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/decl.c b/decl.c @@ -47,7 +47,7 @@ dirdcl(register struct ctype *tp, unsigned char ns) len = 0; } else { expect(CONSTANT); - len = atoi(yytext); + len = yyval->i; expect(']'); } pushtype(len); @@ -101,7 +101,7 @@ field_dcl(unsigned char ns) switch (tp->type) { case INT: case BOOL: tp = btype(NULL, BITFLD); - tp->len = atoi(yytext); + tp->len = yyval->i; break; default: error("bit-field '%s' has invalid type", @@ -155,9 +155,9 @@ enum_dcl(struct ctype *base) sym->ctype = tp; if (accept('=')) { expect(CONSTANT); - val = atoi(yytext); + val = yyval->i; } - sym->val = val++; + sym->i = val++; } while (accept(',')); expect('}'); diff --git a/expr.c b/expr.c @@ -24,7 +24,7 @@ primary(void) np = nodesym(sym); break; case CONSTANT: - sym = lookup(NULL, NS_IDEN); + sym = yyval; next(); np = nodesym(sym); break; diff --git a/lex.c b/lex.c @@ -26,12 +26,58 @@ struct keyword { static FILE *yyin; static struct keyword *ktab[NR_KEYW_HASH]; +struct symbol *yyval; + +struct symbol * +integer(char *s, char base) +{ + register struct ctype *tp; + register struct symbol *sym; + static long long v; + static char ch; + + tp = btype(NULL, INT); + +type: switch (ch = toupper(getc(yyin))) { + case 'L': + tp = btype(tp, LONG); + goto type; + case 'U': + tp = btype(tp, UNSIGNED); + goto type; + default: + ungetc(ch, yyin); + } + + v = strtoll(s, NULL, base); + sym = lookup(NULL, NS_IDEN); + sym->ctype = tp; + + switch (sym->ctype->type) { + case INT: + sym->i = v; + break; + case SHORT: + sym->s = v; + break; + case LONG: + sym->l = xmalloc(sizeof(long)); + *sym->l = v; + break; + case LLONG: + sym->ll = xmalloc(sizeof(long long)); + *sym->ll = v; + break; + } + + return sym; +} static char number(void) { register char *bp, ch; - static char base; + static char base, type, sign; if ((ch = getc(yyin)) == '0') { if (toupper(ch = getc(yyin)) == 'X') { @@ -67,6 +113,7 @@ end: if (bp == yytext + IDENTSIZ) error("identifier too long %s", yytext); *bp = '\0'; ungetc(ch, yyin); + yyval = integer(yytext, base); return CONSTANT; } diff --git a/symbol.h b/symbol.h @@ -49,7 +49,11 @@ struct symbol { char *name; struct { union { - short val; /* used in integer constant */ + char c; /* numerical constants */ + short s; + int i; + long *l; + long long *ll; unsigned char label; }; }; diff --git a/tokens.h b/tokens.h @@ -31,7 +31,7 @@ enum tokens { struct symbol; - +extern struct symbol *yyval; extern char yytext[]; extern size_t yylen;