Home | History | Annotate | Line # | Download | only in gspa
      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
     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
    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
    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
    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
    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
    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
    283 yyerror(const char *errs)
    284 {
    285 
    286 	perr("%s", errs);
    287 	longjmp(synerrjmp, 1);
    288 }
    289 
    290 static 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