xref: /netbsd-src/usr.sbin/gspa/gspa/gspa.c (revision 514310971d8a7616ab21eacb952423d1d350090a)
1 /*	$NetBSD: gspa.c,v 1.15 2011/08/30 18:53:41 joerg 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.15 2011/08/30 18:53:41 joerg 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 #include <util.h>
49 
50 #include "gsp_ass.h"
51 #include "gsp_gram.h"
52 
53 #define YYDEBUG_VALUE	0
54 
55 extern YYSTYPE yylval;
56 int err_count;
57 
58 char line[MAXLINE];
59 unsigned lineno;
60 
61 extern int yydebug;
62 short pass2;
63 
64 unsigned pc;
65 unsigned highest_pc;
66 unsigned line_pc;
67 
68 FILE *infile;
69 FILE *current_infile;
70 FILE *objfile;
71 FILE *listfile;
72 
73 char *c_name;
74 char in_name[PATH_MAX + 1];
75 
76 struct input {
77 	FILE	*fp;
78 	struct input *next;
79 	int	lineno;
80 	char	name[128];
81 } *pending_input;
82 
83 jmp_buf synerrjmp;
84 
85 void	setext(char *, const char *, const char *);
86 __dead static void	usage(void);
87 int	yyparse(void);
88 
89 void	c_dumpbuf(void);
90 
91 int
main(int argc,char ** argv)92 main(int argc, char **argv)
93 {
94 	char * volatile hex_name;
95 	char * volatile list_name;
96 	int c;
97 
98 	hex_name = list_name = 0;
99 
100 	/* parse options */
101 	while ((c = getopt(argc, argv, "o:l:c:")) != -1) {
102 		switch (c) {
103 		case 'o':
104 			if (hex_name)
105 				usage();
106 			hex_name = optarg;
107 			break;
108 		case 'c':
109 			if (c_name)
110 				usage();
111 			c_name = optarg;
112 			break;
113 		case 'l':
114 			if (list_name)
115 				usage();
116 			list_name = optarg;
117 			break;
118 		default:
119 			usage();
120 		}
121 	}
122 
123 	/* get source file */
124 	argc -= optind;
125 	argv += optind;
126 	if (argc == 0) {
127 		infile = stdin;
128 		strlcpy(in_name, "<stdin>", sizeof(in_name));
129 	} else if (argc == 1) {
130 		strlcpy(in_name, *argv, sizeof(in_name));
131 		if ((infile = fopen(in_name, "r")) == NULL)
132 			err(1, "fopen");
133 	} else
134 		usage();
135 
136 	/* Pass 1 */
137 	pending_input = NULL;
138 	current_infile = infile;
139 
140 	yydebug = YYDEBUG_VALUE;
141 	pass2 = 0;
142 	pc = 0;
143 	lineno = 0;
144 	while( get_line(line, MAXLINE) ){
145 		if( !setjmp(synerrjmp) ){
146 			lex_init(line);
147 			yyparse();
148 		}
149 	}
150 	if( err_count > 0 )
151 		exit(1);
152 
153 	/* Open output files */
154 	if (hex_name == 0)
155 		objfile = stdout;
156 	else if ((objfile = fopen(hex_name, "w")) == NULL)
157 		err(1, "fopen");
158 	if (c_name) {
159 		fprintf(objfile, "/*\n"
160 		    " * This file was automatically created from\n"
161 		    " * a TMS34010 assembler output file.\n"
162 		    " * Do not edit manually.\n"
163 		    " */\n"
164 		    "#include <sys/types.h>\n"
165 		    "u_int16_t %s[] = {\n\t", c_name);
166 	}
167 	if (list_name)
168 		if ((listfile = fopen(list_name, "w")) == NULL)
169 			err(1, "fopen");
170 
171 	/* Pass 2 */
172 	pass2 = 1;
173 	rewind(infile);
174 	current_infile = infile;
175 	pc = 0;
176 	lineno = 0;
177 	reset_numeric_labels();
178 	while( get_line(line, MAXLINE) ){
179 		line_pc = pc;
180 		if( !setjmp(synerrjmp) ){
181 			lex_init(line);
182 			yyparse();
183 		}
184 		listing();
185 	}
186 
187 	if (c_name) {
188 		c_dumpbuf();
189 		fprintf(objfile, "\n\t0\n};\n");
190 	}
191 
192 	exit(err_count != 0);
193 }
194 
195 void
setext(char * out,const char * in,const char * ext)196 setext(char *out, const char *in, const char *ext)
197 {
198 	const char *p;
199 
200 	p = strrchr(in, '.');
201 	if( p != NULL ){
202 		memcpy(out, in, p - in);
203 		strcpy(out + (p - in), ext);
204 	} else {
205 		strcpy(out, in);
206 		strcat(out, ext);
207 	}
208 }
209 
210 void
push_input(char * fn)211 push_input(char *fn)
212 {
213 	FILE *f;
214 	struct input *p;
215 
216 	f = fopen(fn, "r");
217 	if( f == NULL ){
218 		p1err("Can't open input file %s", fn);
219 		return;
220 	}
221 	new(p);
222 	p->fp = current_infile;
223 	p->lineno = lineno;
224 	strlcpy(p->name, in_name, sizeof(p->name));
225 	p->next = pending_input;
226 	current_infile = f;
227 	lineno = 1;
228 	strlcpy(in_name, fn, sizeof(in_name));
229 	pending_input = p;
230 }
231 
232 int
get_line(char * lp,int maxlen)233 get_line(char *lp, int maxlen)
234 {
235 	struct input *p;
236 
237 	while( fgets(lp, maxlen, current_infile) == NULL ){
238 		if( (p = pending_input) == NULL )
239 			return 0;
240 		/* pop the input stack */
241 		fclose(current_infile);
242 		current_infile = p->fp;
243 		strlcpy(in_name, p->name, sizeof(in_name));
244 		lineno = p->lineno;
245 		pending_input = p->next;
246 		free(p);
247 	}
248 	++lineno;
249 	return 1;
250 }
251 
252 void
perr(const char * fmt,...)253 perr(const char *fmt, ...)
254 {
255 	va_list ap;
256 	char error_string[256];
257 
258 	if( !pass2 )
259 		return;
260 	fprintf(stderr, "Error in line %d: ", lineno);
261 	va_start(ap, fmt);
262 	vsprintf(error_string, fmt, ap);
263 	va_end(ap);
264 	fprintf(stderr, "%s\n", error_string);
265 	list_error(error_string);
266 	++err_count;
267 }
268 
269 void
p1err(const char * fmt,...)270 p1err(const char *fmt, ...)
271 {
272 	va_list ap;
273 
274 	fprintf(stderr, "Pass 1 error in line %d: ", lineno);
275 	va_start(ap, fmt);
276 	vfprintf(stderr, fmt, ap);
277 	va_end(ap);
278 	fprintf(stderr, "\n");
279 	++err_count;
280 }
281 
282 void
yyerror(const char * errs)283 yyerror(const char *errs)
284 {
285 
286 	perr("%s", errs);
287 	longjmp(synerrjmp, 1);
288 }
289 
290 static void
usage(void)291 usage(void)
292 {
293 	fprintf(stderr,
294 		"Usage: gspa [-c c_array_name] [-l list_file] [-o hex_file] [infile]\n");
295 	exit(1);
296 }
297