shithub: scc

Download patch

ref: 3cb05279b1ab7d3b2a97d4aa427a44a1598ec839
parent: e55a366ab763ffa5706625ad27271384eee6e857
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Apr 23 10:52:23 EDT 2014

Add STRING constants

These are the common C strings ended with a 0.

--- a/cc1.h
+++ b/cc1.h
@@ -103,6 +103,7 @@
 	} s;
 	union {
 		int i;
+		char *s;
 		struct symbol *sym;
 		uint8_t ns, token;
 	} u;
@@ -169,7 +170,7 @@
 	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
 };
--- a/code.c
+++ b/code.c
@@ -79,7 +79,16 @@
 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
--- a/expr.c
+++ b/expr.c
@@ -422,7 +422,7 @@
 	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 @@
 		}
 		next();
 		break;
-	/* TODO: case STRING: */
 	case '(':
 		next();
 		np = expr();
--- a/lex.c
+++ b/lex.c
@@ -98,7 +98,8 @@
 		}
 	}
 
-end:	if (bp == &yybuf[IDENTSIZ])
+end:
+	if (bp == &yybuf[IDENTSIZ])
 		error("identifier too long %s", yybuf);
 	*bp = '\0';
 	ungetc(ch, yyin);
@@ -105,6 +106,71 @@
 	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 @@
 		yyntoken = iden();
 	else if (isdigit(c) || c == '-' || c == '+')
 		yyntoken = number();
+	else if (c == '"')
+		yyntoken = string();
 	else
 		yyntoken = operator();