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