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