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