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