code: plan9front

Download patch

ref: d79edf98b8d3dd8c1cbf9ad1be7728e13ed7a364
parent: ec19c5697f3caf52e6be57049169e2eb048299e6
author: Jacob Moody <moody@posixcafe.org>
date: Tue Mar 21 17:24:16 EDT 2023

cpp: #pragma once support

--- a/sys/src/cmd/cpp/cpp.c
+++ b/sys/src/cmd/cpp/cpp.c
@@ -85,6 +85,7 @@
 {
 	Nlist *np;
 	Token *tp;
+	Dir *d;
 
 	tp = trp->tp;
 	if (tp->type!=NAME) {
@@ -148,7 +149,17 @@
 		break;
 
 	case KPRAGMA:
-		return;
+		tp += 1;
+		if (tp->type!=NAME || tp->len < 4 || memcmp(tp->t, "once", 4) != 0)
+			return;
+		if (nblocked >= NONCE)
+			error(FATAL, "#pragma once list max length exceeded");
+		d = dirfstat(cursource->fd);
+		if (d == nil)
+			error(FATAL, "Out of memory from dirfstat");
+		incblocked[nblocked++] = d->qid;
+		free(d);
+		break;
 
 	case KIFDEF:
 	case KIFNDEF:
--- a/sys/src/cmd/cpp/cpp.h
+++ b/sys/src/cmd/cpp/cpp.h
@@ -2,6 +2,7 @@
 #define	OBS	4096		/* outbut buffer */
 #define	NARG	64		/* Max number arguments to a macro */
 #define	NINCLUDE 64		/* Max number of include directories (-I) */
+#define	NONCE	256		/* Max number of #pragma once directives */
 #define	NIF	32		/* depth of nesting of #if */
 #ifndef EOF
 #define	EOF	(-1)
@@ -153,4 +154,6 @@
 extern	int Cplusplus;
 extern	Nlist *kwdefined;
 extern	Includelist includelist[NINCLUDE];
+extern	Qid incblocked[NONCE];
+extern	int nblocked;
 extern	char wd[];
--- a/sys/src/cmd/cpp/include.c
+++ b/sys/src/cmd/cpp/include.c
@@ -6,6 +6,9 @@
 
 char	*objname;
 
+Qid	incblocked[NONCE];
+int	nblocked = 0;
+
 void
 doinclude(Tokenrow *trp)
 {
@@ -12,6 +15,7 @@
 	char fname[256], iname[256], *p;
 	Includelist *ip;
 	int angled, len, fd, i;
+	Dir *d;
 
 	trp->tp += 1;
 	if (trp->tp>=trp->lp)
@@ -87,6 +91,15 @@
 		write(1,"\n",1);
 	}
 	if (fd >= 0) {
+		d = dirfstat(fd);
+		if (d == nil)
+			error(FATAL, "Out of memory from dirfstat");
+		for (i=0; i<nblocked; i++)
+			if (incblocked[i].path == d->qid.path && incblocked[i].type == d->qid.type) {
+				free(d);
+				return;
+			}
+		free(d);
 		if (++incdepth > 20)
 			error(FATAL, "#include too deeply nested");
 		setsource((char*)newstring((uchar*)iname, strlen(iname), 0), fd, NULL);