xref: /original-bsd/usr.bin/pascal/src/yyput.c (revision 431be598)
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  */
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  */
72 yyflush()
73 {
74 
75 	yyoutfl(32767);
76 }
77 
78 /*
79  * Flush the listing to the sequence id toseqid
80  */
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  */
109 yysync()
110 {
111 
112 	yyoutfl(yyeseqid);
113 	if (lastid != yyeseqid)
114 		yygetline(yyefile, yyseekp, yyeline, yyeseqid);
115 }
116 
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  */
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 
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  */
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 
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 
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  */
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  */
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