xref: /csrg-svn/usr.bin/pascal/pxp/yycomm.c (revision 30650)
12868Speter /*
222243Sdist  * Copyright (c) 1980 Regents of the University of California.
322243Sdist  * All rights reserved.  The Berkeley software License Agreement
422243Sdist  * specifies the terms and conditions for redistribution.
522243Sdist  */
622243Sdist 
722243Sdist #ifndef lint
8*30650Slepreau static char sccsid[] = "@(#)yycomm.c	5.2 (Berkeley) 03/17/87";
922243Sdist #endif not lint
1022243Sdist 
1122243Sdist /*
122868Speter  * pxp - Pascal execution profiler
132868Speter  *
142868Speter  * Bill Joy UCB
152868Speter  * Version 1.2 January 1979
162868Speter  */
172868Speter 
1810733Smckusick #include "whoami.h"
192868Speter #include "0.h"
202868Speter #include "yy.h"
212868Speter 
222868Speter /*
232868Speter  * COMMENT PROCESSING CLUSTER
242868Speter  *
252868Speter  * The global organization of this cluster is as follows.
262868Speter  * While parsing the program information is saved in the tree which
272868Speter  * tells the source text coordinates (sequence numbers and columns)
282868Speter  * bounding each production.  The comments from the source program
292868Speter  * are also saved, with information about their source text position
302868Speter  * and a classification as to their kind.
312868Speter  *
322868Speter  * When printing the reformatted program we flush out the comments
332868Speter  * at various points using the information in the comments and the parse
342868Speter  * tree to "resynchronize".  A number of special cases are recognized to
352868Speter  * deal with the vagarities of producing a true "fixed point" so that
362868Speter  * a prettyprinted program will re-prettyprint to itself.
372868Speter  */
382868Speter 
392868Speter /*
402868Speter  * Save sequence id's and column markers bounding a production
412868Speter  * for later use in placing comments.  We save the sequence id
422868Speter  * and column of the leftmost token and the following token, and
432868Speter  * the sequence id of the last token in this reduction.
442868Speter  * See putcm, putcml, and putcmp below for motivation.
452868Speter  */
462868Speter line2of(l)
472868Speter 	int l;
482868Speter {
492868Speter 
502868Speter 	return (lineNof(l, 2));
512868Speter }
522868Speter 
532868Speter lineof(l)
542868Speter 	int l;
552868Speter {
562868Speter 
572868Speter 	return (lineNof(l, 1));
582868Speter }
592868Speter 
602868Speter lineNof(l, i)
612868Speter 	int l, i;
622868Speter {
632868Speter 
642868Speter 	return(tree(6, l, yypw[i].Wseqid, yypw[i].Wcol, yyseqid, yycol, yypw[N].Wseqid));
652868Speter }
662868Speter 
672868Speter /*
682868Speter  * After a call to setline, Seqid is set to the sequence id
692868Speter  * of the symbol which followed the reduction in which the
702868Speter  * lineof call was embedded, Col to the associated column,
712868Speter  * and LSeqid to the sequence id of the last symbol in the reduction
722868Speter  * (Note that this is exact only if the last symbol was a terminal
732868Speter  * this is always true when it matters.)
742868Speter  */
752868Speter int	Seqid, Col, LSeqid;
762868Speter 
772868Speter /*
782868Speter  * Retrieve the information from a call to lineof before beginning the
792868Speter  * output of a tree from a reduction.  First flush to the left margin
802868Speter  * of the production, and then set so that later calls to putcm, putcml
812868Speter  * and putcmp will deal with the right margin of this comment.
822868Speter  *
832868Speter  * The routine setinfo is called when the lineof has no embedded line
842868Speter  * number to avoid trashing the current "line".
852868Speter  *
862868Speter  * The routine setinfo is often called after completing the output of
872868Speter  * the text of a tree to restore Seqid, Col, and LSeqid which may have
882868Speter  * been destroyed by the nested processing calls to setline.
892868Speter  * In this case the only effect of the call to setinfo is to
902868Speter  * modify the above three variables as a side effect.
912868Speter  *
922868Speter  * We return a word giving information about the comments which were
932868Speter  * actually put out.  See putcm for details.
942868Speter  */
952868Speter setline(ip)
962868Speter 	int *ip;
972868Speter {
982868Speter 
992868Speter 	line = ip[0];
1002868Speter 	return(setinfo(ip));
1012868Speter }
1022868Speter 
1032868Speter setinfo(ip)
1042868Speter 	register int *ip;
1052868Speter {
1062868Speter 	register int i;
1072868Speter 
1082868Speter 	ip++;
1092868Speter 	Seqid = *ip++;
1102868Speter 	Col = *ip++;
1112868Speter 	i = putcm();
1122868Speter 	Seqid = *ip++;
1132868Speter 	Col = *ip++;
1142868Speter 	LSeqid = *ip++;
1152868Speter 	return (i);
1162868Speter }
1172868Speter 
1182868Speter char	cmeof, incomm;
1192868Speter 
1202868Speter /*
1212868Speter  * Get the text of a comment from the input stream,
1222868Speter  * recording its type and linking it into the linked
1232868Speter  * list of comments headed by cmhp.
1242868Speter  */
1252868Speter getcm(cmdelim)
1262868Speter 	char cmdelim;
1272868Speter {
1282868Speter 	int cmjust, col;
1292868Speter 	register struct comment *cp;
1302868Speter 	register struct commline *kp;
1312868Speter 
1322868Speter 	incomm = 1;
1332868Speter 	if (cmdelim == '*' && yycol == 10 || cmdelim == '{' && yycol == 9)
1342868Speter 		cmjust = CLMARG;
1352868Speter 	else if (yytokcnt <= 1)
1362868Speter 		cmjust = CALIGN;
1372868Speter 	else if (yywhcnt < 2)
1382868Speter 		cmjust = CTRAIL;
1392868Speter 	else
1402868Speter 		cmjust = CRMARG;
1412868Speter 	col = yycol - (cmdelim == '{' ? 1 : 2);
1422868Speter 	cp = tree5(NIL, cmdelim, NIL, cmjust, yyseqid);
1432868Speter 	cmeof = 0;
1442868Speter 	do {
1452868Speter 		kp = getcmline(cmdelim);
1462868Speter 		if (cp->cml == NIL) {
1472868Speter 			kp->cml = kp;
1482868Speter 			kp->cmcol = col;
1492868Speter 		} else {
1502868Speter 			kp->cml = cp->cml->cml;
1512868Speter 			cp->cml->cml = kp;
1522868Speter 			switch (cp->cmjust) {
1532868Speter 				case CTRAIL:
1542868Speter 				case CRMARG:
1552868Speter 					cp->cmjust = CALIGN;
1562868Speter 			}
1572868Speter 		}
1582868Speter 		cp->cml = kp;
1592868Speter 	} while (!cmeof);
1602868Speter 	newcomm(cp);
1612868Speter 	incomm = 0;
1622868Speter }
1632868Speter 
1642868Speter /*
1652868Speter  * Chain the new comment at "cp" onto the linked list of comments.
1662868Speter  */
1672868Speter newcomm(cp)
1682868Speter 	register struct comment *cp;
1692868Speter {
1702868Speter 
1712868Speter 	if (cmhp == NIL)
1722868Speter 		cp->cmnext = cp;
1732868Speter 	else {
1742868Speter 		cp->cmnext = cmhp->cmnext;
1752868Speter 		cmhp->cmnext = cp;
1762868Speter 	}
1772868Speter 	cmhp = cp;
1782868Speter }
1792868Speter 
1802868Speter 
1812868Speter int	nilcml[3];
1822868Speter 
1832868Speter quickcomm(t)
1842868Speter 	int t;
1852868Speter {
1862868Speter 
1872868Speter 	if (incomm)
1882868Speter 		return;
1892868Speter 	newcomm(tree5(nilcml, NIL, NIL, t, yyseqid));
1902868Speter }
1912868Speter 
1922868Speter commincl(cp, ch)
1932868Speter 	char *cp, ch;
1942868Speter {
1952868Speter 
1962868Speter 	newcomm(tree5(nilcml, savestr(cp), ch, CINCLUD, yyseqid));
1972868Speter }
1982868Speter 
1992868Speter getcmline(cmdelim)
2002868Speter 	char cmdelim;
2012868Speter {
2022868Speter 	char lastc;
2032868Speter 	register char *tp;
2042868Speter 	register CHAR c;
2052868Speter 	register struct commline *kp;
2062868Speter 
2072868Speter 	c = readch();
2082868Speter 	kp = tree3(NIL, yycol, NIL);
2092868Speter 	tp = token;
2102868Speter 	lastc = 0;
2112868Speter 	for (;;) {
2122868Speter 		switch (c) {
2132868Speter 			case '}':
2142868Speter 				if (cmdelim == '{')
2152868Speter 					goto endcm;
2162868Speter 				break;
2172868Speter 			case ')':
2182868Speter 				if (cmdelim == '*' && lastc == '*') {
2192868Speter 					--tp;
2202868Speter 					goto endcm;
2212868Speter 				}
2222868Speter 				break;
2232868Speter 			case '\n':
2242868Speter 				goto done;
2252868Speter 			case -1:
2262868Speter 				yerror("Comment does not terminate - QUIT");
2272868Speter 				pexit(ERRS);
2282868Speter 		}
2292868Speter 		lastc = c;
2302868Speter 		*tp++ = c;
2312868Speter 		c = readch();
2322868Speter 	}
2332868Speter endcm:
2342868Speter 	cmeof++;
2352868Speter done:
2362868Speter 	*tp = 0;
2372868Speter 	kp->cmtext = copystr(token);
2382868Speter 	return (kp);
2392868Speter }
2402868Speter 
2412868Speter /*
2422868Speter  * Flush through the line this token is on.
2432868Speter  * Ignore if next token on same line as this one.
2442868Speter  */
2452868Speter putcml()
2462868Speter {
2472868Speter 	register int i, SSeqid, SCol;
2482868Speter 
2492868Speter 	if (Seqid == LSeqid)
2502868Speter 		return (1);
2512868Speter 	SSeqid = Seqid, SCol = Col;
2522868Speter 	Seqid = LSeqid, Col = 32767;
2532868Speter 	i = putcm();
2542868Speter 	Seqid = SSeqid, Col = SCol;
2552868Speter 	return (i);
2562868Speter }
2572868Speter 
2582868Speter /*
2592868Speter  * Flush to the beginning of the line this token is on.
2602868Speter  * Ignore if this token is on the same line as the previous one
2612868Speter  * (effectively since all such already then flushed.)
2622868Speter  */
2632868Speter putcmp()
2642868Speter {
2652868Speter 	register int i, SSeqid, SCol;
2662868Speter 
2672868Speter 	SSeqid = Seqid, SCol = Col;
2682868Speter 	Seqid = LSeqid, Col = 0;
2692868Speter 	i = putcm();
2702868Speter 	Seqid = SSeqid, Col = SCol;
2712868Speter 	return (i);
2722868Speter }
2732868Speter 
2742868Speter /*
2752868Speter  * Put out the comments to the border indicated by Seqid and Col
2762868Speter  */
2772868Speter putcm()
2782868Speter {
2792868Speter 	register struct comment *cp;
2802868Speter 	register int i;
2812868Speter 
2822868Speter 	cp = cmhp;
2832868Speter 	if (cp == NIL)
2842868Speter 		return (0);
2852868Speter 	i = 0;
2862868Speter 	cp = cp->cmnext;
2872868Speter 	while (cp->cmseqid < Seqid || cp->cmseqid == Seqid && cp->cml->cmcol < Col) {
2882868Speter 		putone(cp);
289*30650Slepreau 		i |= 1 << cp->cmjust;
2902868Speter 		if (cp->cmnext == cp) {
2912868Speter 			cmhp = NIL;
2922868Speter 			break;
2932868Speter 		}
2942868Speter 		cp = cp->cmnext;
2952868Speter 		cmhp->cmnext = cp;
2962868Speter 	}
2972868Speter 	return (i);
2982868Speter }
2992868Speter 
3002868Speter /*
3012868Speter  * Put out one comment.
3022868Speter  * Note that empty lines, form feeds and #include statements
3032868Speter  * are treated as comments are regurgitated here.
3042868Speter  */
3052868Speter putone(cp)
3062868Speter 	register struct comment *cp;
3072868Speter {
3082868Speter 	register struct commline *cml, *cmf;
3092868Speter 
3102868Speter 	align(cp);
3112868Speter 	switch (cp->cmjust) {
3122868Speter 		case CINCLUD:
3132868Speter 		     /* ppflush() */
3142868Speter 			if (noinclude == 0) {
3152868Speter 				putchar('\f');
3162868Speter 				return;
3172868Speter 			}
3182868Speter 			printf("#include %c%s%c", cp->cml, cp->cmdelim, cp->cml);
3192868Speter 			return;
3202868Speter 	}
3212868Speter 	if (stripcomm)
3222868Speter 		return;
3232868Speter 	switch (cp->cmjust) {
3242868Speter 		case CFORM:
3252868Speter 			ppop("\f");
3262868Speter 			ppnl();
3272868Speter 		case CNL:
3282868Speter 		case CNLBL:
3292868Speter 			return;
3302868Speter 	}
3312868Speter 	ppbra(cp->cmdelim == '{' ? "{" : "(*");
3322868Speter 	cmf = cp->cml->cml;
3332868Speter 	ppid(cmf->cmtext);
3342868Speter 	for (cml = cmf->cml; cml != cmf; cml = cml->cml) {
3352868Speter 		align(cp);
3362868Speter 		oneline(cmf->cmcol, cml);
3372868Speter 	}
3382868Speter 	ppket(cp->cmdelim == '{' ? "}" : "*)");
3392868Speter }
3402868Speter 
3412868Speter /*
3422868Speter  * Do the preliminary horizontal and vertical
3432868Speter  * motions necessary before beginning a comment,
3442868Speter  * or between lines of a mult-line comment.
3452868Speter  */
3462868Speter align(cp)
3472868Speter 	register struct comment *cp;
3482868Speter {
3492868Speter 
3502868Speter 	switch (cp->cmjust) {
3512868Speter 		case CNL:
3522868Speter 			ppsnl();
3532868Speter 			break;
3542868Speter 		case CNLBL:
3552868Speter 			ppsnlb();
3562868Speter 			break;
3572868Speter 		case CFORM:
3582868Speter 		case CINCLUD:
3592868Speter 			ppnl();
3602868Speter 			break;
3612868Speter 		case CLMARG:
3622868Speter 			ppnl();
3632868Speter 			if (profile)
3642868Speter 				ppid("\t");
3652868Speter 			break;
3662868Speter 		case CALIGN:
3672868Speter 			ppnl();
3682868Speter 			indent();
3692868Speter 			break;
3702868Speter 		case CTRAIL:
3712868Speter 			ppspac();
3722868Speter 			break;
3732868Speter 		case CRMARG:
3742868Speter 		case CSRMARG:
3752868Speter 			pptab();
3762868Speter 			break;
3772868Speter 	}
3782868Speter }
3792868Speter 
3802868Speter /*
3812868Speter  * One line of a multi-line comment
3822868Speter  * Deal with alignment and initial white space trimming.
3832868Speter  * The "margin" indicates where the first line of the
3842868Speter  * comment began... don't print stuff in this comment
3852868Speter  * which came before this.
3862868Speter  */
3872868Speter oneline(margin, cml)
3882868Speter 	int margin;
3892868Speter 	struct commline *cml;
3902868Speter {
3912868Speter 	register char *tp;
3922868Speter 	register int i;
3932868Speter 
3942868Speter 	for (i = 8, tp = cml->cmtext; i < margin && *tp; tp++)
3952868Speter 		switch (*tp) {
3962868Speter 			case ' ':
3972868Speter 				i++;
3982868Speter 				continue;
3992868Speter 			case '\t':
400*30650Slepreau 				i += 8;
401*30650Slepreau 				i &= ~7;
4022868Speter 				if (i < margin)
4032868Speter 					continue;
4042868Speter 				ppop("\t");
4052868Speter 			default:
4062868Speter 				goto out;
4072868Speter 		}
4082868Speter out:
4092868Speter 	ppid(tp);
4102868Speter }
4112868Speter 
4122868Speter /*
4132868Speter  * Flush all comments
4142868Speter  */
4152868Speter flushcm()
4162868Speter {
4172868Speter 
4182868Speter 	Seqid = 32767;
4192868Speter 	return(putcm());
4202868Speter }
4212868Speter 
4222868Speter #define	BLANKS	((1 << CNL) | (1 << CNLBL) | (1 << CFORM))
4232868Speter noblank(i)
4242868Speter 	int i;
4252868Speter {
4262868Speter 
4272868Speter 	return ((i & BLANKS) == 0);
4282868Speter }
4292868Speter 
4302868Speter int	needform, neednlbl, neednl, needseqid;
4312868Speter 
4322868Speter needtree()
4332868Speter {
4342868Speter 	register struct comment *cp;
4352868Speter 
4362868Speter 	needform = neednlbl = neednl = 0;
4372868Speter 	cp = cmhp;
4382868Speter 	if (cp == NIL)
4392868Speter 		return (0);
4402868Speter 	do {
4412868Speter 		switch (cp->cmjust) {
4422868Speter 			case CNL:
4432868Speter 				neednl++;
4442868Speter 				goto seq;
4452868Speter 			case CNLBL:
4462868Speter 				neednlbl++;
4472868Speter 				goto seq;
4482868Speter 			case CFORM:
4492868Speter 				needform++;
4502868Speter seq:
4512868Speter 				needseqid = cp->cmseqid;
4522868Speter 				break;
4532868Speter 			default:
4542868Speter 				neednl = neednlbl = needform = 0;
4552868Speter 				return (1);
4562868Speter 		}
4572868Speter 		cp = cp->cmnext;
4582868Speter 	} while (cp != cmhp);
4592868Speter 	cmhp = NIL;
4602868Speter 	return (0);
4612868Speter }
4622868Speter 
4632868Speter packtree()
4642868Speter {
4652868Speter 	int save;
4662868Speter 
4672868Speter 	save = yyseqid;
4682868Speter 	yyseqid = needseqid;
4692868Speter 	for (; needform > 0; needform--)
4702868Speter 		commform();
4712868Speter 	for (; neednl > 0; neednl--)
4722868Speter 		commnl();
4732868Speter 	for (; neednlbl > 0; neednlbl--)
4742868Speter 		commnlbl();
4752868Speter 	yyseqid = save;
4762868Speter }
477