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