xref: /plan9/sys/src/cmd/cpp/nlist.c (revision 401314a3b4602c168a19b28ed47ba5cbefe42fe0)
1 #include <u.h>
2 #include <libc.h>
3 #include <stdio.h>
4 #include "cpp.h"
5 
6 extern	int getopt(int, char **, char *);
7 extern	char	*optarg;
8 extern	int	optind;
9 int	verbose;
10 int	Mflag;
11 int	Cplusplus;
12 int	nolineinfo;
13 Nlist	*kwdefined;
14 char	wd[128];
15 
16 #define	NLSIZE	128
17 
18 Nlist	*nlist[NLSIZE];
19 
20 struct	kwtab {
21 	char	*kw;
22 	int	val;
23 	int	flag;
24 } kwtab[] = {
25 	"if",		KIF,		ISKW,
26 	"ifdef",	KIFDEF,		ISKW,
27 	"ifndef",	KIFNDEF,	ISKW,
28 	"elif",		KELIF,		ISKW,
29 	"else",		KELSE,		ISKW,
30 	"endif",	KENDIF,		ISKW,
31 	"include",	KINCLUDE,	ISKW,
32 	"define",	KDEFINE,	ISKW,
33 	"undef",	KUNDEF,		ISKW,
34 	"line",		KLINE,		ISKW,
35 	"error",	KERROR,		ISKW,
36 	"warning",	KWARNING,	ISKW,		// extension to ANSI
37 	"pragma",	KPRAGMA,	ISKW,
38 	"eval",		KEVAL,		ISKW,
39 	"defined",	KDEFINED,	ISDEFINED+ISUNCHANGE,
40 	"__LINE__",	KLINENO,	ISMAC+ISUNCHANGE,
41 	"__FILE__",	KFILE,		ISMAC+ISUNCHANGE,
42 	"__DATE__",	KDATE,		ISMAC+ISUNCHANGE,
43 	"__TIME__",	KTIME,		ISMAC+ISUNCHANGE,
44 	"__STDC__",	KSTDC,		ISUNCHANGE,
45 	NULL
46 };
47 
48 unsigned long	namebit[077+1];
49 Nlist 	*np;
50 
51 void
setup(int argc,char ** argv)52 setup(int argc, char **argv)
53 {
54 	struct kwtab *kp;
55 	Nlist *np;
56 	Token t;
57 	int fd, i;
58 	char *fp, *dp;
59 	Tokenrow tr;
60 	char *objtype;
61 	char *includeenv;
62 	int firstinclude;
63 	static char nbuf[40];
64 	static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
65 	static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
66 	int debuginclude = 0;
67 	int nodot = 0;
68 	char xx[2] = { 0, 0};
69 
70 	for (kp=kwtab; kp->kw; kp++) {
71 		t.t = (uchar*)kp->kw;
72 		t.len = strlen(kp->kw);
73 		np = lookup(&t, 1);
74 		np->flag = kp->flag;
75 		np->val = kp->val;
76 		if (np->val == KDEFINED) {
77 			kwdefined = np;
78 			np->val = NAME;
79 			np->vp = &deftr;
80 			np->ap = 0;
81 		}
82 	}
83 	/*
84 	 * For Plan 9, search /objtype/include, then /sys/include
85 	 * (Note that includelist is searched from high end to low)
86 	 */
87 	if ((objtype = getenv("objtype"))){
88 		snprintf(nbuf, sizeof nbuf, "/%s/include", objtype);
89 		includelist[1].file = nbuf;
90 		includelist[1].always = 1;
91 	} else {
92 		includelist[1].file = NULL;
93 		error(WARNING, "Unknown $objtype");
94 	}
95 	if (getwd(wd, sizeof(wd))==0)
96 		wd[0] = '\0';
97 	includelist[0].file = "/sys/include";
98 	includelist[0].always = 1;
99 	firstinclude = NINCLUDE-2;
100 	if ((includeenv=getenv("include")) != NULL) {
101 		char *cp;
102 		includeenv = strdup(includeenv);
103 		for (;firstinclude>0; firstinclude--) {
104 			cp = strtok(includeenv, " ");
105 			if (cp==NULL)
106 				break;
107 			includelist[firstinclude].file = cp;
108 			includelist[firstinclude].always = 1;
109 			includeenv = NULL;
110 		}
111 	}
112 	setsource("", -1, 0);
113 	ARGBEGIN {
114 		case 'N':
115 			for (i=0; i<NINCLUDE; i++)
116 				if (includelist[i].always==1)
117 					includelist[i].deleted = 1;
118 			break;
119 		case 'I':
120 			for (i=firstinclude; i>=0; i--) {
121 				if (includelist[i].file==NULL) {
122 					includelist[i].always = 1;
123 					includelist[i].file = ARGF();
124 					break;
125 				}
126 			}
127 			if (i<0)
128 				error(WARNING, "Too many -I directives");
129 			break;
130 		case 'D':
131 		case 'U':
132 			setsource("<cmdarg>", -1, ARGF());
133 			maketokenrow(3, &tr);
134 			gettokens(&tr, 1);
135 			doadefine(&tr, ARGC());
136 			unsetsource();
137 			break;
138 		case 'M':
139 			Mflag++;
140 			break;
141 		case 'V':
142 			verbose++;
143 			break;
144 		case '+':
145 			Cplusplus++;
146 			break;
147 		case 'i':
148 			debuginclude++;
149 			break;
150 		case 'P':
151 			nolineinfo++;
152 			break;
153 		case '.':
154 			nodot++;
155 			break;
156 		default:
157 			xx[0] = ARGC();
158 			error(FATAL, "Unknown argument '%s'", xx);
159 			break;
160 	} ARGEND
161 	dp = ".";
162 	fp = "<stdin>";
163 	fd = 0;
164 	if (argc > 2)
165 		error(FATAL, "Too many file arguments; see cpp(1)");
166 	if (argc > 0) {
167 		if ((fp = strrchr(argv[0], '/')) != NULL) {
168 			int len = fp - argv[0];
169 			dp = (char*)newstring((uchar*)argv[0], len+1, 0);
170 			dp[len] = '\0';
171 		}
172 		fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0);
173 		if ((fd = open(fp, 0)) < 0)
174 			error(FATAL, "Can't open input file %s", fp);
175 	}
176 	if (argc > 1) {
177 		int fdo = create(argv[1], 1, 0666);
178 		if (fdo<0)
179 			error(FATAL, "Can't open output file %s", argv[1]);
180 		dup(fdo, 1);
181 	}
182 	if (Mflag)
183 		setobjname(fp);
184 	includelist[NINCLUDE-1].always = 0;
185 	includelist[NINCLUDE-1].file = dp;
186 	if(nodot)
187 		includelist[NINCLUDE-1].deleted = 1;
188 	setsource(fp, fd, NULL);
189 	if (debuginclude) {
190 		for (i=0; i<NINCLUDE; i++)
191 			if (includelist[i].file && includelist[i].deleted==0)
192 				error(WARNING, "Include: %s", includelist[i].file);
193 	}
194 }
195 
196 Nlist *
lookup(Token * tp,int install)197 lookup(Token *tp, int install)
198 {
199 	unsigned int h;
200 	Nlist *np;
201 	uchar *cp, *cpe;
202 
203 	h = 0;
204 	for (cp=tp->t, cpe=cp+tp->len; cp<cpe; )
205 		h += *cp++;
206 	h %= NLSIZE;
207 	np = nlist[h];
208 	while (np) {
209 		if (*tp->t==*np->name && tp->len==np->len
210 		 && strncmp((char*)tp->t, (char*)np->name, tp->len)==0)
211 			return np;
212 		np = np->next;
213 	}
214 	if (install) {
215 		np = new(Nlist);
216 		np->val = 0;
217 		np->vp = NULL;
218 		np->ap = NULL;
219 		np->flag = 0;
220 		np->len = tp->len;
221 		np->name = newstring(tp->t, tp->len, 0);
222 		np->next = nlist[h];
223 		nlist[h] = np;
224 		quickset(tp->t[0], tp->len>1? tp->t[1]:0);
225 		return np;
226 	}
227 	return NULL;
228 }
229