BSD 3 development
[unix-history] / usr / src / cmd / pxp / yyput.c
CommitLineData
eb8dd88e
BJ
1/* Copyright (c) 1979 Regents of the University of California */
2#
3/*
4 * pi - Pascal interpreter code translator
5 *
6 * Charles Haley, Bill Joy UCB
7 * Version 1.2 January 1979
8 *
9 *
10 * pxp - Pascal execution profiler
11 *
12 * Bill Joy UCB
13 * Version 1.2 January 1979
14 */
15
16#include "0.h"
17#include "tree.h"
18#include "yy.h"
19
20/*
21 * Structure describing queued listing lines during the forward move
22 * of error recovery. These lines will be stroed by yyoutline during
23 * the forward move and flushed by yyoutfl or yyflush when an
24 * error occurs or a program termination.
25 */
26struct B {
27 int Bmagic;
28 int Bline;
29 int Bseekp;
30 char *Bfile;
31 int Bseqid;
32 struct B *Bnext;
33} *bottled;
34
35/*
36 * Filename gives the current input file, lastname is
37 * the last filename we printed, and lastid is the seqid of the last line
38 * we printed, to help us avoid printing
39 * multiple copies of lines.
40 */
41extern char *filename;
42char *lastname;
43int lastid;
44
45char hadsome;
46char holdbl;
47\f
48/*
49 * Print the current line in the input line
50 * buffer or, in a forward move of the recovery, queue it for printing.
51 */
52yyoutline()
53{
54 register struct B *bp;
55
56 if (Recovery) {
57 bp = tree(6, T_BOTTLE, yyline, yylinpt, filename, yyseqid);
58 if (bottled != NIL)
59 bp->Bnext = bottled->Bnext, bottled->Bnext = bp;
60 else
61 bp->Bnext = bp;
62 bottled = bp;
63 return;
64 }
65 yyoutfl(yyseqid);
66 if (yyseqid != lastid)
67 yyprline(charbuf, yyline, filename, yyseqid);
68}
69
70/*
71 * Flush all the bottled output.
72 */
73yyflush()
74{
75
76 yyoutfl(32767);
77}
78
79/*
80 * Flush the listing to the sequence id toseqid
81 */
82yyoutfl(toseqid)
83 int toseqid;
84{
85 register struct B *bp;
86
87 bp = bottled;
88 if (bp == NIL)
89 return;
90 bp = bp->Bnext;
91 while (bp->Bseqid <= toseqid) {
92 yygetline(bp->Bfile, bp->Bseekp, bp->Bline, bp->Bseqid);
93 if (bp->Bnext == bp) {
94 bottled = NIL;
95 break;
96 }
97 bp = bp->Bnext;
98 bottled->Bnext = bp;
99 }
100}
101\f
102int yygetunit -1;
103char *yygetfile;
104
105/*
106 * Yysync guarantees that the line associated
107 * with the current token was the last line
108 * printed for a syntactic error message.
109 */
110yysync()
111{
112
113 yyoutfl(yyeseqid);
114 if (lastid != yyeseqid)
115 yygetline(yyefile, yyseekp, yyeline, yyeseqid);
116}
117
118yySsync()
119{
120
121 yyoutfl(OY.Yyeseqid);
122}
123
124/*
125 * Yygetline gets a line from a file after we have
126 * lost it. The pointer efile gives the name of the file,
127 * seekp its offset in the file, and eline its line number.
128 * If this routine has been called before the last file
129 * it worked on will be open in yygetunit, with the files
130 * name being given in yygetfile. Note that this unit must
131 * be opened independently of the unit in use for normal i/o
132 * to this file; if it were a dup seeks would seek both files.
133 */
134yygetline(efile, seekp, eline, eseqid)
135 char *efile;
136 int seekp, eline, eseqid;
137{
138 register int cnt;
139 register char *bp;
140 char buf[CBSIZE + 1];
141
142 if (lastid == eseqid)
143 return;
144 if (eseqid == yyseqid) {
145 bp = charbuf;
146 yyprtd++;
147 } else {
148 bp = buf;
149 if (efile != yygetfile) {
150 close(yygetunit);
151 yygetfile = efile;
152 yygetunit = open(yygetfile, 0);
153 if (yygetunit < 0)
154oops:
155 perror(yygetfile), pexit(DIED);
156 }
157 if (lseek(yygetunit, (long)seekp, 0) < 0)
158 goto oops;
159 cnt = read(yygetunit, bp, CBSIZE);
160 if (cnt < 0)
161 goto oops;
162 bp[cnt] = 0;
163 }
164 yyprline(bp, eline, efile, eseqid);
165}
166
167yyretrieve()
168{
169
170 yygetline(OY.Yyefile, OY.Yyseekp, OY.Yyeline, OY.Yyeseqid);
171}
172\f
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 */
180yyprline(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 putchar('\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
207yyprintf(cp, line)
208 register char *cp;
209 int line;
210{
211
212 printf("%6d ", line);
213 while (*cp != 0 && *cp != '\n')
214 putchar(graphic(*cp++));
215 putchar('\n');
216}
217
218graphic(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\f
234extern int nopflg;
235
236char 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 */
242yysetfile(file)
243 register char *file;
244{
245
246#ifdef PXP
247 if (nopflg == 1)
248 return;
249#endif
250
251 if (lastname == file)
252 return;
253 if (file == filename && opt('n') && (printed & 02) == 0) {
254 printed =| 02;
255 header();
256 } else
257 yyputfn(file);
258 lastname = file;
259}
260
261/*
262 * Put out an include file name
263 * if an error occurs but the name has
264 * not been printed (or if another name
265 * has been printed since it has).
266 */
267yyputfn(cp)
268 register char *cp;
269{
270 extern int outcol;
271
272 if (cp == lastname && printed)
273 return;
274 lastname = cp;
275 printed = 1;
276#ifdef PXP
277 if (outcol)
278 putchar('\n');
279#endif
280 printf("%s:\n", cp);
281 hadsome = 1;
282}