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