xref: /plan9-contrib/sys/src/cmd/cpp/tokens.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
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 maketokenrow(int size, Tokenrow *trp)
78 {
79 	trp->max = size;
80 	trp->bp = (Token *)domalloc(size*sizeof(Token));
81 	trp->tp = trp->bp;
82 	trp->lp = trp->bp;
83 }
84 
85 Token *
86 growtokenrow(Tokenrow *trp)
87 {
88 	int ncur = trp->tp - trp->bp;
89 	int nlast = trp->lp - trp->bp;
90 
91 	trp->max = 3*trp->max/2 + 1;
92 	trp->bp = (Token *)realloc(trp->bp, trp->max*sizeof(Token));
93 	trp->lp = &trp->bp[nlast];
94 	trp->tp = &trp->bp[ncur];
95 	return trp->lp;
96 }
97 
98 /*
99  * Compare a row of tokens, ignoring the content of WS; return !=0 if different
100  */
101 int
102 comparetokens(Tokenrow *tr1, Tokenrow *tr2)
103 {
104 	Token *tp1, *tp2;
105 
106 	tp1 = tr1->tp;
107 	tp2 = tr2->tp;
108 	if (tr1->lp-tp1 != tr2->lp-tp2)
109 		return 1;
110 	for (; tp1<tr1->lp ; tp1++, tp2++) {
111 		if (tp1->type != tp2->type
112 		 || (tp1->wslen==0) != (tp2->wslen==0)
113 		 || tp1->len != tp2->len
114 		 || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0)
115 			return 1;
116 	}
117 	return 0;
118 }
119 
120 /*
121  * replace ntok tokens starting at dtr->tp with the contents of str.
122  * tp ends up pointing just beyond the replacement.
123  * Canonical whitespace is assured on each side.
124  */
125 void
126 insertrow(Tokenrow *dtr, int ntok, Tokenrow *str)
127 {
128 	int nrtok = rowlen(str);
129 
130 	dtr->tp += ntok;
131 	adjustrow(dtr, nrtok-ntok);
132 	dtr->tp -= ntok;
133 	movetokenrow(dtr, str);
134 	makespace(dtr);
135 	dtr->tp += nrtok;
136 	makespace(dtr);
137 }
138 
139 /*
140  * make sure there is WS before trp->tp, if tokens might merge in the output
141  */
142 void
143 makespace(Tokenrow *trp)
144 {
145 	uchar *tt;
146 	Token *tp = trp->tp;
147 
148 	if (tp >= trp->lp)
149 		return;
150 	if (tp->wslen) {
151 		if (tp->flag&XPWS
152 		 && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) {
153 			tp->wslen = 0;
154 			return;
155 		}
156 		tp->t[-1] = ' ';
157 		return;
158 	}
159 	if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])
160 		return;
161 	tt = newstring(tp->t, tp->len, 1);
162 	*tt++ = ' ';
163 	tp->t = tt;
164 	tp->wslen = 1;
165 	tp->flag |= XPWS;
166 }
167 
168 /*
169  * Copy an entire tokenrow into another, at tp.
170  * It is assumed that there is enough space.
171  *  Not strictly conforming.
172  */
173 void
174 movetokenrow(Tokenrow *dtr, Tokenrow *str)
175 {
176 	int nby;
177 
178 	/* nby = sizeof(Token) * (str->lp - str->bp); */
179 	nby = (char *)str->lp - (char *)str->bp;
180 	memmove(dtr->tp, str->bp, nby);
181 }
182 
183 /*
184  * Move the tokens in a row, starting at tr->tp, rightward by nt tokens;
185  * nt may be negative (left move).
186  * The row may need to be grown.
187  * Non-strictly conforming because of the (char *), but easily fixed
188  */
189 void
190 adjustrow(Tokenrow *trp, int nt)
191 {
192 	int nby, size;
193 
194 	if (nt==0)
195 		return;
196 	size = (trp->lp - trp->bp) + nt;
197 	while (size > trp->max)
198 		growtokenrow(trp);
199 	/* nby = sizeof(Token) * (trp->lp - trp->tp); */
200 	nby = (char *)trp->lp - (char *)trp->tp;
201 	if (nby)
202 		memmove(trp->tp+nt, trp->tp, nby);
203 	trp->lp += nt;
204 }
205 
206 /*
207  * Copy a row of tokens into the destination holder, allocating
208  * the space for the contents.  Return the destination.
209  */
210 Tokenrow *
211 copytokenrow(Tokenrow *dtr, Tokenrow *str)
212 {
213 	int len = rowlen(str);
214 
215 	maketokenrow(len, dtr);
216 	movetokenrow(dtr, str);
217 	dtr->lp += len;
218 	return dtr;
219 }
220 
221 /*
222  * Produce a copy of a row of tokens.  Start at trp->tp.
223  * The value strings are copied as well.  The first token
224  * has WS available.
225  */
226 Tokenrow *
227 normtokenrow(Tokenrow *trp)
228 {
229 	Token *tp;
230 	Tokenrow *ntrp = new(Tokenrow);
231 	int len;
232 
233 	len = trp->lp - trp->tp;
234 	if (len<=0)
235 		len = 1;
236 	maketokenrow(len, ntrp);
237 	for (tp=trp->tp; tp < trp->lp; tp++) {
238 		*ntrp->lp = *tp;
239 		if (tp->len) {
240 			ntrp->lp->t = newstring(tp->t, tp->len, 1);
241 			*ntrp->lp->t++ = ' ';
242 			if (tp->wslen)
243 				ntrp->lp->wslen = 1;
244 		}
245 		ntrp->lp++;
246 	}
247 	if (ntrp->lp > ntrp->bp)
248 		ntrp->bp->wslen = 0;
249 	return ntrp;
250 }
251 
252 /*
253  * Debugging
254  */
255 void
256 peektokens(Tokenrow *trp, char *str)
257 {
258 	Token *tp;
259 	int c;
260 
261 	tp = trp->tp;
262 	flushout();
263 	if (str)
264 		fprintf(stderr, "%s ", str);
265 	if (tp <trp->bp || tp>trp->lp)
266 		fprintf(stderr, "(tp offset %d) ", tp-trp->bp);
267 	for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) {
268 		if (tp->type!=NL) {
269 			c = tp->t[tp->len];
270 			tp->t[tp->len] = 0;
271 			fprintf(stderr, "%s", tp->t, tp->len);
272 			tp->t[tp->len] = c;
273 		}
274 		if (tp->type==NAME) {
275 			fprintf(stderr, tp==trp->tp?"{*":"{");
276 			prhideset(tp->hideset);
277 			fprintf(stderr, "} ");
278 		} else
279 			fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type);
280 	}
281 	fprintf(stderr, "\n");
282 	fflush(stderr);
283 }
284 
285 void
286 puttokens(Tokenrow *trp)
287 {
288 	Token *tp;
289 	int len;
290 	uchar *p;
291 
292 	if (verbose)
293 		peektokens(trp, "");
294 	tp = trp->bp;
295 	for (; tp<trp->lp; tp++) {
296 		len = tp->len+tp->wslen;
297 		p = tp->t-tp->wslen;
298 		while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) {
299 			tp++;
300 			len += tp->wslen+tp->len;
301 		}
302 		memcpy(wbp, p, len);
303 		wbp += len;
304 		if (wbp >= &wbuf[OBS]) {
305 			write(1, wbuf, OBS);
306 			if (wbp > &wbuf[OBS])
307 				memcpy(wbuf, wbuf+OBS, wbp - &wbuf[OBS]);
308 			wbp -= OBS;
309 		}
310 	}
311 	trp->tp = tp;
312 	if (cursource->fd==0)
313 		flushout();
314 }
315 
316 void
317 flushout(void)
318 {
319 	if (wbp>wbuf) {
320 		write(1, wbuf, wbp-wbuf);
321 		wbp = wbuf;
322 	}
323 }
324 
325 /*
326  * turn a row into just a newline
327  */
328 void
329 setempty(Tokenrow *trp)
330 {
331 	trp->tp = trp->bp;
332 	trp->lp = trp->bp+1;
333 	*trp->bp = nltoken;
334 }
335 
336 /*
337  * generate a number
338  */
339 char *
340 outnum(char *p, int n)
341 {
342 	if (n>=10)
343 		p = outnum(p, n/10);
344 	*p++ = n%10 + '0';
345 	return p;
346 }
347 
348 /*
349  * allocate and initialize a new string from s, of length l, at offset o
350  * Null terminated.
351  */
352 uchar *
353 newstring(uchar *s, int l, int o)
354 {
355 	uchar *ns = (uchar *)domalloc(l+o+1);
356 
357 	ns[l+o] = '\0';
358 	return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o;
359 }
360