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