diff directive.c @ 165:cc6d6f27d6ee

Fix Joerg's #line code. (avoid redundant whitespace grinding, don't use atoi, be simpler and tidier, etc.)
author David A. Holland
date Fri, 12 Jun 2015 01:30:13 -0400
parents f14f5352956c
children 6ff17ab68b16
line wrap: on
line diff
--- a/directive.c	Fri Jun 12 01:00:38 2015 -0400
+++ b/directive.c	Fri Jun 12 01:30:13 2015 -0400
@@ -31,6 +31,7 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include "utils.h"
 #include "mode.h"
@@ -417,8 +418,10 @@
 {
 	char *text;
 	size_t oldlen;
-	const char *token, *start_lineno, *start_filename;
-	size_t len_lineno, len_filename;
+	unsigned long val;
+	char *moretext;
+	size_t moretextlen;
+	char *filename;
 
 	text = macroexpand(p2, line, strlen(line), true);
 
@@ -427,48 +430,48 @@
 	/* trim to fit, so the malloc debugging won't complain */
 	text = dorealloc(text, oldlen + 1, strlen(text) + 1);
 
-	token = text;
-	token += strspn(token, ws);
-	start_lineno = token;
-	len_lineno = strspn(token, digits);
-	if (len_lineno == 0) {
-		goto illegal_line;
+	/*
+	 * What we should have here: either 1234 "file.c",
+	 * or just 1234.
+	 */
+
+	errno = 0;
+	val = strtoul(text, &moretext, 10);
+	if (errno) {
+		complain(&lp->current, "No line number in #line directive");
+		goto fail;
 	}
-	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;
-		}
+#if UINT_MAX < ULONG_MAX
+	if (val > UINT_MAX) {
+		complain(&lp->current,
+			 "Line number in #line directive too large");
+		goto fail;
 	}
-	lp->nextline.line = atoi(start_lineno);
-	if (len_filename) {
-		char *filename = dostrndup(start_filename, len_filename);
+#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_setfile(&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;
 
-illegal_line:
-	complain(&lp->current, "Illegal #line directive");
-	complain(&lp->current, "Before macro expansion: #include %s", line);
-	complain(&lp->current, "After macro expansion: #include %s", text);
+fail:
+	complain(&lp->current, "Before macro expansion: #line %s", line);
+	complain(&lp->current, "After macro expansion: #line %s", text);
+	complain_fail();
 	dostrfree(text);
 }