xref: /original-bsd/usr.bin/pascal/pxp/yyput.c (revision c3e32dec)
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  */
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  */
83 yyflush()
84 {
85 
86 	yyoutfl(32767);
87 }
88 
89 /*
90  * Flush the listing to the sequence id toseqid
91  */
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  */
120 yysync()
121 {
122 
123 	yyoutfl(yyeseqid);
124 	if (lastid != yyeseqid)
125 		yygetline(yyefile, yyseekp, yyeline, yyeseqid);
126 }
127 
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  */
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 
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  */
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 
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 
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  */
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  */
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