xref: /plan9-contrib/sys/src/cmd/cpp/nlist.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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;
12bd389b36SDavid du Colombier Nlist	*kwdefined;
13*219b2ee8SDavid du Colombier char	wd[128];
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier #define	NLSIZE	128
163e12c5d1SDavid du Colombier 
173e12c5d1SDavid du Colombier Nlist	*nlist[NLSIZE];
183e12c5d1SDavid du Colombier 
193e12c5d1SDavid du Colombier struct	kwtab {
203e12c5d1SDavid du Colombier 	char	*kw;
213e12c5d1SDavid du Colombier 	int	val;
223e12c5d1SDavid du Colombier 	int	flag;
233e12c5d1SDavid du Colombier } kwtab[] = {
243e12c5d1SDavid du Colombier 	"if",		KIF,		ISKW,
253e12c5d1SDavid du Colombier 	"ifdef",	KIFDEF,		ISKW,
263e12c5d1SDavid du Colombier 	"ifndef",	KIFNDEF,	ISKW,
273e12c5d1SDavid du Colombier 	"elif",		KELIF,		ISKW,
283e12c5d1SDavid du Colombier 	"else",		KELSE,		ISKW,
293e12c5d1SDavid du Colombier 	"endif",	KENDIF,		ISKW,
303e12c5d1SDavid du Colombier 	"include",	KINCLUDE,	ISKW,
313e12c5d1SDavid du Colombier 	"define",	KDEFINE,	ISKW,
323e12c5d1SDavid du Colombier 	"undef",	KUNDEF,		ISKW,
333e12c5d1SDavid du Colombier 	"line",		KLINE,		ISKW,
343e12c5d1SDavid du Colombier 	"error",	KERROR,		ISKW,
353e12c5d1SDavid du Colombier 	"pragma",	KPRAGMA,	ISKW,
363e12c5d1SDavid du Colombier 	"eval",		KEVAL,		ISKW,
37bd389b36SDavid du Colombier 	"defined",	KDEFINED,	ISDEFINED+ISUNCHANGE,
383e12c5d1SDavid du Colombier 	"__LINE__",	KLINENO,	ISMAC+ISUNCHANGE,
393e12c5d1SDavid du Colombier 	"__FILE__",	KFILE,		ISMAC+ISUNCHANGE,
403e12c5d1SDavid du Colombier 	"__DATE__",	KDATE,		ISMAC+ISUNCHANGE,
413e12c5d1SDavid du Colombier 	"__TIME__",	KTIME,		ISMAC+ISUNCHANGE,
423e12c5d1SDavid du Colombier 	"__STDC__",	KSTDC,		ISUNCHANGE,
433e12c5d1SDavid du Colombier 	NULL
443e12c5d1SDavid du Colombier };
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier unsigned long	namebit[077+1];
47bd389b36SDavid du Colombier Nlist 	*np;
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier void
503e12c5d1SDavid du Colombier setup(int argc, char **argv)
513e12c5d1SDavid du Colombier {
523e12c5d1SDavid du Colombier 	struct kwtab *kp;
533e12c5d1SDavid du Colombier 	Nlist *np;
543e12c5d1SDavid du Colombier 	Token t;
553e12c5d1SDavid du Colombier 	int fd, i;
563e12c5d1SDavid du Colombier 	char *fp, *dp;
573e12c5d1SDavid du Colombier 	Tokenrow tr;
583e12c5d1SDavid du Colombier 	char *objtype;
593e12c5d1SDavid du Colombier 	static char nbuf[40];
60bd389b36SDavid du Colombier 	static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
61bd389b36SDavid du Colombier 	static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier 	for (kp=kwtab; kp->kw; kp++) {
643e12c5d1SDavid du Colombier 		t.t = (uchar*)kp->kw;
653e12c5d1SDavid du Colombier 		t.len = strlen(kp->kw);
663e12c5d1SDavid du Colombier 		np = lookup(&t, 1);
673e12c5d1SDavid du Colombier 		np->flag = kp->flag;
683e12c5d1SDavid du Colombier 		np->val = kp->val;
69bd389b36SDavid du Colombier 		if (np->val == KDEFINED) {
70bd389b36SDavid du Colombier 			kwdefined = np;
71bd389b36SDavid du Colombier 			np->val = NAME;
72bd389b36SDavid du Colombier 			np->vp = &deftr;
73bd389b36SDavid du Colombier 			np->ap = 0;
74bd389b36SDavid du Colombier 		}
753e12c5d1SDavid du Colombier 	}
763e12c5d1SDavid du Colombier 	/*
773e12c5d1SDavid du Colombier 	 * For Plan 9, search /objtype/include, then /sys/include
783e12c5d1SDavid du Colombier 	 * (Note that includelist is searched from high end to low
793e12c5d1SDavid du Colombier 	 */
803e12c5d1SDavid du Colombier 	if ((objtype = getenv("objtype"))){
813e12c5d1SDavid du Colombier 		sprintf(nbuf, "/%s/include", objtype);
823e12c5d1SDavid du Colombier 		includelist[1].file = nbuf;
833e12c5d1SDavid du Colombier 		includelist[1].always = 1;
843e12c5d1SDavid du Colombier 	} else {
853e12c5d1SDavid du Colombier 		includelist[1].file = NULL;
863e12c5d1SDavid du Colombier 		error(WARNING, "Unknown $objtype");
873e12c5d1SDavid du Colombier 	}
88*219b2ee8SDavid du Colombier 	if (getwd(wd, sizeof(wd))==0)
89*219b2ee8SDavid du Colombier 		wd[0] = '\0';
903e12c5d1SDavid du Colombier 	includelist[0].file = "/sys/include";
913e12c5d1SDavid du Colombier 	includelist[0].always = 1;
923e12c5d1SDavid du Colombier 	setsource("", -1, 0);
933e12c5d1SDavid du Colombier 	ARGBEGIN {
943e12c5d1SDavid du Colombier 		case 'N':
953e12c5d1SDavid du Colombier 			for (i=0; i<NINCLUDE; i++)
963e12c5d1SDavid du Colombier 				if (includelist[i].always==1)
973e12c5d1SDavid du Colombier 					includelist[i].deleted = 1;
983e12c5d1SDavid du Colombier 			break;
993e12c5d1SDavid du Colombier 		case 'I':
1003e12c5d1SDavid du Colombier 			for (i=NINCLUDE-2; i>=0; i--) {
1013e12c5d1SDavid du Colombier 				if (includelist[i].file==NULL) {
1023e12c5d1SDavid du Colombier 					includelist[i].always = 1;
1033e12c5d1SDavid du Colombier 					includelist[i].file = ARGF();
1043e12c5d1SDavid du Colombier 					break;
1053e12c5d1SDavid du Colombier 				}
1063e12c5d1SDavid du Colombier 			}
1073e12c5d1SDavid du Colombier 			if (i<0)
1083e12c5d1SDavid du Colombier 				error(FATAL, "Too many -I directives");
1093e12c5d1SDavid du Colombier 			break;
1103e12c5d1SDavid du Colombier 		case 'D':
1113e12c5d1SDavid du Colombier 		case 'U':
1123e12c5d1SDavid du Colombier 			setsource("<cmdarg>", -1, ARGF());
1133e12c5d1SDavid du Colombier 			maketokenrow(3, &tr);
1143e12c5d1SDavid du Colombier 			gettokens(&tr, 1);
1153e12c5d1SDavid du Colombier 			doadefine(&tr, ARGC());
1163e12c5d1SDavid du Colombier 			unsetsource();
1173e12c5d1SDavid du Colombier 			break;
118bd389b36SDavid du Colombier 		case 'M':
119bd389b36SDavid du Colombier 			Mflag++;
120bd389b36SDavid du Colombier 			break;
1213e12c5d1SDavid du Colombier 		case 'V':
1223e12c5d1SDavid du Colombier 			verbose++;
1233e12c5d1SDavid du Colombier 			break;
1243e12c5d1SDavid du Colombier 		case '+':
1253e12c5d1SDavid du Colombier 			Cplusplus++;
1263e12c5d1SDavid du Colombier 			break;
127*219b2ee8SDavid du Colombier 		case 'W':
128*219b2ee8SDavid du Colombier 			clearwstab();
129*219b2ee8SDavid du Colombier 			break;
1303e12c5d1SDavid du Colombier 		default:
1313e12c5d1SDavid du Colombier 			error(FATAL, "Unknown argument");
1323e12c5d1SDavid du Colombier 			break;
1333e12c5d1SDavid du Colombier 	} ARGEND
1343e12c5d1SDavid du Colombier 	dp = ".";
1353e12c5d1SDavid du Colombier 	fp = "<stdin>";
1363e12c5d1SDavid du Colombier 	fd = 0;
1373e12c5d1SDavid du Colombier 	if (argc > 0) {
1383e12c5d1SDavid du Colombier 		if ((fp = strrchr(argv[0], '/')) != NULL) {
1393e12c5d1SDavid du Colombier 			int len = fp - argv[0];
1403e12c5d1SDavid du Colombier 			dp = (char*)newstring((uchar*)argv[0], len+1, 0);
1413e12c5d1SDavid du Colombier 			dp[len] = '\0';
1423e12c5d1SDavid du Colombier 		}
1433e12c5d1SDavid du Colombier 		fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0);
1443e12c5d1SDavid du Colombier 		if ((fd = open(fp, 0)) <= 0)
1453e12c5d1SDavid du Colombier 			error(FATAL, "Can't open input file %s", fp);
1463e12c5d1SDavid du Colombier 	}
1473e12c5d1SDavid du Colombier 	if (argc > 1) {
1483e12c5d1SDavid du Colombier 		int fdo = create(argv[1], 1, 0666);
1493e12c5d1SDavid du Colombier 		if (fdo<0)
1503e12c5d1SDavid du Colombier 			error(FATAL, "Can't open output file %s", argv[1]);
1513e12c5d1SDavid du Colombier 		dup(fdo, 1);
1523e12c5d1SDavid du Colombier 	}
153bd389b36SDavid du Colombier 	if (Mflag)
154bd389b36SDavid du Colombier 		setobjname(fp);
1553e12c5d1SDavid du Colombier 	includelist[NINCLUDE-1].always = 0;
1563e12c5d1SDavid du Colombier 	includelist[NINCLUDE-1].file = dp;
1573e12c5d1SDavid du Colombier 	setsource(fp, fd, NULL);
1583e12c5d1SDavid du Colombier }
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier Nlist *
1613e12c5d1SDavid du Colombier lookup(Token *tp, int install)
1623e12c5d1SDavid du Colombier {
1633e12c5d1SDavid du Colombier 	unsigned int h;
1643e12c5d1SDavid du Colombier 	Nlist *np;
1653e12c5d1SDavid du Colombier 	uchar *cp, *cpe;
1663e12c5d1SDavid du Colombier 
1673e12c5d1SDavid du Colombier 	h = 0;
1683e12c5d1SDavid du Colombier 	for (cp=tp->t, cpe=cp+tp->len; cp<cpe; )
1693e12c5d1SDavid du Colombier 		h += *cp++;
1703e12c5d1SDavid du Colombier 	h %= NLSIZE;
1713e12c5d1SDavid du Colombier 	np = nlist[h];
1723e12c5d1SDavid du Colombier 	while (np) {
1733e12c5d1SDavid du Colombier 		if (*tp->t==*np->name && tp->len==np->len
1743e12c5d1SDavid du Colombier 		 && strncmp((char*)tp->t, (char*)np->name, tp->len)==0)
1753e12c5d1SDavid du Colombier 			return np;
1763e12c5d1SDavid du Colombier 		np = np->next;
1773e12c5d1SDavid du Colombier 	}
1783e12c5d1SDavid du Colombier 	if (install) {
1793e12c5d1SDavid du Colombier 		np = new(Nlist);
180*219b2ee8SDavid du Colombier 		np->val = 0;
1813e12c5d1SDavid du Colombier 		np->vp = NULL;
1823e12c5d1SDavid du Colombier 		np->ap = NULL;
1833e12c5d1SDavid du Colombier 		np->flag = 0;
1843e12c5d1SDavid du Colombier 		np->len = tp->len;
1853e12c5d1SDavid du Colombier 		np->name = newstring(tp->t, tp->len, 0);
1863e12c5d1SDavid du Colombier 		np->next = nlist[h];
1873e12c5d1SDavid du Colombier 		nlist[h] = np;
1883e12c5d1SDavid du Colombier 		quickset(tp->t[0], tp->len>1? tp->t[1]:0);
1893e12c5d1SDavid du Colombier 		return np;
1903e12c5d1SDavid du Colombier 	}
1913e12c5d1SDavid du Colombier 	return NULL;
1923e12c5d1SDavid du Colombier }
193