1/* $NetBSD: gspa.c,v 1.14 2009/04/15 08:26:35 lukem 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.14 2009/04/15 08:26:35 lukem 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 55extern YYSTYPE yylval; 56int err_count; 57 58char line[MAXLINE]; 59unsigned lineno; 60 61extern int yydebug; 62short pass2; 63 64unsigned pc; 65unsigned highest_pc; 66unsigned line_pc; 67 68FILE *infile; 69FILE *current_infile; 70FILE *objfile; 71FILE *listfile; 72 73char *c_name; 74char in_name[PATH_MAX + 1]; 75 76struct input { 77 FILE *fp; 78 struct input *next; 79 int lineno; 80 char name[128]; 81} *pending_input; 82 83jmp_buf synerrjmp; 84 85void setext(char *, const char *, const char *); 86__dead static void usage(void); 87int yyparse(void); 88 89void c_dumpbuf(void); 90 91int 92main(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 195void 196setext(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 210void 211push_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 232int 233get_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 252void 253perr(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 269void 270p1err(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 282void 283yyerror(const char *errs) 284{ 285 286 perr("%s", errs); 287 longjmp(synerrjmp, 1); 288} 289 290static void 291usage(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