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