148116Sbostic /*-
2*62227Sbostic * Copyright (c) 1980, 1993
3*62227Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622213Sdist */
7793Speter
814748Sthien #ifndef lint
9*62227Sbostic static char sccsid[] = "@(#)yyput.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11793Speter
12793Speter #include "whoami.h"
13793Speter #include "0.h"
14793Speter #include "tree.h"
1514748Sthien #include "tree_ty.h" /* must be included for yy.h */
16793Speter #include "yy.h"
17793Speter
18793Speter /*
19793Speter * Structure describing queued listing lines during the forward move
20793Speter * of error recovery. These lines will be stroed by yyoutline during
21793Speter * the forward move and flushed by yyoutfl or yyflush when an
22793Speter * error occurs or a program termination.
23793Speter */
24793Speter struct B {
25793Speter int Bmagic;
26793Speter int Bline;
27793Speter int Bseekp;
28793Speter char *Bfile;
29793Speter int Bseqid;
30793Speter struct B *Bnext;
31793Speter } *bottled;
32793Speter
33793Speter /*
34793Speter * Filename gives the current input file, lastname is
35793Speter * the last filename we printed, and lastid is the seqid of the last line
36793Speter * we printed, to help us avoid printing
37793Speter * multiple copies of lines.
38793Speter */
39793Speter extern char *filename;
40793Speter char *lastname;
41793Speter int lastid;
42793Speter
43793Speter char hadsome;
44793Speter char holdbl;
45793Speter
46793Speter /*
47793Speter * Print the current line in the input line
48793Speter * buffer or, in a forward move of the recovery, queue it for printing.
49793Speter */
yyoutline()50793Speter yyoutline()
51793Speter {
52793Speter register struct B *bp;
53793Speter
54793Speter if (Recovery) {
5514748Sthien bp = (struct B *) tree(6, T_BOTTLE, yyline, yylinpt, filename,
5614748Sthien yyseqid);
57793Speter if (bottled != NIL)
58793Speter bp->Bnext = bottled->Bnext, bottled->Bnext = bp;
59793Speter else
60793Speter bp->Bnext = bp;
61793Speter bottled = bp;
62793Speter return;
63793Speter }
64793Speter yyoutfl(yyseqid);
65793Speter if (yyseqid != lastid)
66793Speter yyprline(charbuf, yyline, filename, yyseqid);
67793Speter }
68793Speter
69793Speter /*
70793Speter * Flush all the bottled output.
71793Speter */
yyflush()72793Speter yyflush()
73793Speter {
74793Speter
75793Speter yyoutfl(32767);
76793Speter }
77793Speter
78793Speter /*
79793Speter * Flush the listing to the sequence id toseqid
80793Speter */
yyoutfl(toseqid)81793Speter yyoutfl(toseqid)
82793Speter int toseqid;
83793Speter {
84793Speter register struct B *bp;
85793Speter
86793Speter bp = bottled;
87793Speter if (bp == NIL)
88793Speter return;
89793Speter bp = bp->Bnext;
90793Speter while (bp->Bseqid <= toseqid) {
91793Speter yygetline(bp->Bfile, bp->Bseekp, bp->Bline, bp->Bseqid);
92793Speter if (bp->Bnext == bp) {
93793Speter bottled = NIL;
94793Speter break;
95793Speter }
96793Speter bp = bp->Bnext;
97793Speter bottled->Bnext = bp;
98793Speter }
99793Speter }
100793Speter
101793Speter FILE *yygetunit = NULL;
102793Speter char *yygetfile;
103793Speter
104793Speter /*
105793Speter * Yysync guarantees that the line associated
106793Speter * with the current token was the last line
107793Speter * printed for a syntactic error message.
108793Speter */
yysync()109793Speter yysync()
110793Speter {
111793Speter
112793Speter yyoutfl(yyeseqid);
113793Speter if (lastid != yyeseqid)
114793Speter yygetline(yyefile, yyseekp, yyeline, yyeseqid);
115793Speter }
116793Speter
yySsync()117793Speter yySsync()
118793Speter {
119793Speter
120793Speter yyoutfl(OY.Yyeseqid);
121793Speter }
122793Speter
123793Speter /*
124793Speter * Yygetline gets a line from a file after we have
125793Speter * lost it. The pointer efile gives the name of the file,
126793Speter * seekp its offset in the file, and eline its line number.
127793Speter * If this routine has been called before the last file
128793Speter * it worked on will be open in yygetunit, with the files
129793Speter * name being given in yygetfile. Note that this unit must
130793Speter * be opened independently of the unit in use for normal i/o
131793Speter * to this file; if it were a dup seeks would seek both files.
132793Speter */
yygetline(efile,seekp,eline,eseqid)133793Speter yygetline(efile, seekp, eline, eseqid)
134793Speter char *efile;
135793Speter int seekp, eline, eseqid;
136793Speter {
137793Speter register int cnt;
138793Speter register char *bp;
139793Speter char buf[CBSIZE + 1];
140793Speter
141793Speter if (lastid == eseqid)
142793Speter return;
143793Speter if (eseqid == yyseqid) {
144793Speter bp = charbuf;
145793Speter yyprtd++;
146793Speter } else {
147793Speter bp = buf;
148793Speter if (efile != yygetfile) {
149793Speter if ( yygetunit != NULL )
15014748Sthien (void) fclose( yygetunit );
151793Speter yygetfile = efile;
152793Speter yygetunit = fopen( yygetfile , "r" );
15335694Sbostic if (yygetunit == 0)
154793Speter oops:
155793Speter perror(yygetfile), pexit(DIED);
156793Speter }
157793Speter if ( fseek( yygetunit , (long) seekp , 0 ) < 0)
158793Speter goto oops;
159793Speter cnt = fread( bp , sizeof( * bp ) , CBSIZE , yygetunit );
160793Speter if (cnt < 0)
161793Speter goto oops;
162793Speter bp[cnt] = 0;
163793Speter }
164793Speter yyprline(bp, eline, efile, eseqid);
165793Speter }
166793Speter
yyretrieve()167793Speter yyretrieve()
168793Speter {
169793Speter
170793Speter yygetline(OY.Yyefile, OY.Yyseekp, OY.Yyeline, OY.Yyeseqid);
171793Speter }
172793Speter
173793Speter /*
174793Speter * Print the line in the character buffer which has
175793Speter * line number line. The buffer may be terminated by a new
176793Speter * line character or a null character. We process
177793Speter * form feed directives, lines with only a form feed character, and
178793Speter * suppress numbering lines which are empty here.
179793Speter */
yyprline(buf,line,file,id)180793Speter yyprline(buf, line, file, id)
181793Speter register char *buf;
182793Speter int line;
183793Speter char *file;
184793Speter int id;
185793Speter {
186793Speter
187793Speter lastid = id;
188793Speter if (buf[0] == '\f' && buf[1] == '\n') {
189793Speter printf("\f\n");
190793Speter hadsome = 0;
191793Speter holdbl = 0;
192793Speter return;
193793Speter }
194793Speter if (holdbl) {
195793Speter pchr('\n');
196793Speter holdbl = 0;
197793Speter }
198793Speter if (buf[0] == '\n')
199793Speter holdbl = 1;
200793Speter else {
201793Speter yysetfile(file);
202793Speter yyprintf(buf, line);
203793Speter }
204793Speter hadsome = 1;
205793Speter }
206793Speter
yyprintf(cp,line)207793Speter yyprintf(cp, line)
208793Speter register char *cp;
209793Speter int line;
210793Speter {
211793Speter
212793Speter printf("%6d ", line);
213793Speter while (*cp != 0 && *cp != '\n')
214793Speter pchr(graphic(*cp++));
215793Speter pchr('\n');
216793Speter }
217793Speter
graphic(ch)218793Speter graphic(ch)
219793Speter register CHAR ch;
220793Speter {
221793Speter
222793Speter switch (ch) {
223793Speter default:
224793Speter if (ch >= ' ')
225793Speter return (ch);
226793Speter case 0177:
227793Speter return ('?');
228793Speter case '\n':
229793Speter case '\t':
230793Speter return (ch);
231793Speter }
232793Speter }
233793Speter
234793Speter extern int nopflg;
235793Speter
2363087Smckusic char printed = 1;
237793Speter /*
238793Speter * Set the current file name to be file,
239793Speter * printing the name, or a header on a new
240793Speter * page if required.
241793Speter * there is another yysetfile in error.c
242793Speter * this one is for PI and PXP that one is for PI1
243793Speter */
yysetfile(file)244793Speter yysetfile(file)
245793Speter register char *file;
246793Speter {
247793Speter
248793Speter #ifdef PXP
249793Speter if (nopflg == 1)
250793Speter return;
251793Speter #endif
252793Speter
253793Speter if (lastname == file)
254793Speter return;
255793Speter if (file == filename && opt('n') && (printed & 02) == 0) {
2563087Smckusic printed |= 02;
257793Speter header();
258793Speter } else
259793Speter yyputfn(file);
260793Speter lastname = file;
261793Speter }
262793Speter
263793Speter /*
264793Speter * Put out an include file name
265793Speter * if an error occurs but the name has
266793Speter * not been printed (or if another name
267793Speter * has been printed since it has).
268793Speter */
yyputfn(cp)269793Speter yyputfn(cp)
270793Speter register char *cp;
271793Speter {
272793Speter extern int outcol;
273793Speter
274793Speter if (cp == lastname && printed)
275793Speter return;
276793Speter lastname = cp;
277793Speter printed = 1;
278793Speter #ifdef PXP
279793Speter if (outcol)
280793Speter pchr('\n');
281793Speter #endif
282793Speter gettime( cp );
28314748Sthien printf("%s %s:\n" , myctime( (int *) (&tvec) ) , cp );
284793Speter hadsome = 1;
285793Speter }
286