1*3055Smckusic static char *sccsid = "@(#)yyput.c 1.2 (Berkeley) 03/07/81"; 22871Speter /* Copyright (c) 1979 Regents of the University of California */ 32871Speter # 42871Speter /* 52871Speter * pi - Pascal interpreter code translator 62871Speter * 72871Speter * Charles Haley, Bill Joy UCB 82871Speter * Version 1.2 January 1979 92871Speter * 102871Speter * 112871Speter * pxp - Pascal execution profiler 122871Speter * 132871Speter * Bill Joy UCB 142871Speter * Version 1.2 January 1979 152871Speter */ 162871Speter 172871Speter #include "0.h" 182871Speter #include "tree.h" 192871Speter #include "yy.h" 202871Speter 212871Speter /* 222871Speter * Structure describing queued listing lines during the forward move 232871Speter * of error recovery. These lines will be stroed by yyoutline during 242871Speter * the forward move and flushed by yyoutfl or yyflush when an 252871Speter * error occurs or a program termination. 262871Speter */ 272871Speter struct B { 282871Speter int Bmagic; 292871Speter int Bline; 302871Speter int Bseekp; 312871Speter char *Bfile; 322871Speter int Bseqid; 332871Speter struct B *Bnext; 342871Speter } *bottled; 352871Speter 362871Speter /* 372871Speter * Filename gives the current input file, lastname is 382871Speter * the last filename we printed, and lastid is the seqid of the last line 392871Speter * we printed, to help us avoid printing 402871Speter * multiple copies of lines. 412871Speter */ 422871Speter extern char *filename; 432871Speter char *lastname; 442871Speter int lastid; 452871Speter 462871Speter char hadsome; 472871Speter char holdbl; 482871Speter 492871Speter /* 502871Speter * Print the current line in the input line 512871Speter * buffer or, in a forward move of the recovery, queue it for printing. 522871Speter */ 532871Speter yyoutline() 542871Speter { 552871Speter register struct B *bp; 562871Speter 572871Speter if (Recovery) { 582871Speter bp = tree(6, T_BOTTLE, yyline, yylinpt, filename, yyseqid); 592871Speter if (bottled != NIL) 602871Speter bp->Bnext = bottled->Bnext, bottled->Bnext = bp; 612871Speter else 622871Speter bp->Bnext = bp; 632871Speter bottled = bp; 642871Speter return; 652871Speter } 662871Speter yyoutfl(yyseqid); 672871Speter if (yyseqid != lastid) 682871Speter yyprline(charbuf, yyline, filename, yyseqid); 692871Speter } 702871Speter 712871Speter /* 722871Speter * Flush all the bottled output. 732871Speter */ 742871Speter yyflush() 752871Speter { 762871Speter 772871Speter yyoutfl(32767); 782871Speter } 792871Speter 802871Speter /* 812871Speter * Flush the listing to the sequence id toseqid 822871Speter */ 832871Speter yyoutfl(toseqid) 842871Speter int toseqid; 852871Speter { 862871Speter register struct B *bp; 872871Speter 882871Speter bp = bottled; 892871Speter if (bp == NIL) 902871Speter return; 912871Speter bp = bp->Bnext; 922871Speter while (bp->Bseqid <= toseqid) { 932871Speter yygetline(bp->Bfile, bp->Bseekp, bp->Bline, bp->Bseqid); 942871Speter if (bp->Bnext == bp) { 952871Speter bottled = NIL; 962871Speter break; 972871Speter } 982871Speter bp = bp->Bnext; 992871Speter bottled->Bnext = bp; 1002871Speter } 1012871Speter } 1022871Speter 103*3055Smckusic int yygetunit = -1; 1042871Speter char *yygetfile; 1052871Speter 1062871Speter /* 1072871Speter * Yysync guarantees that the line associated 1082871Speter * with the current token was the last line 1092871Speter * printed for a syntactic error message. 1102871Speter */ 1112871Speter yysync() 1122871Speter { 1132871Speter 1142871Speter yyoutfl(yyeseqid); 1152871Speter if (lastid != yyeseqid) 1162871Speter yygetline(yyefile, yyseekp, yyeline, yyeseqid); 1172871Speter } 1182871Speter 1192871Speter yySsync() 1202871Speter { 1212871Speter 1222871Speter yyoutfl(OY.Yyeseqid); 1232871Speter } 1242871Speter 1252871Speter /* 1262871Speter * Yygetline gets a line from a file after we have 1272871Speter * lost it. The pointer efile gives the name of the file, 1282871Speter * seekp its offset in the file, and eline its line number. 1292871Speter * If this routine has been called before the last file 1302871Speter * it worked on will be open in yygetunit, with the files 1312871Speter * name being given in yygetfile. Note that this unit must 1322871Speter * be opened independently of the unit in use for normal i/o 1332871Speter * to this file; if it were a dup seeks would seek both files. 1342871Speter */ 1352871Speter yygetline(efile, seekp, eline, eseqid) 1362871Speter char *efile; 1372871Speter int seekp, eline, eseqid; 1382871Speter { 1392871Speter register int cnt; 1402871Speter register char *bp; 1412871Speter char buf[CBSIZE + 1]; 1422871Speter 1432871Speter if (lastid == eseqid) 1442871Speter return; 1452871Speter if (eseqid == yyseqid) { 1462871Speter bp = charbuf; 1472871Speter yyprtd++; 1482871Speter } else { 1492871Speter bp = buf; 1502871Speter if (efile != yygetfile) { 1512871Speter close(yygetunit); 1522871Speter yygetfile = efile; 1532871Speter yygetunit = open(yygetfile, 0); 1542871Speter if (yygetunit < 0) 1552871Speter oops: 1562871Speter perror(yygetfile), pexit(DIED); 1572871Speter } 1582871Speter if (lseek(yygetunit, (long)seekp, 0) < 0) 1592871Speter goto oops; 1602871Speter cnt = read(yygetunit, bp, CBSIZE); 1612871Speter if (cnt < 0) 1622871Speter goto oops; 1632871Speter bp[cnt] = 0; 1642871Speter } 1652871Speter yyprline(bp, eline, efile, eseqid); 1662871Speter } 1672871Speter 1682871Speter yyretrieve() 1692871Speter { 1702871Speter 1712871Speter yygetline(OY.Yyefile, OY.Yyseekp, OY.Yyeline, OY.Yyeseqid); 1722871Speter } 1732871Speter 1742871Speter /* 1752871Speter * Print the line in the character buffer which has 1762871Speter * line number line. The buffer may be terminated by a new 1772871Speter * line character or a null character. We process 1782871Speter * form feed directives, lines with only a form feed character, and 1792871Speter * suppress numbering lines which are empty here. 1802871Speter */ 1812871Speter yyprline(buf, line, file, id) 1822871Speter register char *buf; 1832871Speter int line; 1842871Speter char *file; 1852871Speter int id; 1862871Speter { 1872871Speter 1882871Speter lastid = id; 1892871Speter if (buf[0] == '\f' && buf[1] == '\n') { 1902871Speter printf("\f\n"); 1912871Speter hadsome = 0; 1922871Speter holdbl = 0; 1932871Speter return; 1942871Speter } 1952871Speter if (holdbl) { 1962871Speter putchar('\n'); 1972871Speter holdbl = 0; 1982871Speter } 1992871Speter if (buf[0] == '\n') 2002871Speter holdbl = 1; 2012871Speter else { 2022871Speter yysetfile(file); 2032871Speter yyprintf(buf, line); 2042871Speter } 2052871Speter hadsome = 1; 2062871Speter } 2072871Speter 2082871Speter yyprintf(cp, line) 2092871Speter register char *cp; 2102871Speter int line; 2112871Speter { 2122871Speter 2132871Speter printf("%6d ", line); 2142871Speter while (*cp != 0 && *cp != '\n') 2152871Speter putchar(graphic(*cp++)); 2162871Speter putchar('\n'); 2172871Speter } 2182871Speter 2192871Speter graphic(ch) 2202871Speter register CHAR ch; 2212871Speter { 2222871Speter 2232871Speter switch (ch) { 2242871Speter default: 2252871Speter if (ch >= ' ') 2262871Speter return (ch); 2272871Speter case 0177: 2282871Speter return ('?'); 2292871Speter case '\n': 2302871Speter case '\t': 2312871Speter return (ch); 2322871Speter } 2332871Speter } 2342871Speter 2352871Speter extern int nopflg; 2362871Speter 237*3055Smckusic char printed = 1; 2382871Speter /* 2392871Speter * Set the current file name to be file, 2402871Speter * printing the name, or a header on a new 2412871Speter * page if required. 2422871Speter */ 2432871Speter yysetfile(file) 2442871Speter register char *file; 2452871Speter { 2462871Speter 2472871Speter #ifdef PXP 2482871Speter if (nopflg == 1) 2492871Speter return; 2502871Speter #endif 2512871Speter 2522871Speter if (lastname == file) 2532871Speter return; 2542871Speter if (file == filename && opt('n') && (printed & 02) == 0) { 2552871Speter printed =| 02; 2562871Speter header(); 2572871Speter } else 2582871Speter yyputfn(file); 2592871Speter lastname = file; 2602871Speter } 2612871Speter 2622871Speter /* 2632871Speter * Put out an include file name 2642871Speter * if an error occurs but the name has 2652871Speter * not been printed (or if another name 2662871Speter * has been printed since it has). 2672871Speter */ 2682871Speter yyputfn(cp) 2692871Speter register char *cp; 2702871Speter { 2712871Speter extern int outcol; 2722871Speter 2732871Speter if (cp == lastname && printed) 2742871Speter return; 2752871Speter lastname = cp; 2762871Speter printed = 1; 2772871Speter #ifdef PXP 2782871Speter if (outcol) 2792871Speter putchar('\n'); 2802871Speter #endif 2812871Speter printf("%s:\n", cp); 2822871Speter hadsome = 1; 2832871Speter } 284