changeset 160:d6e6b3940780

Fully implement #line.
author Joerg Sonnenberger <joerg@bec.de>
date Fri, 27 Feb 2015 02:06:49 +0100
parents 8cef6d7227a8
children 4a4b3d5c41fa
files directive.c directive.h files.c place.c place.h tests/t38.c tests/t38.good utils.c utils.h
diffstat 9 files changed, 97 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/directive.c	Fri Feb 27 00:41:46 2015 +0100
+++ b/directive.c	Fri Feb 27 02:06:49 2015 +0100
@@ -175,7 +175,7 @@
 
 static
 void
-d_if(struct place *p, struct place *p2, char *line)
+d_if(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	char *expr;
 	bool val;
@@ -200,7 +200,7 @@
 
 static
 void
-d_ifdef(struct place *p, struct place *p2, char *line)
+d_ifdef(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	uncomment(line);
 	oneword("#ifdef", p2, line);
@@ -209,7 +209,7 @@
 
 static
 void
-d_ifndef(struct place *p, struct place *p2, char *line)
+d_ifndef(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	uncomment(line);
 	oneword("#ifndef", p2, line);
@@ -218,7 +218,7 @@
 
 static
 void
-d_elif(struct place *p, struct place *p2, char *line)
+d_elif(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	char *expr;
 	struct place p3 = *p2;
@@ -247,7 +247,7 @@
 
 static
 void
-d_else(struct place *p, struct place *p2, char *line)
+d_else(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	(void)p2;
 	(void)line;
@@ -264,7 +264,7 @@
 
 static
 void
-d_endif(struct place *p, struct place *p2, char *line)
+d_endif(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	(void)p2;
 	(void)line;
@@ -282,7 +282,7 @@
 
 static
 void
-d_define(struct place *p, struct place *p2, char *line)
+d_define(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	size_t pos, argpos;
 	struct place p3, p4;
@@ -347,7 +347,7 @@
 
 static
 void
-d_undef(struct place *p, struct place *p2, char *line)
+d_undef(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	(void)p;
 
@@ -383,7 +383,7 @@
 
 static
 void
-d_include(struct place *p, struct place *p2, char *line)
+d_include(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	char *text;
 	size_t oldlen;
@@ -412,13 +412,63 @@
 
 static
 void
-d_line(struct place *p, struct place *p2, char *line)
+d_line(struct place *p, struct place *p2, struct place *np, char *line)
 {
-	(void)p2;
-	(void)line;
+	char *text;
+	size_t oldlen;
+	const char *token, *start_lineno, *start_filename;
+	size_t len_lineno, len_filename;
+
+	text = macroexpand(p2, line, strlen(line), true);
+
+	oldlen = strlen(text);
+	uncomment(text);
+	/* trim to fit, so the malloc debugging won't complain */
+	text = dorealloc(text, oldlen + 1, strlen(text) + 1);
 
-	/* XXX */
-	complain(p, "Sorry, no #line yet");
+	token = text;
+	token += strspn(token, ws);
+	start_lineno = token;
+	len_lineno = strspn(token, digits);
+	if (len_lineno == 0) {
+		goto illegal_line;
+	}
+	token += len_lineno;
+	token += strspn(ws, token);
+	if (*token == '"') {
+		++token;
+		start_filename = token;
+		len_filename = strcspn(token, "\"");
+		token += len_filename;
+		if (*token != '"' || len_filename == 0) {
+			goto illegal_line;
+		}
+		++token;
+		token += strspn(token, ws);
+		if (*token != '\0') {
+			goto illegal_line;
+		}
+	} else {
+		len_filename = 0;
+		token += strspn(token, ws);
+		if (*token != '\0') {
+			goto illegal_line;
+		}
+	}
+	np->line = atoi(start_lineno);
+	if (len_filename) {
+		char *filename = dostrndup(start_filename, len_filename);
+		place_setfile(np, filename);
+		dostrfree(filename);
+	}
+	dostrfree(text);
+	return;
+
+illegal_line:
+	complain(p, "Illegal #line directive");
+	complain(p, "Before macro expansion: #include %s", line);
+	complain(p, "After macro expansion: #include %s", text);
+	dostrfree(text);
 }
 
 ////////////////////////////////////////////////////////////
@@ -426,7 +476,7 @@
 
 static
 void
-d_warning(struct place *p, struct place *p2, char *line)
+d_warning(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	char *msg;
 
@@ -440,7 +490,7 @@
 
 static
 void
-d_error(struct place *p, struct place *p2, char *line)
+d_error(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	char *msg;
 
@@ -455,7 +505,7 @@
 
 static
 void
-d_pragma(struct place *p, struct place *p2, char *line)
+d_pragma(struct place *p, struct place *p2, struct place *np, char *line)
 {
 	(void)p2;
 
@@ -469,7 +519,8 @@
 static const struct {
 	const char *name;
 	bool ifskip;
-	void (*func)(struct place *, struct place *, char *line);
+	void (*func)(struct place *, struct place *, struct place *,
+		     char *line);
 } directives[] = {
 	{ "define",  true,  d_define },
 	{ "elif",    false, d_elif },
@@ -489,7 +540,7 @@
 
 static
 void
-directive_gotdirective(struct place *p, char *line)
+directive_gotdirective(struct place *p, struct place *np, char *line)
 {
 	struct place p2;
 	size_t len, skip;
@@ -512,7 +563,7 @@
 			if (len < strlen(line)) {
 				line[len] = '\0';
 			}
-			directives[i].func(p, &p2, line);
+			directives[i].func(p, &p2, np, line);
 			return;
 		}
 	}
@@ -574,7 +625,7 @@
 }
 
 void
-directive_gotline(struct place *p, char *line, size_t len)
+directive_gotline(struct place *p, struct place *np, char *line, size_t len)
 {
 	size_t skip;
 
@@ -588,7 +639,7 @@
 		assert(skip <= len);
 		p->column += skip;
 		assert(line[len] == '\0');
-		directive_gotdirective(p, line+skip /*, length = len-skip */);
+		directive_gotdirective(p, np, line+skip);
 		p->column += len-skip;
 	} else if (ifstate->curtrue) {
 		macro_sendline(p, line, len);
--- a/directive.h	Fri Feb 27 00:41:46 2015 +0100
+++ b/directive.h	Fri Feb 27 02:06:49 2015 +0100
@@ -34,6 +34,6 @@
 void directive_init(void);
 void directive_cleanup(void);
 
-void directive_gotline(struct place *p, char *line, size_t len);
+void directive_gotline(struct place *p, struct place *np, char *line, size_t len);
 void directive_goteof(struct place *p);
 
--- a/files.c	Fri Feb 27 00:41:46 2015 +0100
+++ b/files.c	Fri Feb 27 02:06:49 2015 +0100
@@ -275,7 +275,7 @@
 
 		/* if the line isn't empty, process it */
 		if (lineend > linestart) {
-			directive_gotline(&linestartplace,
+			directive_gotline(&linestartplace, &nextlinestartplace,
 					  buf+linestart, lineend-linestart);
 		}
 
--- a/place.c	Fri Feb 27 00:41:46 2015 +0100
+++ b/place.c	Fri Feb 27 02:06:49 2015 +0100
@@ -154,6 +154,17 @@
 	p->column = 1;
 }
 
+void
+place_setfile(struct place *p, const char *name)
+{
+	assert(p->type == P_FILE);
+	if (strcmp(name, p->file->name) == 0) {
+		return;
+	}
+	p->file = placefile_create(&p->file->includedfrom, name,
+	    p->file->fromsystemdir);
+}
+
 const char *
 place_getname(const struct place *p)
 {
--- a/place.h	Fri Feb 27 00:41:46 2015 +0100
+++ b/place.h	Fri Feb 27 02:06:49 2015 +0100
@@ -50,6 +50,7 @@
 void place_setbuiltin(struct place *p, unsigned num);
 void place_setcommandline(struct place *p, unsigned word, unsigned column);
 void place_setfilestart(struct place *p, const struct placefile *pf);
+void place_setfile(struct place *p, const char *name);
 
 const char *place_getparsedir(const struct place *incplace);
 
--- a/tests/t38.c	Fri Feb 27 00:41:46 2015 +0100
+++ b/tests/t38.c	Fri Feb 27 02:06:49 2015 +0100
@@ -3,3 +3,7 @@
 __FILE__
 __LINE__
 m()
+#line 500
+m()
+#line 600 "foo.c"
+m()
--- a/tests/t38.good	Fri Feb 27 00:41:46 2015 +0100
+++ b/tests/t38.good	Fri Feb 27 02:06:49 2015 +0100
@@ -2,3 +2,5 @@
 "t38.c"
 4
 "t38.c":5
+"t38.c":500
+"foo.c":600
--- a/utils.c	Fri Feb 27 00:41:46 2015 +0100
+++ b/utils.c	Fri Feb 27 02:06:49 2015 +0100
@@ -44,6 +44,9 @@
 	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 	"_"
 ;
+const char digits[] =
+	"0123456789"
+;
 
 ////////////////////////////////////////////////////////////
 // malloc
--- a/utils.h	Fri Feb 27 00:41:46 2015 +0100
+++ b/utils.h	Fri Feb 27 02:06:49 2015 +0100
@@ -46,7 +46,7 @@
 
 extern const char ws[];
 extern const char alnum[];
-
+extern const char digits[];
 
 void *domalloc(size_t len);
 void *dorealloc(void *ptr, size_t oldlen, size_t newlen);