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