xref: /original-bsd/usr.bin/pascal/pxp/yycomm.c (revision 6c57d260)
1 static	char *sccsid = "@(#)yycomm.c	1.1 (Berkeley) 03/02/81";
2 /* Copyright (c) 1979 Regents of the University of California */
3 #
4 /*
5  * pxp - Pascal execution profiler
6  *
7  * Bill Joy UCB
8  * Version 1.2 January 1979
9  */
10 
11 #include "0.h"
12 #include "yy.h"
13 
14 /*
15  * COMMENT PROCESSING CLUSTER
16  *
17  * The global organization of this cluster is as follows.
18  * While parsing the program information is saved in the tree which
19  * tells the source text coordinates (sequence numbers and columns)
20  * bounding each production.  The comments from the source program
21  * are also saved, with information about their source text position
22  * and a classification as to their kind.
23  *
24  * When printing the reformatted program we flush out the comments
25  * at various points using the information in the comments and the parse
26  * tree to "resynchronize".  A number of special cases are recognized to
27  * deal with the vagarities of producing a true "fixed point" so that
28  * a prettyprinted program will re-prettyprint to itself.
29  */
30 
31 /*
32  * Save sequence id's and column markers bounding a production
33  * for later use in placing comments.  We save the sequence id
34  * and column of the leftmost token and the following token, and
35  * the sequence id of the last token in this reduction.
36  * See putcm, putcml, and putcmp below for motivation.
37  */
38 line2of(l)
39 	int l;
40 {
41 
42 	return (lineNof(l, 2));
43 }
44 
45 lineof(l)
46 	int l;
47 {
48 
49 	return (lineNof(l, 1));
50 }
51 
52 lineNof(l, i)
53 	int l, i;
54 {
55 
56 	return(tree(6, l, yypw[i].Wseqid, yypw[i].Wcol, yyseqid, yycol, yypw[N].Wseqid));
57 }
58 
59 /*
60  * After a call to setline, Seqid is set to the sequence id
61  * of the symbol which followed the reduction in which the
62  * lineof call was embedded, Col to the associated column,
63  * and LSeqid to the sequence id of the last symbol in the reduction
64  * (Note that this is exact only if the last symbol was a terminal
65  * this is always true when it matters.)
66  */
67 int	Seqid, Col, LSeqid;
68 
69 /*
70  * Retrieve the information from a call to lineof before beginning the
71  * output of a tree from a reduction.  First flush to the left margin
72  * of the production, and then set so that later calls to putcm, putcml
73  * and putcmp will deal with the right margin of this comment.
74  *
75  * The routine setinfo is called when the lineof has no embedded line
76  * number to avoid trashing the current "line".
77  *
78  * The routine setinfo is often called after completing the output of
79  * the text of a tree to restore Seqid, Col, and LSeqid which may have
80  * been destroyed by the nested processing calls to setline.
81  * In this case the only effect of the call to setinfo is to
82  * modify the above three variables as a side effect.
83  *
84  * We return a word giving information about the comments which were
85  * actually put out.  See putcm for details.
86  */
87 setline(ip)
88 	int *ip;
89 {
90 
91 	line = ip[0];
92 	return(setinfo(ip));
93 }
94 
95 setinfo(ip)
96 	register int *ip;
97 {
98 	register int i;
99 
100 	ip++;
101 	Seqid = *ip++;
102 	Col = *ip++;
103 	i = putcm();
104 	Seqid = *ip++;
105 	Col = *ip++;
106 	LSeqid = *ip++;
107 	return (i);
108 }
109 
110 char	cmeof, incomm;
111 
112 /*
113  * Get the text of a comment from the input stream,
114  * recording its type and linking it into the linked
115  * list of comments headed by cmhp.
116  */
117 getcm(cmdelim)
118 	char cmdelim;
119 {
120 	int cmjust, col;
121 	register struct comment *cp;
122 	register struct commline *kp;
123 
124 	incomm = 1;
125 	if (cmdelim == '*' && yycol == 10 || cmdelim == '{' && yycol == 9)
126 		cmjust = CLMARG;
127 	else if (yytokcnt <= 1)
128 		cmjust = CALIGN;
129 	else if (yywhcnt < 2)
130 		cmjust = CTRAIL;
131 	else
132 		cmjust = CRMARG;
133 	col = yycol - (cmdelim == '{' ? 1 : 2);
134 	cp = tree5(NIL, cmdelim, NIL, cmjust, yyseqid);
135 	cmeof = 0;
136 	do {
137 		kp = getcmline(cmdelim);
138 		if (cp->cml == NIL) {
139 			kp->cml = kp;
140 			kp->cmcol = col;
141 		} else {
142 			kp->cml = cp->cml->cml;
143 			cp->cml->cml = kp;
144 			switch (cp->cmjust) {
145 				case CTRAIL:
146 				case CRMARG:
147 					cp->cmjust = CALIGN;
148 			}
149 		}
150 		cp->cml = kp;
151 	} while (!cmeof);
152 	newcomm(cp);
153 	incomm = 0;
154 }
155 
156 /*
157  * Chain the new comment at "cp" onto the linked list of comments.
158  */
159 newcomm(cp)
160 	register struct comment *cp;
161 {
162 
163 	if (cmhp == NIL)
164 		cp->cmnext = cp;
165 	else {
166 		cp->cmnext = cmhp->cmnext;
167 		cmhp->cmnext = cp;
168 	}
169 	cmhp = cp;
170 }
171 
172 
173 int	nilcml[3];
174 
175 quickcomm(t)
176 	int t;
177 {
178 
179 	if (incomm)
180 		return;
181 	newcomm(tree5(nilcml, NIL, NIL, t, yyseqid));
182 }
183 
184 commincl(cp, ch)
185 	char *cp, ch;
186 {
187 
188 	newcomm(tree5(nilcml, savestr(cp), ch, CINCLUD, yyseqid));
189 }
190 
191 getcmline(cmdelim)
192 	char cmdelim;
193 {
194 	char lastc;
195 	register char *tp;
196 	register CHAR c;
197 	register struct commline *kp;
198 
199 	c = readch();
200 	kp = tree3(NIL, yycol, NIL);
201 	tp = token;
202 	lastc = 0;
203 	for (;;) {
204 		switch (c) {
205 			case '}':
206 				if (cmdelim == '{')
207 					goto endcm;
208 				break;
209 			case ')':
210 				if (cmdelim == '*' && lastc == '*') {
211 					--tp;
212 					goto endcm;
213 				}
214 				break;
215 			case '\n':
216 				goto done;
217 			case -1:
218 				yerror("Comment does not terminate - QUIT");
219 				pexit(ERRS);
220 		}
221 		lastc = c;
222 		*tp++ = c;
223 		c = readch();
224 	}
225 endcm:
226 	cmeof++;
227 done:
228 	*tp = 0;
229 	kp->cmtext = copystr(token);
230 	return (kp);
231 }
232 
233 /*
234  * Flush through the line this token is on.
235  * Ignore if next token on same line as this one.
236  */
237 putcml()
238 {
239 	register int i, SSeqid, SCol;
240 
241 	if (Seqid == LSeqid)
242 		return (1);
243 	SSeqid = Seqid, SCol = Col;
244 	Seqid = LSeqid, Col = 32767;
245 	i = putcm();
246 	Seqid = SSeqid, Col = SCol;
247 	return (i);
248 }
249 
250 /*
251  * Flush to the beginning of the line this token is on.
252  * Ignore if this token is on the same line as the previous one
253  * (effectively since all such already then flushed.)
254  */
255 putcmp()
256 {
257 	register int i, SSeqid, SCol;
258 
259 	SSeqid = Seqid, SCol = Col;
260 	Seqid = LSeqid, Col = 0;
261 	i = putcm();
262 	Seqid = SSeqid, Col = SCol;
263 	return (i);
264 }
265 
266 /*
267  * Put out the comments to the border indicated by Seqid and Col
268  */
269 putcm()
270 {
271 	register struct comment *cp;
272 	register int i;
273 
274 	cp = cmhp;
275 	if (cp == NIL)
276 		return (0);
277 	i = 0;
278 	cp = cp->cmnext;
279 	while (cp->cmseqid < Seqid || cp->cmseqid == Seqid && cp->cml->cmcol < Col) {
280 		putone(cp);
281 		i =| 1 << cp->cmjust;
282 		if (cp->cmnext == cp) {
283 			cmhp = NIL;
284 			break;
285 		}
286 		cp = cp->cmnext;
287 		cmhp->cmnext = cp;
288 	}
289 	return (i);
290 }
291 
292 /*
293  * Put out one comment.
294  * Note that empty lines, form feeds and #include statements
295  * are treated as comments are regurgitated here.
296  */
297 putone(cp)
298 	register struct comment *cp;
299 {
300 	register struct commline *cml, *cmf;
301 
302 	align(cp);
303 	switch (cp->cmjust) {
304 		case CINCLUD:
305 		     /* ppflush() */
306 			if (noinclude == 0) {
307 				putchar('\f');
308 				return;
309 			}
310 			printf("#include %c%s%c", cp->cml, cp->cmdelim, cp->cml);
311 			return;
312 	}
313 	if (stripcomm)
314 		return;
315 	switch (cp->cmjust) {
316 		case CFORM:
317 			ppop("\f");
318 			ppnl();
319 		case CNL:
320 		case CNLBL:
321 			return;
322 	}
323 	ppbra(cp->cmdelim == '{' ? "{" : "(*");
324 	cmf = cp->cml->cml;
325 	ppid(cmf->cmtext);
326 	for (cml = cmf->cml; cml != cmf; cml = cml->cml) {
327 		align(cp);
328 		oneline(cmf->cmcol, cml);
329 	}
330 	ppket(cp->cmdelim == '{' ? "}" : "*)");
331 }
332 
333 /*
334  * Do the preliminary horizontal and vertical
335  * motions necessary before beginning a comment,
336  * or between lines of a mult-line comment.
337  */
338 align(cp)
339 	register struct comment *cp;
340 {
341 
342 	switch (cp->cmjust) {
343 		case CNL:
344 			ppsnl();
345 			break;
346 		case CNLBL:
347 			ppsnlb();
348 			break;
349 		case CFORM:
350 		case CINCLUD:
351 			ppnl();
352 			break;
353 		case CLMARG:
354 			ppnl();
355 			if (profile)
356 				ppid("\t");
357 			break;
358 		case CALIGN:
359 			ppnl();
360 			indent();
361 			break;
362 		case CTRAIL:
363 			ppspac();
364 			break;
365 		case CRMARG:
366 		case CSRMARG:
367 			pptab();
368 			break;
369 	}
370 }
371 
372 /*
373  * One line of a multi-line comment
374  * Deal with alignment and initial white space trimming.
375  * The "margin" indicates where the first line of the
376  * comment began... don't print stuff in this comment
377  * which came before this.
378  */
379 oneline(margin, cml)
380 	int margin;
381 	struct commline *cml;
382 {
383 	register char *tp;
384 	register int i;
385 
386 	for (i = 8, tp = cml->cmtext; i < margin && *tp; tp++)
387 		switch (*tp) {
388 			case ' ':
389 				i++;
390 				continue;
391 			case '\t':
392 				i =+ 8;
393 				i =& ~7;
394 				if (i < margin)
395 					continue;
396 				ppop("\t");
397 			default:
398 				goto out;
399 		}
400 out:
401 	ppid(tp);
402 }
403 
404 /*
405  * Flush all comments
406  */
407 flushcm()
408 {
409 
410 	Seqid = 32767;
411 	return(putcm());
412 }
413 
414 #define	BLANKS	((1 << CNL) | (1 << CNLBL) | (1 << CFORM))
415 noblank(i)
416 	int i;
417 {
418 
419 	return ((i & BLANKS) == 0);
420 }
421 
422 int	needform, neednlbl, neednl, needseqid;
423 
424 needtree()
425 {
426 	register struct comment *cp;
427 
428 	needform = neednlbl = neednl = 0;
429 	cp = cmhp;
430 	if (cp == NIL)
431 		return (0);
432 	do {
433 		switch (cp->cmjust) {
434 			case CNL:
435 				neednl++;
436 				goto seq;
437 			case CNLBL:
438 				neednlbl++;
439 				goto seq;
440 			case CFORM:
441 				needform++;
442 seq:
443 				needseqid = cp->cmseqid;
444 				break;
445 			default:
446 				neednl = neednlbl = needform = 0;
447 				return (1);
448 		}
449 		cp = cp->cmnext;
450 	} while (cp != cmhp);
451 	cmhp = NIL;
452 	return (0);
453 }
454 
455 packtree()
456 {
457 	int save;
458 
459 	save = yyseqid;
460 	yyseqid = needseqid;
461 	for (; needform > 0; needform--)
462 		commform();
463 	for (; neednl > 0; neednl--)
464 		commnl();
465 	for (; neednlbl > 0; neednlbl--)
466 		commnlbl();
467 	yyseqid = save;
468 }
469