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