diff macro.c @ 159:8cef6d7227a8

Expand __FILE__ and __LINE__.
author Joerg Sonnenberger <joerg@bec.de>
date Fri, 27 Feb 2015 00:41:46 +0100
parents 19278e2f885d
children 4a4b3d5c41fa
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));