xref: /plan9-contrib/sys/src/cmd/cpp/nlist.c (revision ad1af46927dd6466ebbfcad9e65ece52cfaf8172)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <stdio.h>
43e12c5d1SDavid du Colombier #include "cpp.h"
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier extern	int getopt(int, char **, char *);
73e12c5d1SDavid du Colombier extern	char	*optarg;
83e12c5d1SDavid du Colombier extern	int	optind;
93e12c5d1SDavid du Colombier int	verbose;
10bd389b36SDavid du Colombier int	Mflag;
113e12c5d1SDavid du Colombier int	Cplusplus;
127dd7cddfSDavid du Colombier int	nolineinfo;
13bd389b36SDavid du Colombier Nlist	*kwdefined;
14219b2ee8SDavid du Colombier char	wd[128];
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier #define	NLSIZE	128
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier Nlist	*nlist[NLSIZE];
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier struct	kwtab {
213e12c5d1SDavid du Colombier 	char	*kw;
223e12c5d1SDavid du Colombier 	int	val;
233e12c5d1SDavid du Colombier 	int	flag;
243e12c5d1SDavid du Colombier } kwtab[] = {
253e12c5d1SDavid du Colombier 	"if",		KIF,		ISKW,
263e12c5d1SDavid du Colombier 	"ifdef",	KIFDEF,		ISKW,
273e12c5d1SDavid du Colombier 	"ifndef",	KIFNDEF,	ISKW,
283e12c5d1SDavid du Colombier 	"elif",		KELIF,		ISKW,
293e12c5d1SDavid du Colombier 	"else",		KELSE,		ISKW,
303e12c5d1SDavid du Colombier 	"endif",	KENDIF,		ISKW,
313e12c5d1SDavid du Colombier 	"include",	KINCLUDE,	ISKW,
323e12c5d1SDavid du Colombier 	"define",	KDEFINE,	ISKW,
333e12c5d1SDavid du Colombier 	"undef",	KUNDEF,		ISKW,
343e12c5d1SDavid du Colombier 	"line",		KLINE,		ISKW,
353e12c5d1SDavid du Colombier 	"error",	KERROR,		ISKW,
36*ad1af469SDavid du Colombier 	"warning",	KWARNING,	ISKW,		// extension to ANSI
373e12c5d1SDavid du Colombier 	"pragma",	KPRAGMA,	ISKW,
383e12c5d1SDavid du Colombier 	"eval",		KEVAL,		ISKW,
39bd389b36SDavid du Colombier 	"defined",	KDEFINED,	ISDEFINED+ISUNCHANGE,
403e12c5d1SDavid du Colombier 	"__LINE__",	KLINENO,	ISMAC+ISUNCHANGE,
413e12c5d1SDavid du Colombier 	"__FILE__",	KFILE,		ISMAC+ISUNCHANGE,
423e12c5d1SDavid du Colombier 	"__DATE__",	KDATE,		ISMAC+ISUNCHANGE,
433e12c5d1SDavid du Colombier 	"__TIME__",	KTIME,		ISMAC+ISUNCHANGE,
443e12c5d1SDavid du Colombier 	"__STDC__",	KSTDC,		ISUNCHANGE,
453e12c5d1SDavid du Colombier 	NULL
463e12c5d1SDavid du Colombier };
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier unsigned long	namebit[077+1];
49bd389b36SDavid du Colombier Nlist 	*np;
503e12c5d1SDavid du Colombier 
513e12c5d1SDavid du Colombier void
523e12c5d1SDavid du Colombier setup(int argc, char **argv)
533e12c5d1SDavid du Colombier {
543e12c5d1SDavid du Colombier 	struct kwtab *kp;
553e12c5d1SDavid du Colombier 	Nlist *np;
563e12c5d1SDavid du Colombier 	Token t;
573e12c5d1SDavid du Colombier 	int fd, i;
583e12c5d1SDavid du Colombier 	char *fp, *dp;
593e12c5d1SDavid du Colombier 	Tokenrow tr;
603e12c5d1SDavid du Colombier 	char *objtype;
617dd7cddfSDavid du Colombier 	char *includeenv;
627dd7cddfSDavid du Colombier 	int firstinclude;
633e12c5d1SDavid du Colombier 	static char nbuf[40];
64bd389b36SDavid du Colombier 	static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
65bd389b36SDavid du Colombier 	static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
667dd7cddfSDavid du Colombier 	int debuginclude = 0;
678deabd96SDavid du Colombier 	int nodot = 0;
687dd7cddfSDavid du Colombier 	char xx[2] = { 0, 0};
693e12c5d1SDavid du Colombier 
703e12c5d1SDavid du Colombier 	for (kp=kwtab; kp->kw; kp++) {
713e12c5d1SDavid du Colombier 		t.t = (uchar*)kp->kw;
723e12c5d1SDavid du Colombier 		t.len = strlen(kp->kw);
733e12c5d1SDavid du Colombier 		np = lookup(&t, 1);
743e12c5d1SDavid du Colombier 		np->flag = kp->flag;
753e12c5d1SDavid du Colombier 		np->val = kp->val;
76bd389b36SDavid du Colombier 		if (np->val == KDEFINED) {
77bd389b36SDavid du Colombier 			kwdefined = np;
78bd389b36SDavid du Colombier 			np->val = NAME;
79bd389b36SDavid du Colombier 			np->vp = &deftr;
80bd389b36SDavid du Colombier 			np->ap = 0;
81bd389b36SDavid du Colombier 		}
823e12c5d1SDavid du Colombier 	}
833e12c5d1SDavid du Colombier 	/*
843e12c5d1SDavid du Colombier 	 * For Plan 9, search /objtype/include, then /sys/include
857dd7cddfSDavid du Colombier 	 * (Note that includelist is searched from high end to low)
863e12c5d1SDavid du Colombier 	 */
873e12c5d1SDavid du Colombier 	if ((objtype = getenv("objtype"))){
884d44ba9bSDavid du Colombier 		snprintf(nbuf, sizeof nbuf, "/%s/include", objtype);
893e12c5d1SDavid du Colombier 		includelist[1].file = nbuf;
903e12c5d1SDavid du Colombier 		includelist[1].always = 1;
913e12c5d1SDavid du Colombier 	} else {
923e12c5d1SDavid du Colombier 		includelist[1].file = NULL;
933e12c5d1SDavid du Colombier 		error(WARNING, "Unknown $objtype");
943e12c5d1SDavid du Colombier 	}
95219b2ee8SDavid du Colombier 	if (getwd(wd, sizeof(wd))==0)
96219b2ee8SDavid du Colombier 		wd[0] = '\0';
973e12c5d1SDavid du Colombier 	includelist[0].file = "/sys/include";
983e12c5d1SDavid du Colombier 	includelist[0].always = 1;
997dd7cddfSDavid du Colombier 	firstinclude = NINCLUDE-2;
1007dd7cddfSDavid du Colombier 	if ((includeenv=getenv("include")) != NULL) {
1017dd7cddfSDavid du Colombier 		char *cp;
1027dd7cddfSDavid du Colombier 		includeenv = strdup(includeenv);
1037dd7cddfSDavid du Colombier 		for (;firstinclude>0; firstinclude--) {
1047dd7cddfSDavid du Colombier 			cp = strtok(includeenv, " ");
1057dd7cddfSDavid du Colombier 			if (cp==NULL)
1067dd7cddfSDavid du Colombier 				break;
1077dd7cddfSDavid du Colombier 			includelist[firstinclude].file = cp;
1087dd7cddfSDavid du Colombier 			includelist[firstinclude].always = 1;
1097dd7cddfSDavid du Colombier 			includeenv = NULL;
1107dd7cddfSDavid du Colombier 		}
1117dd7cddfSDavid du Colombier 	}
1123e12c5d1SDavid du Colombier 	setsource("", -1, 0);
1133e12c5d1SDavid du Colombier 	ARGBEGIN {
1143e12c5d1SDavid du Colombier 		case 'N':
1153e12c5d1SDavid du Colombier 			for (i=0; i<NINCLUDE; i++)
1163e12c5d1SDavid du Colombier 				if (includelist[i].always==1)
1173e12c5d1SDavid du Colombier 					includelist[i].deleted = 1;
1183e12c5d1SDavid du Colombier 			break;
1193e12c5d1SDavid du Colombier 		case 'I':
1207dd7cddfSDavid du Colombier 			for (i=firstinclude; i>=0; i--) {
1213e12c5d1SDavid du Colombier 				if (includelist[i].file==NULL) {
1223e12c5d1SDavid du Colombier 					includelist[i].always = 1;
1233e12c5d1SDavid du Colombier 					includelist[i].file = ARGF();
1243e12c5d1SDavid du Colombier 					break;
1253e12c5d1SDavid du Colombier 				}
1263e12c5d1SDavid du Colombier 			}
1273e12c5d1SDavid du Colombier 			if (i<0)
1287dd7cddfSDavid du Colombier 				error(WARNING, "Too many -I directives");
1293e12c5d1SDavid du Colombier 			break;
1303e12c5d1SDavid du Colombier 		case 'D':
1313e12c5d1SDavid du Colombier 		case 'U':
1323e12c5d1SDavid du Colombier 			setsource("<cmdarg>", -1, ARGF());
1333e12c5d1SDavid du Colombier 			maketokenrow(3, &tr);
1343e12c5d1SDavid du Colombier 			gettokens(&tr, 1);
1353e12c5d1SDavid du Colombier 			doadefine(&tr, ARGC());
1363e12c5d1SDavid du Colombier 			unsetsource();
1373e12c5d1SDavid du Colombier 			break;
138bd389b36SDavid du Colombier 		case 'M':
139bd389b36SDavid du Colombier 			Mflag++;
140bd389b36SDavid du Colombier 			break;
1413e12c5d1SDavid du Colombier 		case 'V':
1423e12c5d1SDavid du Colombier 			verbose++;
1433e12c5d1SDavid du Colombier 			break;
1443e12c5d1SDavid du Colombier 		case '+':
1453e12c5d1SDavid du Colombier 			Cplusplus++;
1463e12c5d1SDavid du Colombier 			break;
1477dd7cddfSDavid du Colombier 		case 'i':
1487dd7cddfSDavid du Colombier 			debuginclude++;
1497dd7cddfSDavid du Colombier 			break;
1507dd7cddfSDavid du Colombier 		case 'P':
1517dd7cddfSDavid du Colombier 			nolineinfo++;
152219b2ee8SDavid du Colombier 			break;
1538deabd96SDavid du Colombier 		case '.':
1548deabd96SDavid du Colombier 			nodot++;
1558deabd96SDavid du Colombier 			break;
1563e12c5d1SDavid du Colombier 		default:
1577dd7cddfSDavid du Colombier 			xx[0] = ARGC();
1587dd7cddfSDavid du Colombier 			error(FATAL, "Unknown argument '%s'", xx);
1593e12c5d1SDavid du Colombier 			break;
1603e12c5d1SDavid du Colombier 	} ARGEND
1613e12c5d1SDavid du Colombier 	dp = ".";
1623e12c5d1SDavid du Colombier 	fp = "<stdin>";
1633e12c5d1SDavid du Colombier 	fd = 0;
1643e12c5d1SDavid du Colombier 	if (argc > 0) {
1653e12c5d1SDavid du Colombier 		if ((fp = strrchr(argv[0], '/')) != NULL) {
1663e12c5d1SDavid du Colombier 			int len = fp - argv[0];
1673e12c5d1SDavid du Colombier 			dp = (char*)newstring((uchar*)argv[0], len+1, 0);
1683e12c5d1SDavid du Colombier 			dp[len] = '\0';
1693e12c5d1SDavid du Colombier 		}
1703e12c5d1SDavid du Colombier 		fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0);
1713e12c5d1SDavid du Colombier 		if ((fd = open(fp, 0)) <= 0)
1723e12c5d1SDavid du Colombier 			error(FATAL, "Can't open input file %s", fp);
1733e12c5d1SDavid du Colombier 	}
1743e12c5d1SDavid du Colombier 	if (argc > 1) {
1753e12c5d1SDavid du Colombier 		int fdo = create(argv[1], 1, 0666);
1763e12c5d1SDavid du Colombier 		if (fdo<0)
1773e12c5d1SDavid du Colombier 			error(FATAL, "Can't open output file %s", argv[1]);
1783e12c5d1SDavid du Colombier 		dup(fdo, 1);
1793e12c5d1SDavid du Colombier 	}
180bd389b36SDavid du Colombier 	if (Mflag)
181bd389b36SDavid du Colombier 		setobjname(fp);
1823e12c5d1SDavid du Colombier 	includelist[NINCLUDE-1].always = 0;
1833e12c5d1SDavid du Colombier 	includelist[NINCLUDE-1].file = dp;
1848deabd96SDavid du Colombier 	if(nodot)
1858deabd96SDavid du Colombier 		includelist[NINCLUDE-1].deleted = 1;
1863e12c5d1SDavid du Colombier 	setsource(fp, fd, NULL);
1877dd7cddfSDavid du Colombier 	if (debuginclude) {
1887dd7cddfSDavid du Colombier 		for (i=0; i<NINCLUDE; i++)
1897dd7cddfSDavid du Colombier 			if (includelist[i].file && includelist[i].deleted==0)
1907dd7cddfSDavid du Colombier 				error(WARNING, "Include: %s", includelist[i].file);
1917dd7cddfSDavid du Colombier 	}
1923e12c5d1SDavid du Colombier }
1933e12c5d1SDavid du Colombier 
1943e12c5d1SDavid du Colombier Nlist *
1953e12c5d1SDavid du Colombier lookup(Token *tp, int install)
1963e12c5d1SDavid du Colombier {
1973e12c5d1SDavid du Colombier 	unsigned int h;
1983e12c5d1SDavid du Colombier 	Nlist *np;
1993e12c5d1SDavid du Colombier 	uchar *cp, *cpe;
2003e12c5d1SDavid du Colombier 
2013e12c5d1SDavid du Colombier 	h = 0;
2023e12c5d1SDavid du Colombier 	for (cp=tp->t, cpe=cp+tp->len; cp<cpe; )
2033e12c5d1SDavid du Colombier 		h += *cp++;
2043e12c5d1SDavid du Colombier 	h %= NLSIZE;
2053e12c5d1SDavid du Colombier 	np = nlist[h];
2063e12c5d1SDavid du Colombier 	while (np) {
2073e12c5d1SDavid du Colombier 		if (*tp->t==*np->name && tp->len==np->len
2083e12c5d1SDavid du Colombier 		 && strncmp((char*)tp->t, (char*)np->name, tp->len)==0)
2093e12c5d1SDavid du Colombier 			return np;
2103e12c5d1SDavid du Colombier 		np = np->next;
2113e12c5d1SDavid du Colombier 	}
2123e12c5d1SDavid du Colombier 	if (install) {
2133e12c5d1SDavid du Colombier 		np = new(Nlist);
214219b2ee8SDavid du Colombier 		np->val = 0;
2153e12c5d1SDavid du Colombier 		np->vp = NULL;
2163e12c5d1SDavid du Colombier 		np->ap = NULL;
2173e12c5d1SDavid du Colombier 		np->flag = 0;
2183e12c5d1SDavid du Colombier 		np->len = tp->len;
2193e12c5d1SDavid du Colombier 		np->name = newstring(tp->t, tp->len, 0);
2203e12c5d1SDavid du Colombier 		np->next = nlist[h];
2213e12c5d1SDavid du Colombier 		nlist[h] = np;
2223e12c5d1SDavid du Colombier 		quickset(tp->t[0], tp->len>1? tp->t[1]:0);
2233e12c5d1SDavid du Colombier 		return np;
2243e12c5d1SDavid du Colombier 	}
2253e12c5d1SDavid du Colombier 	return NULL;
2263e12c5d1SDavid du Colombier }
227