changeset 164:f14f5352956c

Merge upstream into Joerg's changes.
author David A. Holland
date Fri, 12 Jun 2015 01:00:38 -0400
parents e1dfa3f90b6c (diff) a2c2fe8dbea3 (current diff)
children cc6d6f27d6ee
files directive.c directive.h files.c macro.c place.h
diffstat 13 files changed, 235 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/directive.c	Fri Jun 12 00:56:12 2015 -0400
+++ b/directive.c	Fri Jun 12 01:00:38 2015 -0400
@@ -415,11 +415,61 @@
 void
 d_line(struct lineplace *lp, struct place *p2, 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(&lp->current, "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;
+		}
+	}
+	lp->nextline.line = atoi(start_lineno);
+	if (len_filename) {
+		char *filename = dostrndup(start_filename, len_filename);
+		place_setfile(&lp->nextline, filename);
+		dostrfree(filename);
+	}
+	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);
+	dostrfree(text);
 }
 
 ////////////////////////////////////////////////////////////
--- a/macro.c	Fri Jun 12 00:56:12 2015 -0400
+++ b/macro.c	Fri Jun 12 01:00:38 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:
@@ -885,11 +962,18 @@
 		m = macrotable_findlen(buf, len, false);
 		if (m == NULL || m->inuse) {
 			expand_send(es, p, buf, len);
+		} else if (m->isspecial) {
+			es->curmacro = m;
+			newbuf = expand_substitute(p, es);
+			expand_send(es, p, newbuf, strlen(newbuf));
+			dostrfree(newbuf);
+			es->curmacro = NULL;
+			m->inuse = false;
 		} else if (!m->hasparams) {
 			m->inuse = true;
 			assert(expansionitemarray_num(&m->expansion) == 1);
 			ei = expansionitemarray_get(&m->expansion, 0);
-			assert(ei->isstring);
+			assert(ei->itemtype == EI_STRING);
 			newbuf = macroexpand(p, ei->string,
 					     strlen(ei->string), false);
 			doexpand(es, p, newbuf, strlen(newbuf));
@@ -1177,7 +1261,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 00:56:12 2015 -0400
+++ b/macro.h	Fri Jun 12 01:00:38 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 00:56:12 2015 -0400
+++ b/main.c	Fri Jun 12 01:00:38 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 00:56:12 2015 -0400
+++ b/place.c	Fri Jun 12 01:00:38 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 00:56:12 2015 -0400
+++ b/place.h	Fri Jun 12 01:00:38 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 00:56:12 2015 -0400
+++ b/tests/Makefile	Fri Jun 12 01:00:38 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:00:38 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:00:38 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:00:38 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:00:38 2015 -0400
@@ -0,0 +1,1 @@
+=123:: 456
--- a/utils.c	Fri Jun 12 00:56:12 2015 -0400
+++ b/utils.c	Fri Jun 12 01:00:38 2015 -0400
@@ -44,6 +44,9 @@
 	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 	"_"
 ;
+const char digits[] =
+	"0123456789"
+;
 
 ////////////////////////////////////////////////////////////
 // malloc
--- a/utils.h	Fri Jun 12 00:56:12 2015 -0400
+++ b/utils.h	Fri Jun 12 01:00:38 2015 -0400
@@ -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);