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