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