changeset 168:8d8a4bfd4684

Merge from upstream
author David A. Holland
date Fri, 12 Jun 2015 01:55:52 -0400
parents fa9752f194c6 (diff) e6eb15635a48 (current diff)
children 80e243f2047d
files macro.c
diffstat 11 files changed, 226 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/directive.c	Fri Jun 12 01:53:42 2015 -0400
+++ b/directive.c	Fri Jun 12 01:55:52 2015 -0400
@@ -31,6 +31,7 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include "utils.h"
 #include "mode.h"
@@ -415,11 +416,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_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;
+
+fail:
+	complain(&lp->current, "Before macro expansion: #line %s", line);
+	complain(&lp->current, "After macro expansion: #line %s", text);
+	complain_fail();
+	dostrfree(text);
 }
 
 ////////////////////////////////////////////////////////////
--- a/macro.c	Fri Jun 12 01:53:42 2015 -0400
+++ b/macro.c	Fri Jun 12 01:55:52 2015 -0400
@@ -28,6 +28,7 @@
  */
 
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -38,7 +39,7 @@
 #include "output.h"
 
 struct expansionitem {
-	bool isstring;
+	enum { EI_PARAM, EI_STRING, EI_FILE, EI_LINE } itemtype;
 	union {
 		char *string;
 		unsigned param;
@@ -50,11 +51,12 @@
 struct macro {
 	struct place defplace;
 	struct place expansionplace;
-	unsigned hash;
-	char *name;
-	bool hasparams;
 	struct stringarray params;
 	struct expansionitemarray expansion;
+	char *name;
+	unsigned hash;
+	bool hasparams;
+	bool isspecial;
 	bool inuse;
 };
 DECLARRAY(macro, static UNUSED);
@@ -76,7 +78,7 @@
 	struct expansionitem *ei;
 
 	ei = domalloc(sizeof(*ei));
-	ei->isstring = true;
+	ei->itemtype = EI_STRING;
 	ei->string = dostrdup(string);
 	return ei;
 }
@@ -88,7 +90,7 @@
 	struct expansionitem *ei;
 
 	ei = domalloc(sizeof(*ei));
-	ei->isstring = true;
+	ei->itemtype = EI_STRING;
 	ei->string = dostrndup(string, len);
 	return ei;
 }
@@ -100,16 +102,38 @@
 	struct expansionitem *ei;
 
 	ei = domalloc(sizeof(*ei));
-	ei->isstring = false;
+	ei->itemtype = EI_PARAM;
 	ei->param = param;
 	return ei;
 }
 
 static
+struct expansionitem *
+expansionitem_create_file(void)
+{
+	struct expansionitem *ei;
+
+	ei = domalloc(sizeof(*ei));
+	ei->itemtype = EI_FILE;
+	return ei;
+}
+
+static
+struct expansionitem *
+expansionitem_create_line(void)
+{
+	struct expansionitem *ei;
+
+	ei = domalloc(sizeof(*ei));
+	ei->itemtype = EI_LINE;
+	return ei;
+}
+
+static
 void
 expansionitem_destroy(struct expansionitem *ei)
 {
-	if (ei->isstring) {
+	if (ei->itemtype == EI_STRING) {
 		dostrfree(ei->string);
 	}
 	dofree(ei, sizeof(*ei));
@@ -120,10 +144,10 @@
 expansionitem_eq(const struct expansionitem *ei1,
 		 const struct expansionitem *ei2)
 {
-	if (ei1->isstring != ei2->isstring) {
+	if ((ei1->itemtype == EI_STRING) != (ei2->itemtype == EI_STRING)) {
 		return false;
 	}
-	if (ei1->isstring) {
+	if (ei1->itemtype == EI_STRING) {
 		if (strcmp(ei1->string, ei2->string) != 0) {
 			return false;
 		}
@@ -148,6 +172,7 @@
 	m->hash = hash;
 	m->name = dostrdup(name);
 	m->hasparams = false;
+	m->isspecial = false;
 	stringarray_init(&m->params);
 	expansionitemarray_init(&m->expansion);
 	m->inuse = false;
@@ -174,6 +199,10 @@
 	struct expansionitem *ei1, *ei2;
 	const char *p1, *p2;
 
+	if (m2->isspecial) {
+		return false;
+	}
+
 	if (strcmp(m1->name, m2->name) != 0) {
 		return false;
 	}
@@ -573,6 +602,32 @@
 }
 
 void
+macro_define_file(struct place *p)
+{
+	struct macro *m;
+	struct expansionitem *ei;
+
+	m = macro_define_common_start(p, "__FILE__", p);
+	m->isspecial = true;
+	ei = expansionitem_create_file();
+	expansionitemarray_add(&m->expansion, ei, NULL);
+	macro_define_common_end(m);
+}
+
+void
+macro_define_line(struct place *p)
+{
+	struct macro *m;
+	struct expansionitem *ei;
+
+	m = macro_define_common_start(p, "__LINE__", p);
+	m->isspecial = true;
+	ei = expansionitem_create_line();
+	expansionitemarray_add(&m->expansion, ei, NULL);
+	macro_define_common_end(m);
+}
+
+void
 macro_define_params(struct place *p1, const char *macro,
 		    struct place *p2, const char *params,
 		    struct place *p3, const char *expansion)
@@ -705,7 +760,7 @@
 
 static
 void
-expand_newarg(struct expstate *es, char *buf, size_t len)
+expand_newarg(struct expstate *es, const char *buf, size_t len)
 {
 	char *text;
 
@@ -715,7 +770,7 @@
 
 static
 void
-expand_appendarg(struct expstate *es, char *buf, size_t len)
+expand_appendarg(struct expstate *es, const char *buf, size_t len)
 {
 	unsigned num;
 	char *text;
@@ -742,6 +797,7 @@
 	char *arg;
 	char *ret;
 	unsigned numargs, numparams;
+	char numbuf[64];
 
 	numargs = stringarray_num(&es->args);
 	numparams = stringarray_num(&es->curmacro->params);
@@ -766,11 +822,20 @@
 	num = expansionitemarray_num(&es->curmacro->expansion);
 	for (i=0; i<num; i++) {
 		ei = expansionitemarray_get(&es->curmacro->expansion, i);
-		if (ei->isstring) {
+		switch (ei->itemtype) {
+		case EI_STRING:
 			len += strlen(ei->string);
-		} else {
+			break;
+		case EI_PARAM:
 			arg = stringarray_get(&es->args, ei->param);
 			len += strlen(arg);
+			break;
+		case EI_FILE:
+			len += strlen(place_getname(p)) + 2;
+			break;
+		case EI_LINE:
+			len += snprintf(numbuf, sizeof(numbuf), "%u", p->line);
+			break;
 		}
 	}
 
@@ -778,11 +843,23 @@
 	*ret = '\0';
 	for (i=0; i<num; i++) {
 		ei = expansionitemarray_get(&es->curmacro->expansion, i);
-		if (ei->isstring) {
+		switch (ei->itemtype) {
+		case EI_STRING:
 			strcat(ret, ei->string);
-		} else {
+			break;
+		case EI_PARAM:
 			arg = stringarray_get(&es->args, ei->param);
 			strcat(ret, arg);
+			break;
+		case EI_FILE:
+			strcat(ret, "\"");
+			strcat(ret, place_getname(p));
+			strcat(ret, "\"");
+			break;
+		case EI_LINE:
+			snprintf(numbuf, sizeof(numbuf), "%u", p->line);
+			strcat(ret, numbuf);
+			break;
 		}
 	}
 
@@ -846,7 +923,7 @@
 
 static
 void
-expand_got_ws(struct expstate *es, struct place *p, char *buf, size_t len)
+expand_got_ws(struct expstate *es, struct place *p, const char *buf, size_t len)
 {
 	switch (es->state) {
 	    case ES_NORMAL:
@@ -1169,7 +1246,16 @@
 macro_sendline(struct place *p, char *buf, size_t len)
 {
 	doexpand(&mainstate, p, buf, len);
-	output(p, "\n", 1);
+	switch (mainstate.state) {
+	    case ES_NORMAL:
+		output(p, "\n", 1);
+		break;
+	    case ES_WANTLPAREN:
+	    case ES_NOARG:
+	    case ES_HAVEARG:
+		expand_got_ws(&mainstate, p, " ", 1);
+		break;
+	}
 }
 
 void
--- a/macro.h	Fri Jun 12 01:53:42 2015 -0400
+++ b/macro.h	Fri Jun 12 01:55:52 2015 -0400
@@ -35,6 +35,8 @@
 void macros_init(void);
 void macros_cleanup(void);
 
+void macro_define_file(struct place *);
+void macro_define_line(struct place *);
 void macro_define_plain(struct place *, const char *macro,
 			struct place *, const char *expansion);
 void macro_define_params(struct place *, const char *macro,
--- a/main.c	Fri Jun 12 01:53:42 2015 -0400
+++ b/main.c	Fri Jun 12 01:55:52 2015 -0400
@@ -195,6 +195,18 @@
 
 static
 void
+apply_special_macros(unsigned *builtin_counter)
+{
+	struct place p;
+
+	place_setbuiltin(&p, ++(*builtin_counter));
+	macro_define_file(&p);
+	place_setbuiltin(&p, ++(*builtin_counter));
+	macro_define_line(&p);
+}
+
+static
+void
 apply_builtin_macro(unsigned num, const char *name, const char *val)
 {
 	struct place p;
@@ -205,35 +217,35 @@
 
 static
 void
-apply_builtin_macros(void)
+apply_builtin_macros(unsigned *builtin_counter)
 {
-	unsigned n = 1;
-
 #ifdef CONFIG_OS
-	apply_builtin_macro(n++, CONFIG_OS, "1");
+	apply_builtin_macro(++(*builtin_counter), CONFIG_OS, "1");
 #endif
 #ifdef CONFIG_OS_2
-	apply_builtin_macro(n++, CONFIG_OS_2, "1");
+	apply_builtin_macro(++(*builtin_counter), CONFIG_OS_2, "1");
 #endif
 
 #ifdef CONFIG_CPU
-	apply_builtin_macro(n++, CONFIG_CPU, "1");
+	apply_builtin_macro(++(*builtin_counter), CONFIG_CPU, "1");
 #endif
 #ifdef CONFIG_CPU_2
-	apply_builtin_macro(n++, CONFIG_CPU_2, "1");
+	apply_builtin_macro(++(*builtin_counter), CONFIG_CPU_2, "1");
 #endif
 
 #ifdef CONFIG_SIZE
-	apply_builtin_macro(n++, CONFIG_SIZE, "1");
+	apply_builtin_macro(++(*builtin_counter), CONFIG_SIZE, "1");
 #endif
 #ifdef CONFIG_BINFMT
-	apply_builtin_macro(n++, CONFIG_BINFMT, "1");
+	apply_builtin_macro(++(*builtin_counter), CONFIG_BINFMT, "1");
 #endif
 
 #ifdef CONFIG_COMPILER
-	apply_builtin_macro(n++, CONFIG_COMPILER, VERSION_MAJOR);
-	apply_builtin_macro(n++, CONFIG_COMPILER_MINOR, VERSION_MINOR);
-	apply_builtin_macro(n++, "__VERSION__", VERSION_LONG);
+	apply_builtin_macro(++(*builtin_counter), CONFIG_COMPILER,
+	  VERSION_MAJOR);
+	apply_builtin_macro(++(*builtin_counter), CONFIG_COMPILER_MINOR,
+	    VERSION_MINOR);
+	apply_builtin_macro(++(*builtin_counter), "__VERSION__", VERSION_LONG);
 #endif
 }
 
@@ -1031,6 +1043,7 @@
 	const char *inputfile = NULL;
 	const char *outputfile = NULL;
 	struct place cmdplace;
+	unsigned builtin_counter;
 	int i;
 
 	progname = strrchr(argv[0], '/');
@@ -1076,7 +1089,11 @@
 	mode.output_file = outputfile;
 
 	loadincludepath();
-	apply_builtin_macros();
+
+	builtin_counter = 0;
+	apply_special_macros(&builtin_counter);
+	apply_builtin_macros(&builtin_counter);
+
 	apply_commandline_macros();
 	read_commandline_files();
 	place_setnowhere(&cmdplace);
--- a/place.c	Fri Jun 12 01:53:42 2015 -0400
+++ b/place.c	Fri Jun 12 01:55:52 2015 -0400
@@ -154,7 +154,17 @@
 	p->column = 1;
 }
 
-static
+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 Jun 12 01:53:42 2015 -0400
+++ b/place.h	Fri Jun 12 01:55:52 2015 -0400
@@ -47,11 +47,13 @@
 
 void place_init(void);
 void place_cleanup(void);
+const char *place_getname(const struct place *);
 
 void place_setnowhere(struct place *p);
 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/Makefile	Fri Jun 12 01:53:42 2015 -0400
+++ b/tests/Makefile	Fri Jun 12 01:55:52 2015 -0400
@@ -4,7 +4,7 @@
 TESTS=\
 	t01 t02 t03 t04 t05 t06 t07 t08 t09 t10 t11 t12 t13 t14 t15 t16 \
 	t17 t18 t19 t20 t21 t22 t23 t24 t25 t26 t27 t28 t29 t30 t31 t32 \
-	t33 t34 t35 t36 t37
+	t33 t34 t35 t36 t37 t38 t39
 
 all: run-tests .WAIT show-diffs
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/t38.c	Fri Jun 12 01:55:52 2015 -0400
@@ -0,0 +1,9 @@
+#define m() __FILE__:__LINE__
+__LINE__
+__FILE__
+__LINE__
+m()
+#line 500
+m()
+#line 600 "foo.c"
+m()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/t38.good	Fri Jun 12 01:55:52 2015 -0400
@@ -0,0 +1,6 @@
+2
+"t38.c"
+4
+"t38.c":5
+"t38.c":500
+"foo.c":600
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/t39.c	Fri Jun 12 01:55:52 2015 -0400
@@ -0,0 +1,3 @@
+#define m(a,b) a::b
+=m(123,
+456)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/t39.good	Fri Jun 12 01:55:52 2015 -0400
@@ -0,0 +1,1 @@
+=123:: 456