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:
M | cc1.h | | | 3 | ++- |
M | code.c | | | 11 | ++++++++++- |
M | expr.c | | | 3 | +-- |
M | 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();