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