scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 3cb05279b1ab7d3b2a97d4aa427a44a1598ec839
parent e55a366ab763ffa5706625ad27271384eee6e857
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 23 Apr 2014 14:52:23 +0200

Add STRING constants

These are the common C strings ended with a 0.

Diffstat:
cc1.h | 3++-
code.c | 11++++++++++-
expr.c | 3+--
lex.c | 70+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 82 insertions(+), 5 deletions(-)

diff --git a/cc1.h b/cc1.h @@ -103,6 +103,7 @@ struct symbol { } s; union { int i; + char *s; struct symbol *sym; uint8_t ns, token; } u; @@ -169,7 +170,7 @@ enum tokens { LE, GE, EQ, NE, AND, OR, MUL_EQ, DIV_EQ, MOD_EQ, ADD_EQ, SUB_EQ, AND_EQ, XOR_EQ, OR_EQ, SHL_EQ, SHR_EQ, - ELLIPSIS, + ELLIPSIS, STRING, CASE, DEFAULT, IF, ELSE, SWITCH, WHILE, DO, FOR, GOTO, CONTINUE, BREAK, RETURN, EOFTOK, NOTOK }; diff --git a/code.c b/code.c @@ -79,7 +79,16 @@ emitsym2(Symbol *sym) static void emitconst(Node *np) { - printf("#%x", np->u.sym->u.i); + register char *bp, c; + Symbol *sym = np->u.sym; + + if (np->type == inttype) { + printf("#%x", sym->u.i); + } else { + putchar('"'); + for (bp = sym->u.s; c = *bp; ++bp) + printf("%02x", (unsigned) c); + } } void diff --git a/expr.c b/expr.c @@ -422,7 +422,7 @@ primary(void) Symbol *sym; switch (yytoken) { - case CONSTANT: case IDEN: + case STRING: case CONSTANT: case IDEN: if ((sym = yylval.sym) == NULL) error("'%s' undeclared", yytext); np = symcode(yylval.sym); @@ -432,7 +432,6 @@ primary(void) } next(); break; - /* TODO: case STRING: */ case '(': next(); np = expr(); diff --git a/lex.c b/lex.c @@ -98,13 +98,79 @@ number(void) } } -end: if (bp == &yybuf[IDENTSIZ]) +end: + if (bp == &yybuf[IDENTSIZ]) error("identifier too long %s", yybuf); *bp = '\0'; ungetc(ch, yyin); return integer(yybuf, base); } +static char * +escape(char *s) +{ + char c; + + switch (getc(yyin)) { + case '\\': c = '\''; break; + case 'a': c = '\a'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + case '\'': c = '\\'; break; + case '"': c ='"'; break; + case 'x': /* TODO: */ + case '0': /* TODO: */ + case 'u': /* TODO: */ + case '\n': + ++linenum, columnum = 1; + return s; + default: + warn(1, "unknown escape sequence"); + return s; + } + + *s = c; + return ++s; +} + +static uint8_t +string(void) +{ + static char buf[STRINGSIZ+1]; + register char *bp; + register int c; + static Symbol *sym; + + getc(yyin); /* discard the initial " */ + + for (bp = buf; bp < &buf[STRINGSIZ]; ) { + switch (c = getc(yyin)) { + case EOF: + error("found EOF while parsing"); + case '"': + goto end_string; + case '\\': + bp = escape(bp); + break; + default: + *bp++ = c; + } + } + +end_string: + if (bp == &buf[IDENTSIZ]) + error("string too long"); + *bp = '\0'; + sym = install("", NS_IDEN); + sym->u.s = xstrdup(buf); + sym->type = mktype(chartype, PTR, NULL, 0); + yynlval.sym = sym; + return STRING; +} + void init_keywords(void) { @@ -322,6 +388,8 @@ next(void) yyntoken = iden(); else if (isdigit(c) || c == '-' || c == '+') yyntoken = number(); + else if (c == '"') + yyntoken = string(); else yyntoken = operator();