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 */
yyoutline()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 */
yyflush()72 yyflush()
73 {
74
75 yyoutfl(32767);
76 }
77
78 /*
79 * Flush the listing to the sequence id toseqid
80 */
yyoutfl(toseqid)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 */
yysync()109 yysync()
110 {
111
112 yyoutfl(yyeseqid);
113 if (lastid != yyeseqid)
114 yygetline(yyefile, yyseekp, yyeline, yyeseqid);
115 }
116
yySsync()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 */
yygetline(efile,seekp,eline,eseqid)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
yyretrieve()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 */
yyprline(buf,line,file,id)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
yyprintf(cp,line)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
graphic(ch)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 */
yysetfile(file)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 */
yyputfn(cp)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