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