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.1 (Berkeley) 6/5/85"; 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: }