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