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