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