diff directive.c @ 178:0d5b9651b240

Merge Joerg's changes into upstream. (now that they've been thrashed out a bit, include CHANGES entries, etc.)
author David A. Holland
date Fri, 12 Jun 2015 03:05:49 -0400
parents a2f047301c15
children 4c3375895c6e
line wrap: on
line diff
--- a/directive.c	Fri Jun 12 03:04:48 2015 -0400
+++ b/directive.c	Fri Jun 12 03:05:49 2015 -0400
@@ -31,6 +31,8 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
+#include <errno.h>
 
 #include "utils.h"
 #include "mode.h"
@@ -415,11 +417,63 @@
 void
 d_line(struct lineplace *lp, struct place *p2, char *line)
 {
-	(void)p2;
-	(void)line;
+	char *text;
+	size_t oldlen;
+	unsigned long val;
+	char *moretext;
+	size_t moretextlen;
+	char *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);
+
+	/*
+	 * What we should have here: either 1234 "file.c",
+	 * or just 1234.
+	 */
 
-	/* XXX */
-	complain(&lp->current, "Sorry, no #line yet");
+	errno = 0;
+	val = strtoul(text, &moretext, 10);
+	if (errno) {
+		complain(&lp->current, "No line number in #line directive");
+		goto fail;
+	}
+#if UINT_MAX < ULONG_MAX
+	if (val > UINT_MAX) {
+		complain(&lp->current,
+			 "Line number in #line directive too large");
+		goto fail;
+	}
+#endif
+	moretext += strspn(moretext, ws);
+	moretextlen = strlen(moretext);
+	lp->current.column += (moretext - text);
+
+	if (moretextlen > 2 &&
+	    moretext[0] == '"' && moretext[moretextlen-1] == '"') {
+		filename = dostrndup(moretext+1, moretextlen-2);
+		place_changefile(&lp->nextline, filename);
+		dostrfree(filename);
+	}
+	else if (moretextlen > 0) {
+		complain(&lp->current,
+			 "Invalid file name in #line directive");
+		goto fail;
+	}
+
+	lp->nextline.line = val;
+	dostrfree(text);
+	return;
+
+fail:
+	complain(&lp->current, "Before macro expansion: #line %s", line);
+	complain(&lp->current, "After macro expansion: #line %s", text);
+	complain_fail();
+	dostrfree(text);
 }
 
 ////////////////////////////////////////////////////////////
@@ -584,7 +638,7 @@
 	}
 
 	/* check if we have a directive line (# exactly in column 0) */
-	if (line[0] == '#') {
+	if (len > 0 && line[0] == '#') {
 		skip = 1 + strspn(line + 1, ws);
 		assert(skip <= len);
 		lp->current.column += skip;