changeset 159:8cef6d7227a8

Expand __FILE__ and __LINE__.
author Joerg Sonnenberger <joerg@bec.de>
date Fri, 27 Feb 2015 00:41:46 +0100
parents 19278e2f885d
children d6e6b3940780
files macro.c macro.h main.c tests/Makefile tests/t38.c tests/t38.good
diffstat 6 files changed, 137 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/macro.c	Fri Feb 27 00:23:01 2015 +0100
+++ b/macro.c	Fri Feb 27 00:41:46 2015 +0100
@@ -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;
@@ -55,6 +56,7 @@
 	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;
 		}
@@ -174,6 +198,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 +601,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)
@@ -742,6 +796,7 @@
 	char *arg;
 	char *ret;
 	unsigned numargs, numparams;
+	char numbuf[64];
 
 	numargs = stringarray_num(&es->args);
 	numparams = stringarray_num(&es->curmacro->params);
@@ -766,11 +821,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 +842,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;
 		}
 	}
 
@@ -883,11 +959,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));
--- a/macro.h	Fri Feb 27 00:23:01 2015 +0100
+++ b/macro.h	Fri Feb 27 00:41:46 2015 +0100
@@ -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 Feb 27 00:23:01 2015 +0100
+++ b/main.c	Fri Feb 27 00:41:46 2015 +0100
@@ -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/tests/Makefile	Fri Feb 27 00:23:01 2015 +0100
+++ b/tests/Makefile	Fri Feb 27 00:41:46 2015 +0100
@@ -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
 
 all: run-tests .WAIT show-diffs
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/t38.c	Fri Feb 27 00:41:46 2015 +0100
@@ -0,0 +1,5 @@
+#define m() __FILE__:__LINE__
+__LINE__
+__FILE__
+__LINE__
+m()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/t38.good	Fri Feb 27 00:41:46 2015 +0100
@@ -0,0 +1,4 @@
+2
+"t38.c"
+4
+"t38.c":5