1: # 2: /* 3: * pi - Pascal interpreter code translator 4: * 5: * Charles Haley, Bill Joy UCB 6: * Version 1.2 January 1979 7: * 8: * 9: * pxp - Pascal execution profiler 10: * 11: * Bill Joy UCB 12: * Version 1.2 January 1979 13: */ 14: 15: #include "0.h" 16: #include "tree.h" 17: #include "yy.h" 18: 19: /* 20: * Structure describing queued listing lines during the forward move 21: * of error recovery. These lines will be stroed by yyoutline during 22: * the forward move and flushed by yyoutfl or yyflush when an 23: * error occurs or a program termination. 24: */ 25: struct B { 26: int Bmagic; 27: int Bline; 28: int Bseekp; 29: char *Bfile; 30: int Bseqid; 31: struct B *Bnext; 32: } *bottled; 33: 34: /* 35: * Filename gives the current input file, lastname is 36: * the last filename we printed, and lastid is the seqid of the last line 37: * we printed, to help us avoid printing 38: * multiple copies of lines. 39: */ 40: extern char *filename; 41: char *lastname; 42: int lastid; 43: 44: char hadsome; 45: char holdbl; 46: 47: /* 48: * Print the current line in the input line 49: * buffer or, in a forward move of the recovery, queue it for printing. 50: */ 51: yyoutline() 52: { 53: register struct B *bp; 54: 55: if (Recovery) { 56: bp = tree(6, T_BOTTLE, yyline, yylinpt, filename, yyseqid); 57: if (bottled != NIL) 58: bp->Bnext = bottled->Bnext, bottled->Bnext = bp; 59: else 60: bp->Bnext = bp; 61: bottled = bp; 62: return; 63: } 64: yyoutfl(yyseqid); 65: if (yyseqid != lastid) 66: yyprline(charbuf, yyline, filename, yyseqid); 67: } 68: 69: /* 70: * Flush all the bottled output. 71: */ 72: yyflush() 73: { 74: 75: yyoutfl(32767); 76: } 77: 78: /* 79: * Flush the listing to the sequence id toseqid 80: */ 81: yyoutfl(toseqid) 82: int toseqid; 83: { 84: register struct B *bp; 85: 86: bp = bottled; 87: if (bp == NIL) 88: return; 89: bp = bp->Bnext; 90: while (bp->Bseqid <= toseqid) { 91: yygetline(bp->Bfile, bp->Bseekp, bp->Bline, bp->Bseqid); 92: if (bp->Bnext == bp) { 93: bottled = NIL; 94: break; 95: } 96: bp = bp->Bnext; 97: bottled->Bnext = bp; 98: } 99: } 100: 101: int yygetunit -1; 102: char *yygetfile; 103: 104: /* 105: * Yysync guarantees that the line associated 106: * with the current token was the last line 107: * printed for a syntactic error message. 108: */ 109: yysync() 110: { 111: 112: yyoutfl(yyeseqid); 113: if (lastid != yyeseqid) 114: yygetline(yyefile, yyseekp, yyeline, yyeseqid); 115: } 116: 117: yySsync() 118: { 119: 120: yyoutfl(OY.Yyeseqid); 121: } 122: 123: /* 124: * Yygetline gets a line from a file after we have 125: * lost it. The pointer efile gives the name of the file, 126: * seekp its offset in the file, and eline its line number. 127: * If this routine has been called before the last file 128: * it worked on will be open in yygetunit, with the files 129: * name being given in yygetfile. Note that this unit must 130: * be opened independently of the unit in use for normal i/o 131: * to this file; if it were a dup seeks would seek both files. 132: */ 133: yygetline(efile, seekp, eline, eseqid) 134: char *efile; 135: int seekp, eline, eseqid; 136: { 137: register int cnt; 138: register char *bp; 139: char buf[CBSIZE + 1]; 140: 141: if (lastid == eseqid) 142: return; 143: if (eseqid == yyseqid) { 144: bp = charbuf; 145: yyprtd++; 146: } else { 147: bp = buf; 148: if (efile != yygetfile) { 149: close(yygetunit); 150: yygetfile = efile; 151: yygetunit = open(yygetfile, 0); 152: if (yygetunit < 0) 153: oops: 154: perror(yygetfile), pexit(DIED); 155: } 156: if (lseek(yygetunit, (long)seekp, 0) < 0) 157: goto oops; 158: cnt = read(yygetunit, bp, CBSIZE); 159: if (cnt < 0) 160: goto oops; 161: bp[cnt] = 0; 162: } 163: yyprline(bp, eline, efile, eseqid); 164: } 165: 166: yyretrieve() 167: { 168: 169: yygetline(OY.Yyefile, OY.Yyseekp, OY.Yyeline, OY.Yyeseqid); 170: } 171: 172: /* 173: * Print the line in the character buffer which has 174: * line number line. The buffer may be terminated by a new 175: * line character or a null character. We process 176: * form feed directives, lines with only a form feed character, and 177: * suppress numbering lines which are empty here. 178: */ 179: yyprline(buf, line, file, id) 180: register char *buf; 181: int line; 182: char *file; 183: int id; 184: { 185: 186: lastid = id; 187: if (buf[0] == '\f' && buf[1] == '\n') { 188: printf("\f\n"); 189: hadsome = 0; 190: holdbl = 0; 191: return; 192: } 193: if (holdbl) { 194: putchar('\n'); 195: holdbl = 0; 196: } 197: if (buf[0] == '\n') 198: holdbl = 1; 199: else { 200: yysetfile(file); 201: yyprintf(buf, line); 202: } 203: hadsome = 1; 204: } 205: 206: yyprintf(cp, line) 207: register char *cp; 208: int line; 209: { 210: 211: printf("%6d ", line); 212: while (*cp != 0 && *cp != '\n') 213: putchar(graphic(*cp++)); 214: putchar('\n'); 215: } 216: 217: graphic(ch) 218: register CHAR ch; 219: { 220: 221: switch (ch) { 222: default: 223: if (ch >= ' ') 224: return (ch); 225: case 0177: 226: return ('?'); 227: case '\n': 228: case '\t': 229: return (ch); 230: } 231: } 232: 233: extern int nopflg; 234: 235: char printed 1; 236: /* 237: * Set the current file name to be file, 238: * printing the name, or a header on a new 239: * page if required. 240: */ 241: yysetfile(file) 242: register char *file; 243: { 244: 245: #ifdef PXP 246: if (nopflg == 1) 247: return; 248: #endif 249: 250: if (lastname == file) 251: return; 252: if (file == filename && opt('n') && (printed & 02) == 0) { 253: printed =| 02; 254: header(); 255: } else 256: yyputfn(file); 257: lastname = file; 258: } 259: 260: /* 261: * Put out an include file name 262: * if an error occurs but the name has 263: * not been printed (or if another name 264: * has been printed since it has). 265: */ 266: yyputfn(cp) 267: register char *cp; 268: { 269: extern int outcol; 270: 271: if (cp == lastname && printed) 272: return; 273: lastname = cp; 274: printed = 1; 275: #ifdef PXP 276: if (outcol) 277: putchar('\n'); 278: #endif 279: printf("%s:\n", cp); 280: hadsome = 1; 281: }