xref: /netbsd/usr.sbin/gspa/gspa/gspa.c (revision bf9ec67e)
1 /*	$NetBSD: gspa.c,v 1.9 2002/05/27 21:11:41 wiz Exp $	*/
2 /*
3  * GSP assembler main program
4  *
5  * Copyright (c) 1993 Paul Mackerras.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Paul Mackerras.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 #ifndef lint
36 __RCSID("$NetBSD: gspa.c,v 1.9 2002/05/27 21:11:41 wiz Exp $");
37 #endif
38 
39 #include <sys/param.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <setjmp.h>
43 #include <stdarg.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 
49 #include "gsp_ass.h"
50 #include "gsp_gram.h"
51 
52 #define YYDEBUG_VALUE	0
53 
54 extern YYSTYPE yylval;
55 int err_count;
56 
57 char line[MAXLINE];
58 int lineno;
59 
60 extern int yydebug;
61 short pass2;
62 
63 unsigned pc;
64 unsigned highest_pc;
65 unsigned line_pc;
66 
67 FILE *infile;
68 FILE *current_infile;
69 FILE *objfile;
70 FILE *listfile;
71 
72 char *c_name;
73 char in_name[PATH_MAX + 1];
74 
75 struct input {
76 	FILE	*fp;
77 	struct input *next;
78 	int	lineno;
79 	char	name[128];
80 } *pending_input;
81 
82 jmp_buf synerrjmp;
83 
84 void	setext(char *, const char *, const char *);
85 void	usage(void);
86 int	yyparse(void);
87 
88 void	c_dumpbuf(void);
89 
90 int
91 main(int argc, char **argv)
92 {
93 	char *hex_name, *list_name;
94 	int c;
95 
96 #if __GNUC__		/* XXX: borken compilers... */
97 	(void)&hex_name;
98 	(void)&list_name;
99 #endif
100 
101 	hex_name = list_name = 0;
102 
103 	/* parse options */
104 	while ((c = getopt(argc, argv, "o:l:c:")) != -1) {
105 		switch (c) {
106 		case 'o':
107 			if (hex_name)
108 				usage();
109 			hex_name = optarg;
110 			break;
111 		case 'c':
112 			if (c_name)
113 				usage();
114 			c_name = optarg;
115 			break;
116 		case 'l':
117 			if (list_name)
118 				usage();
119 			list_name = optarg;
120 			break;
121 		default:
122 			usage();
123 		}
124 	}
125 
126 	/* get source file */
127 	argc -= optind;
128 	argv += optind;
129 	if (argc == 0) {
130 		infile = stdin;
131 		strcpy(in_name, "<stdin>");
132 	} else if (argc == 1) {
133 		strncpy(in_name, *argv, PATH_MAX);
134 		in_name[PATH_MAX] = 0;
135 		if ((infile = fopen(in_name, "r")) == NULL)
136 			err(1, "fopen");
137 	} else
138 		usage();
139 
140 	/* Pass 1 */
141 	pending_input = NULL;
142 	current_infile = infile;
143 
144 	yydebug = YYDEBUG_VALUE;
145 	pass2 = 0;
146 	pc = 0;
147 	lineno = 0;
148 	while( get_line(line, MAXLINE) ){
149 		if( !setjmp(synerrjmp) ){
150 			lex_init(line);
151 			yyparse();
152 		}
153 	}
154 	if( err_count > 0 )
155 		exit(1);
156 
157 	/* Open output files */
158 	if (hex_name == 0)
159 		objfile = stdout;
160 	else if ((objfile = fopen(hex_name, "w")) == NULL)
161 		err(1, "fopen");
162 	if (c_name) {
163 		fprintf(objfile, "/*\n"
164 		    " * This file was automatically created from\n"
165 		    " * a TMS34010 assembler output file.\n"
166 		    " * Do not edit manually.\n"
167 		    " */\n"
168 		    "#include <sys/types.h>\n"
169 		    "u_int16_t %s[] = {\n\t", c_name);
170 	}
171 	if (list_name)
172 		if ((listfile = fopen(list_name, "w")) == NULL)
173 			err(1, "fopen");
174 
175 	/* Pass 2 */
176 	pass2 = 1;
177 	rewind(infile);
178 	current_infile = infile;
179 	pc = 0;
180 	lineno = 0;
181 	reset_numeric_labels();
182 	while( get_line(line, MAXLINE) ){
183 		line_pc = pc;
184 		if( !setjmp(synerrjmp) ){
185 			lex_init(line);
186 			yyparse();
187 		}
188 		listing();
189 	}
190 
191 	if (c_name) {
192 		c_dumpbuf();
193 		fprintf(objfile, "\n\t0\n};\n");
194 	}
195 
196 	exit(err_count != 0);
197 }
198 
199 void
200 setext(char *out, const char *in, const char *ext)
201 {
202 	const char *p;
203 
204 	p = strrchr(in, '.');
205 	if( p != NULL ){
206 		memcpy(out, in, p - in);
207 		strcpy(out + (p - in), ext);
208 	} else {
209 		strcpy(out, in);
210 		strcat(out, ext);
211 	}
212 }
213 
214 void
215 push_input(char *fn)
216 {
217 	FILE *f;
218 	struct input *p;
219 
220 	f = fopen(fn, "r");
221 	if( f == NULL ){
222 		p1err("Can't open input file %s", fn);
223 		return;
224 	}
225 	new(p);
226 	p->fp = current_infile;
227 	p->lineno = lineno;
228 	strcpy(p->name, in_name);
229 	p->next = pending_input;
230 	current_infile = f;
231 	lineno = 1;
232 	strcpy(in_name, fn);
233 	pending_input = p;
234 }
235 
236 int
237 get_line(char *lp, int maxlen)
238 {
239 	struct input *p;
240 
241 	while( fgets(lp, maxlen, current_infile) == NULL ){
242 		if( (p = pending_input) == NULL )
243 			return 0;
244 		/* pop the input stack */
245 		fclose(current_infile);
246 		current_infile = p->fp;
247 		strcpy(in_name, p->name);
248 		lineno = p->lineno;
249 		pending_input = p->next;
250 		free(p);
251 	}
252 	++lineno;
253 	return 1;
254 }
255 
256 void
257 perr(char *fmt, ...)
258 {
259 	va_list ap;
260 	char error_string[256];
261 
262 	if( !pass2 )
263 		return;
264 	fprintf(stderr, "Error in line %d: ", lineno);
265 	va_start(ap, fmt);
266 	vsprintf(error_string, fmt, ap);
267 	va_end(ap);
268 	fprintf(stderr, "%s\n", error_string);
269 	list_error(error_string);
270 	++err_count;
271 }
272 
273 void
274 p1err(char *fmt, ...)
275 {
276 	va_list ap;
277 
278 	fprintf(stderr, "Pass 1 error in line %d: ", lineno);
279 	va_start(ap, fmt);
280 	vfprintf(stderr, fmt, ap);
281 	va_end(ap);
282 	fprintf(stderr, "\n");
283 	++err_count;
284 }
285 
286 void
287 yyerror(char *err)
288 {
289 
290 	perr("%s", err);
291 	longjmp(synerrjmp, 1);
292 }
293 
294 void *
295 alloc(size_t nbytes)
296 {
297 	void *p;
298 
299 	if( (p = malloc(nbytes)) == NULL ){
300 		fprintf(stderr, "Insufficient memory at line %d\n", lineno);
301 		exit(1);
302 	}
303 	return p;
304 }
305 
306 void
307 usage()
308 {
309 	fprintf(stderr,
310 		"Usage: gspa [-c c_array_name] [-l list_file] [-o hex_file] [infile]\n");
311 	exit(1);
312 }
313