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