xref: /illumos-gate/usr/src/cmd/tnf/prex/source.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1994, by Sun Microsytems, Inc.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Includes
30  */
31 
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <libintl.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 
42 #include "new.h"
43 #include "queue.h"
44 #include "source.h"
45 
46 
47 /*
48  * Typedefs
49  */
50 
51 typedef struct source {
52 	queue_node_t	qn;
53 	char		   *path;
54 	FILE		   *instream;
55 	int			 linenum;
56 	boolean_t	   isatty;
57 
58 }			   source_t;
59 
60 
61 /*
62  * Defines
63  */
64 
65 #define	HOME		"HOME"
66 #define	PREXRC		".prexrc"
67 
68 
69 /*
70  * Globals
71  */
72 
73 static queue_node_t stack;
74 static source_t *top;
75 
76 
77 /*
78  * source_init() - initializes the source stack
79  */
80 
81 void
source_init(void)82 source_init(void)
83 {
84 	source_t	   *new_p;
85 	struct stat	 statbuf;
86 	char		   *home;
87 	int			 retval;
88 
89 
90 	/* initialize the stack queue head */
91 	queue_init(&stack);
92 
93 	/* stick the standard input on the bottom of the stack */
94 	new_p = new(source_t);
95 	queue_init(&new_p->qn);
96 	new_p->path = strdup("<STDIN>");
97 	new_p->instream = stdin;
98 	new_p->linenum = 1;
99 	new_p->isatty = isatty(fileno(new_p->instream));
100 
101 	(void) queue_prepend(&stack, &new_p->qn);
102 	top = new_p;
103 
104 	/*
105 	 * since we are pushing onto a stack, we invert the search order *
106 	 * and push the prexrc in the current directory on next.
107 	 */
108 	retval = stat(PREXRC, &statbuf);
109 	if (retval != -1) {
110 		source_file(PREXRC);
111 	}
112 	home = getenv(HOME);
113 	if (home) {
114 		char			path[MAXPATHLEN];
115 
116 		if ((strlen(home) + strlen(PREXRC) + 2) < (size_t) MAXPATHLEN) {
117 			(void) sprintf(path, "%s/%s", home, PREXRC);
118 			retval = stat(path, &statbuf);
119 			if (retval != -1) {
120 				source_file(path);
121 			}
122 		}
123 	}
124 }				/* end source_init */
125 
126 
127 /*
128  * source_file() - pushes a new source onto the stack
129  */
130 
131 void
source_file(char * path)132 source_file(char *path)
133 {
134 	FILE		   *newfile;
135 	source_t	   *new_p;
136 
137 	newfile = fopen(path, "r");
138 	if (!newfile) {
139 		semantic_err(gettext("cannot open \"%s\""), path);
140 		return;
141 	}
142 	new_p = new(source_t);
143 	queue_init(&new_p->qn);
144 	new_p->path = strdup(path);
145 	new_p->instream = newfile;
146 	new_p->linenum = 1;
147 	new_p->isatty = isatty(fileno(new_p->instream));
148 
149 	(void) queue_prepend(&stack, &new_p->qn);
150 	top = new_p;
151 
152 }				/* end source_file */
153 
154 
155 /*
156  * source_input() - lexical analyzer input routine
157  */
158 
159 extern void	 quit(boolean_t, boolean_t);
160 
161 int
source_input(void)162 source_input(void)
163 {
164 	int			 c;
165 
166 	if (!top)
167 		return (0);
168 
169 	c = getc(top->instream);
170 
171 	if (c == EOF) {
172 		/*
173 		 * If we get an EOF at the top level, we quit if we are *
174 		 * non-interactive, pretend we saw a new-line if we are *
175 		 * interactive.
176 		 */
177 		if (top->instream == stdin) {
178 			if (top->isatty) {
179 				source_output('\n');
180 				return ('\n');
181 			} else
182 				quit(B_TRUE, B_TRUE);
183 		}
184 		/* we've exhausted the current stream, pop it, delete it ... */
185 		if (top->path)
186 			free(top->path);
187 		(void) fclose(top->instream);
188 		(void) queue_remove(&top->qn);
189 		free(top);
190 
191 		/* point to the new top level i/o stream */
192 		top = (source_t *) queue_next(&stack, &stack);
193 
194 		if (!top)
195 			return (0);
196 
197 		/* trigger a prompt if neccessary */
198 		prompt();
199 		return (source_input());
200 	}
201 	return (c);
202 
203 }				/* end source_input */
204 
205 
206 /*
207  * source_unput() - lexical analyzer unput routine
208  */
209 
210 void
source_unput(int c)211 source_unput(int c)
212 {
213 	if (top)
214 		(void) ungetc(c, top->instream);
215 
216 }				/* end source_unput */
217 
218 
219 /*
220  * source_output() - lexical analyzer output routine
221  */
222 
223 void
source_output(int c)224 source_output(int c)
225 {
226 	(void) putc(c, stdout);
227 
228 }				/* end source_output */
229 
230 
231 /*
232  * source_nl() - increment the line counter
233  */
234 
235 void
source_nl(void)236 source_nl(void)
237 {
238 	if (top)
239 		top->linenum++;
240 
241 }				/* end source_nl */
242 
243 
244 /*
245  * yyerror() -
246  */
247 
248 extern char	 yytext[];
249 extern int	  g_linenum;
250 
251 void
yyerror(char * s)252 yyerror(char *s)
253 {
254 	(void) fprintf(stderr,
255 		gettext("\"%s\", line %d: %s on or before \"%s\"\n"),
256 		top->path, top->linenum, s, yytext);
257 
258 }
259 
260 
261 /*
262  * yywrap() -
263  */
264 
265 int
yywrap()266 yywrap()
267 {
268 	return (1);
269 
270 }				/* end yywrap */
271 
272 
273 /*
274  * prompt() -
275  */
276 
277 extern char   **g_argv;
278 
279 void
prompt(void)280 prompt(void)
281 {
282 	if (top && top->isatty)
283 		(void) printf("%s> ", g_argv[0]);
284 
285 }				/* end g_prompt */
286 
287 
288 /*
289  * semantic_err() - reports a semantic error
290  */
291 
292 void
semantic_err(char * format,...)293 semantic_err(char *format, ...)
294 {
295 	va_list		 ap;
296 
297 	va_start(ap, format);
298 
299 	if (!top)
300 		return;
301 
302 	(void) fprintf(stderr, gettext("\"%s\", line %d: semantic error: "),
303 		top->path, top->linenum);
304 	(void) vfprintf(stderr, format, ap);
305 	(void) fprintf(stderr, gettext("\n"));
306 
307 }				/* end semantic_err */
308