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