xref: /plan9-contrib/sys/src/cmd/cpp/tokens.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <stdio.h>
4 #include "cpp.h"
5 
6 static char wbuf[2*OBS];
7 static char *wbp = wbuf;
8 
9 /*
10  * 1 for tokens that don't need whitespace when they get inserted
11  * by macro expansion
12  */
13 static const char wstab[] = {
14 	0,	/* END */
15 	0,	/* UNCLASS */
16 	0,	/* NAME */
17 	0,	/* NUMBER */
18 	0,	/* STRING */
19 	0,	/* CCON */
20 	1,	/* NL */
21 	0,	/* WS */
22 	0,	/* DSHARP */
23 	0,	/* EQ */
24 	0,	/* NEQ */
25 	0,	/* LEQ */
26 	0,	/* GEQ */
27 	0,	/* LSH */
28 	0,	/* RSH */
29 	0,	/* LAND */
30 	0,	/* LOR */
31 	0,	/* PPLUS */
32 	0,	/* MMINUS */
33 	0,	/* ARROW */
34 	1,	/* SBRA */
35 	1,	/* SKET */
36 	1,	/* LP */
37 	1,	/* RP */
38 	0,	/* DOT */
39 	0,	/* AND */
40 	0,	/* STAR */
41 	0,	/* PLUS */
42 	0,	/* MINUS */
43 	0,	/* TILDE */
44 	0,	/* NOT */
45 	0,	/* SLASH */
46 	0,	/* PCT */
47 	0,	/* LT */
48 	0,	/* GT */
49 	0,	/* CIRC */
50 	0,	/* OR */
51 	0,	/* QUEST */
52 	0,	/* COLON */
53 	0,	/* ASGN */
54 	1,	/* COMMA */
55 	0,	/* SHARP */
56 	1,	/* SEMIC */
57 	1,	/* CBRA */
58 	1,	/* CKET */
59 	0,	/* ASPLUS */
60  	0,	/* ASMINUS */
61  	0,	/* ASSTAR */
62  	0,	/* ASSLASH */
63  	0,	/* ASPCT */
64  	0,	/* ASCIRC */
65  	0,	/* ASLSH */
66 	0,	/* ASRSH */
67  	0,	/* ASOR */
68  	0,	/* ASAND */
69 	0,	/* ELLIPS */
70 	0,	/* DSHARP1 */
71 	0,	/* NAME1 */
72 	0,	/* DEFINED */
73 	0,	/* UMINUS */
74 };
75 
76 void
77 clearwstab(void)
78 {
79 	int i;
80 
81 	for (i = 0; i < sizeof(wstab); i++)
82 		wstab[i] = 0;
83 }
84 
85 void
86 maketokenrow(int size, Tokenrow *trp)
87 {
88 	trp->max = size;
89 	if (size>0)
90 		trp->bp = (Token *)domalloc(size*sizeof(Token));
91 	else
92 		trp->bp = NULL;
93 	trp->tp = trp->bp;
94 	trp->lp = trp->bp;
95 }
96 
97 Token *
98 growtokenrow(Tokenrow *trp)
99 {
100 	int ncur = trp->tp - trp->bp;
101 	int nlast = trp->lp - trp->bp;
102 
103 	trp->max = 3*trp->max/2 + 1;
104 	trp->bp = (Token *)realloc(trp->bp, trp->max*sizeof(Token));
105 	trp->lp = &trp->bp[nlast];
106 	trp->tp = &trp->bp[ncur];
107 	return trp->lp;
108 }
109 
110 /*
111  * Compare a row of tokens, ignoring the content of WS; return !=0 if different
112  */
113 int
114 comparetokens(Tokenrow *tr1, Tokenrow *tr2)
115 {
116 	Token *tp1, *tp2;
117 
118 	tp1 = tr1->tp;
119 	tp2 = tr2->tp;
120 	if (tr1->lp-tp1 != tr2->lp-tp2)
121 		return 1;
122 	for (; tp1<tr1->lp ; tp1++, tp2++) {
123 		if (tp1->type != tp2->type
124 		 || (tp1->wslen==0) != (tp2->wslen==0)
125 		 || tp1->len != tp2->len
126 		 || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0)
127 			return 1;
128 	}
129 	return 0;
130 }
131 
132 /*
133  * replace ntok tokens starting at dtr->tp with the contents of str.
134  * tp ends up pointing just beyond the replacement.
135  * Canonical whitespace is assured on each side.
136  */
137 void
138 insertrow(Tokenrow *dtr, int ntok, Tokenrow *str)
139 {
140 	int nrtok = rowlen(str);
141 
142 	dtr->tp += ntok;
143 	adjustrow(dtr, nrtok-ntok);
144 	dtr->tp -= ntok;
145 	movetokenrow(dtr, str);
146 	makespace(dtr);
147 	dtr->tp += nrtok;
148 	makespace(dtr);
149 }
150 
151 /*
152  * make sure there is WS before trp->tp, if tokens might merge in the output
153  */
154 void
155 makespace(Tokenrow *trp)
156 {
157 	uchar *tt;
158 	Token *tp = trp->tp;
159 
160 	if (tp >= trp->lp)
161 		return;
162 	if (tp->wslen) {
163 		if (tp->flag&XPWS
164 		 && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) {
165 			tp->wslen = 0;
166 			return;
167 		}
168 		tp->t[-1] = ' ';
169 		return;
170 	}
171 	if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])
172 		return;
173 	tt = newstring(tp->t, tp->len, 1);
174 	*tt++ = ' ';
175 	tp->t = tt;
176 	tp->wslen = 1;
177 	tp->flag |= XPWS;
178 }
179 
180 /*
181  * Copy an entire tokenrow into another, at tp.
182  * It is assumed that there is enough space.
183  *  Not strictly conforming.
184  */
185 void
186 movetokenrow(Tokenrow *dtr, Tokenrow *str)
187 {
188 	int nby;
189 
190 	/* nby = sizeof(Token) * (str->lp - str->bp); */
191 	nby = (char *)str->lp - (char *)str->bp;
192 	memmove(dtr->tp, str->bp, nby);
193 }
194 
195 /*
196  * Move the tokens in a row, starting at tr->tp, rightward by nt tokens;
197  * nt may be negative (left move).
198  * The row may need to be grown.
199  * Non-strictly conforming because of the (char *), but easily fixed
200  */
201 void
202 adjustrow(Tokenrow *trp, int nt)
203 {
204 	int nby, size;
205 
206 	if (nt==0)
207 		return;
208 	size = (trp->lp - trp->bp) + nt;
209 	while (size > trp->max)
210 		growtokenrow(trp);
211 	/* nby = sizeof(Token) * (trp->lp - trp->tp); */
212 	nby = (char *)trp->lp - (char *)trp->tp;
213 	if (nby)
214 		memmove(trp->tp+nt, trp->tp, nby);
215 	trp->lp += nt;
216 }
217 
218 /*
219  * Copy a row of tokens into the destination holder, allocating
220  * the space for the contents.  Return the destination.
221  */
222 Tokenrow *
223 copytokenrow(Tokenrow *dtr, Tokenrow *str)
224 {
225 	int len = rowlen(str);
226 
227 	maketokenrow(len, dtr);
228 	movetokenrow(dtr, str);
229 	dtr->lp += len;
230 	return dtr;
231 }
232 
233 /*
234  * Produce a copy of a row of tokens.  Start at trp->tp.
235  * The value strings are copied as well.  The first token
236  * has WS available.
237  */
238 Tokenrow *
239 normtokenrow(Tokenrow *trp)
240 {
241 	Token *tp;
242 	Tokenrow *ntrp = new(Tokenrow);
243 	int len;
244 
245 	len = trp->lp - trp->tp;
246 	if (len<=0)
247 		len = 1;
248 	maketokenrow(len, ntrp);
249 	for (tp=trp->tp; tp < trp->lp; tp++) {
250 		*ntrp->lp = *tp;
251 		if (tp->len) {
252 			ntrp->lp->t = newstring(tp->t, tp->len, 1);
253 			*ntrp->lp->t++ = ' ';
254 			if (tp->wslen)
255 				ntrp->lp->wslen = 1;
256 		}
257 		ntrp->lp++;
258 	}
259 	if (ntrp->lp > ntrp->bp)
260 		ntrp->bp->wslen = 0;
261 	return ntrp;
262 }
263 
264 /*
265  * Debugging
266  */
267 void
268 peektokens(Tokenrow *trp, char *str)
269 {
270 	Token *tp;
271 	int c;
272 
273 	tp = trp->tp;
274 	flushout();
275 	if (str)
276 		fprintf(stderr, "%s ", str);
277 	if (tp<trp->bp || tp>trp->lp)
278 		fprintf(stderr, "(tp offset %d) ", tp-trp->bp);
279 	for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) {
280 		if (tp->type!=NL) {
281 			c = tp->t[tp->len];
282 			tp->t[tp->len] = 0;
283 			fprintf(stderr, "%s", tp->t, tp->len);
284 			tp->t[tp->len] = c;
285 		}
286 		if (tp->type==NAME) {
287 			fprintf(stderr, tp==trp->tp?"{*":"{");
288 			prhideset(tp->hideset);
289 			fprintf(stderr, "} ");
290 		} else
291 			fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type);
292 	}
293 	fprintf(stderr, "\n");
294 	fflush(stderr);
295 }
296 
297 void
298 puttokens(Tokenrow *trp)
299 {
300 	Token *tp;
301 	int len;
302 	uchar *p;
303 
304 	if (verbose)
305 		peektokens(trp, "");
306 	tp = trp->bp;
307 	for (; tp<trp->lp; tp++) {
308 		len = tp->len+tp->wslen;
309 		p = tp->t-tp->wslen;
310 		while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) {
311 			tp++;
312 			len += tp->wslen+tp->len;
313 		}
314 		if (Mflag==0) {
315 			if (len>OBS/2) {		/* handle giant token */
316 				if (wbp > wbuf)
317 					write(1, wbuf, wbp-wbuf);
318 				write(1, p, len);
319 				wbp = wbuf;
320 			} else {
321 				memcpy(wbp, p, len);
322 				wbp += len;
323 			}
324 		}
325 		if (wbp >= &wbuf[OBS]) {
326 			write(1, wbuf, OBS);
327 			if (wbp > &wbuf[OBS])
328 				memcpy(wbuf, wbuf+OBS, wbp - &wbuf[OBS]);
329 			wbp -= OBS;
330 		}
331 	}
332 	trp->tp = tp;
333 	if (cursource->fd==0)
334 		flushout();
335 }
336 
337 void
338 flushout(void)
339 {
340 	if (wbp>wbuf) {
341 		write(1, wbuf, wbp-wbuf);
342 		wbp = wbuf;
343 	}
344 }
345 
346 /*
347  * turn a row into just a newline
348  */
349 void
350 setempty(Tokenrow *trp)
351 {
352 	trp->tp = trp->bp;
353 	trp->lp = trp->bp+1;
354 	*trp->bp = nltoken;
355 }
356 
357 /*
358  * generate a number
359  */
360 char *
361 outnum(char *p, int n)
362 {
363 	if (n>=10)
364 		p = outnum(p, n/10);
365 	*p++ = n%10 + '0';
366 	return p;
367 }
368 
369 /*
370  * allocate and initialize a new string from s, of length l, at offset o
371  * Null terminated.
372  */
373 uchar *
374 newstring(uchar *s, int l, int o)
375 {
376 	uchar *ns = (uchar *)domalloc(l+o+1);
377 
378 	ns[l+o] = '\0';
379 	return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o;
380 }
381