shithub: scc

Download patch

ref: 84ae6c8c605f208229ccf38cfcc6b42ae735b1db
parent: 4b68176e2bfbb30df5a9820800a53d87ca7d0620
author: Roberto E. Vargas Caballero <[email protected]>
date: Sun May 10 06:39:32 EDT 2015

Add #line directive

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -263,8 +263,10 @@
 extern uint8_t next(void);
 extern void expect(uint8_t tok);
 extern void discard(void);
-extern char *filename(void);
-extern unsigned short fileline(void);
+extern char *getfname(void);
+extern unsigned short getfline(void);
+extern void setfname(char *name);
+extern void setfline(unsigned short line);
 extern bool addinput(char *fname);
 extern void delinput(void);
 #define accept(t) ((yytoken == (t)) ? next() : 0)
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -9,7 +9,7 @@
 #include "cc1.h"
 
 /* TODO: preprocessor error must not rise recover */
-char *
+static char *
 include(char *s)
 {
 	char fname[FILENAME_MAX], delim, c, *p;
@@ -50,6 +50,39 @@
 }
 
 static char *
+line(char *s)
+{
+	char *p, *q;
+
+	for (p = s; isdigit(*p); ++p)
+		/* nothing */;
+	switch (*p) {
+	case ' ':
+	case '\t':
+		while (isspace(*p))
+			++p;
+		if (*p != '"')
+			goto bad_line;
+		for (q = p+1; *q && *q != '"'; ++q)
+			/* nothing */;
+		if (*q == '\0')
+			goto bad_line;
+		*q = '\0';
+		setfname(p);
+		p = q+1;
+		/* passthrough */
+	case '\0':
+		setfline(atoi(s)-1);
+		return p;
+	default:
+		goto bad_line;
+	}
+
+bad_line:
+	error("incorrect #line directive");
+}
+
+static char *
 pragma(char *s)
 {
 	while (*s)
@@ -60,7 +93,7 @@
 static char *
 usererr(char *s)
 {
-	fprintf(stderr, "%s:%u:error: #error %s\n", filename(), fileline(), s);
+	fprintf(stderr, "%s:%u:error: #error %s\n", getfname(), getfline(), s);
 	exit(-1);
 }
 
@@ -71,6 +104,7 @@
 	unsigned short n;
 	static char **bp, *cmds[] = {
 		"include",
+		"line",
 		"pragma",
 		"error",
 		NULL
@@ -77,6 +111,7 @@
 	};
 	static char *(*funs[])(char *) = {
 		include,
+		line,
 		pragma,
 		usererr
 	};
--- a/cc1/error.c
+++ b/cc1/error.c
@@ -18,7 +18,7 @@
 	if (!flag)
 		return;
 	fprintf(stderr, "%s:%s:%u: ",
-		(flag < 0) ? "error" : "warning", filename(), fileline());
+		(flag < 0) ? "error" : "warning", getfname(), getfline());
 	vfprintf(stderr, fmt, va);
 	putc('\n', stderr);
 	if (flag < 0 && nerrors++ == MAXERRNUM) {
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -45,7 +45,7 @@
 		fname = xstrdup(fname);
 	} else if (!input) {
 		fp = stdin;
-		fname = "(stdin)";
+		fname = xstrdup("<stdin>");
 	} else {
 		fname = input->fname;
 		nline = input->nline;
@@ -79,14 +79,27 @@
 	free(ip);
 }
 
+void
+setfname(char *name)
+{
+	free(input->fname);
+	input->fname = xstrdup(name);
+}
+
 char *
-filename(void)
+getfname(void)
 {
 	return input->fname;
 }
 
+void
+setfline(unsigned short line)
+{
+	input->nline = line;
+}
+
 unsigned short
-fileline(void)
+getfline(void)
 {
 	return input->nline;
 }