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