xref: /original-bsd/usr.bin/pascal/pxp/yyput.c (revision 50dd0bba)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)yyput.c	5.2 (Berkeley) 03/17/87";
9 #endif not lint
10 
11 /*
12  * pi - Pascal interpreter code translator
13  *
14  * Charles Haley, Bill Joy UCB
15  * Version 1.2 January 1979
16  *
17  *
18  * pxp - Pascal execution profiler
19  *
20  * Bill Joy UCB
21  * Version 1.2 January 1979
22  */
23 
24 #include "whoami.h"
25 #include "0.h"
26 #include "tree.h"
27 #include "yy.h"
28 
29 /*
30  * Structure describing queued listing lines during the forward move
31  * of error recovery.  These lines will be stroed by yyoutline during
32  * the forward move and flushed by yyoutfl or yyflush when an
33  * error occurs or a program termination.
34  */
35 struct	B {
36 	int	Bmagic;
37 	int	Bline;
38 	int	Bseekp;
39 	char	*Bfile;
40 	int	Bseqid;
41 	struct	B *Bnext;
42 } *bottled;
43 
44 /*
45  * Filename gives the current input file, lastname is
46  * the last filename we printed, and lastid is the seqid of the last line
47  * we printed, to help us avoid printing
48  * multiple copies of lines.
49  */
50 extern	char *filename;
51 char	*lastname;
52 int	lastid;
53 
54 char	hadsome;
55 char	holdbl;
56 
57 /*
58  * Print the current line in the input line
59  * buffer or, in a forward move of the recovery, queue it for printing.
60  */
61 yyoutline()
62 {
63 	register struct B *bp;
64 
65 	if (Recovery) {
66 		bp = tree(6, T_BOTTLE, yyline, yylinpt, filename, yyseqid);
67 		if (bottled != NIL)
68 			bp->Bnext = bottled->Bnext, bottled->Bnext = bp;
69 		else
70 			bp->Bnext = bp;
71 		bottled = bp;
72 		return;
73 	}
74 	yyoutfl(yyseqid);
75 	if (yyseqid != lastid)
76 		yyprline(charbuf, yyline, filename, yyseqid);
77 }
78 
79 /*
80  * Flush all the bottled output.
81  */
82 yyflush()
83 {
84 
85 	yyoutfl(32767);
86 }
87 
88 /*
89  * Flush the listing to the sequence id toseqid
90  */
91 yyoutfl(toseqid)
92 	int toseqid;
93 {
94 	register struct B *bp;
95 
96 	bp = bottled;
97 	if (bp == NIL)
98 		return;
99 	bp = bp->Bnext;
100 	while (bp->Bseqid <= toseqid) {
101 		yygetline(bp->Bfile, bp->Bseekp, bp->Bline, bp->Bseqid);
102 		if (bp->Bnext == bp) {
103 			bottled = NIL;
104 			break;
105 		}
106 		bp = bp->Bnext;
107 		bottled->Bnext = bp;
108 	}
109 }
110 
111 int	yygetunit = -1;
112 char	*yygetfile;
113 
114 /*
115  * Yysync guarantees that the line associated
116  * with the current token was the last line
117  * printed for a syntactic error message.
118  */
119 yysync()
120 {
121 
122 	yyoutfl(yyeseqid);
123 	if (lastid != yyeseqid)
124 		yygetline(yyefile, yyseekp, yyeline, yyeseqid);
125 }
126 
127 yySsync()
128 {
129 
130 	yyoutfl(OY.Yyeseqid);
131 }
132 
133 /*
134  * Yygetline gets a line from a file after we have
135  * lost it.  The pointer efile gives the name of the file,
136  * seekp its offset in the file, and eline its line number.
137  * If this routine has been called before the last file
138  * it worked on will be open in yygetunit, with the files
139  * name being given in yygetfile.  Note that this unit must
140  * be opened independently of the unit in use for normal i/o
141  * to this file; if it were a dup seeks would seek both files.
142  */
143 yygetline(efile, seekp, eline, eseqid)
144 	char *efile;
145 	int seekp, eline, eseqid;
146 {
147 	register int cnt;
148 	register char *bp;
149 	char buf[CBSIZE + 1];
150 
151 	if (lastid == eseqid)
152 		return;
153 	if (eseqid == yyseqid) {
154 		bp = charbuf;
155 		yyprtd++;
156 	} else {
157 		bp = buf;
158 		if (efile != yygetfile) {
159 			close(yygetunit);
160 			yygetfile = efile;
161 			yygetunit = open(yygetfile, 0);
162 			if (yygetunit < 0)
163 oops:
164 				perror(yygetfile), pexit(DIED);
165 		}
166 		if (lseek(yygetunit, (long)seekp, 0) < 0)
167 			goto oops;
168 		cnt = read(yygetunit, bp, CBSIZE);
169 		if (cnt < 0)
170 			goto oops;
171 		bp[cnt] = 0;
172 	}
173 	yyprline(bp, eline, efile, eseqid);
174 }
175 
176 yyretrieve()
177 {
178 
179 	yygetline(OY.Yyefile, OY.Yyseekp, OY.Yyeline, OY.Yyeseqid);
180 }
181 
182 /*
183  * Print the line in the character buffer which has
184  * line number line.  The buffer may be terminated by a new
185  * line character or a null character.  We process
186  * form feed directives, lines with only a form feed character, and
187  * suppress numbering lines which are empty here.
188  */
189 yyprline(buf, line, file, id)
190 	register char *buf;
191 	int line;
192 	char *file;
193 	int id;
194 {
195 
196 	lastid = id;
197 	if (buf[0] == '\f' && buf[1] == '\n') {
198 		printf("\f\n");
199 		hadsome = 0;
200 		holdbl = 0;
201 		return;
202 	}
203 	if (holdbl) {
204 		putchar('\n');
205 		holdbl = 0;
206 	}
207 	if (buf[0] == '\n')
208 		holdbl = 1;
209 	else {
210 		yysetfile(file);
211 		yyprintf(buf, line);
212 	}
213 	hadsome = 1;
214 }
215 
216 yyprintf(cp, line)
217 	register char *cp;
218 	int line;
219 {
220 
221 	printf("%6d  ", line);
222 	while (*cp != 0 && *cp != '\n')
223 		putchar(graphic(*cp++));
224 	putchar('\n');
225 }
226 
227 graphic(ch)
228 	register CHAR ch;
229 {
230 
231 	switch (ch) {
232 		default:
233 			if (ch >= ' ')
234 				return (ch);
235 		case 0177:
236 			return ('?');
237 		case '\n':
238 		case '\t':
239 			return (ch);
240 	}
241 }
242 
243 extern	int nopflg;
244 
245 char	printed = 1;
246 /*
247  * Set the current file name to be file,
248  * printing the name, or a header on a new
249  * page if required.
250  */
251 yysetfile(file)
252 	register char *file;
253 {
254 
255 #ifdef PXP
256 	if (nopflg == 1)
257 		return;
258 #endif
259 
260 	if (lastname == file)
261 		return;
262 	if (file == filename && opt('n') && (printed & 02) == 0) {
263 		printed |= 02;
264 		header();
265 	} else
266 		yyputfn(file);
267 	lastname = file;
268 }
269 
270 /*
271  * Put out an include file name
272  * if an error occurs but the name has
273  * not been printed (or if another name
274  * has been printed since it has).
275  */
276 yyputfn(cp)
277 	register char *cp;
278 {
279 	extern int outcol;
280 
281 	if (cp == lastname && printed)
282 		return;
283 	lastname = cp;
284 	printed = 1;
285 #ifdef PXP
286 	if (outcol)
287 		putchar('\n');
288 #endif
289 	printf("%s:\n", cp);
290 	hadsome = 1;
291 }
292