Home | History | Annotate | Line # | Download | only in gspa
      1 /*	$NetBSD: gspa.c,v 1.16 2025/11/24 08:04:28 nia 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. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 #ifndef lint
     33 __RCSID("$NetBSD: gspa.c,v 1.16 2025/11/24 08:04:28 nia Exp $");
     34 #endif
     35 
     36 #include <sys/param.h>
     37 #include <err.h>
     38 #include <errno.h>
     39 #include <setjmp.h>
     40 #include <stdarg.h>
     41 #include <stdio.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #include <unistd.h>
     45 #include <util.h>
     46 
     47 #include "gsp_ass.h"
     48 #include "gsp_gram.h"
     49 
     50 #define YYDEBUG_VALUE	0
     51 
     52 extern YYSTYPE yylval;
     53 int err_count;
     54 
     55 char line[MAXLINE];
     56 unsigned lineno;
     57 
     58 extern int yydebug;
     59 short pass2;
     60 
     61 unsigned pc;
     62 unsigned highest_pc;
     63 unsigned line_pc;
     64 
     65 FILE *infile;
     66 FILE *current_infile;
     67 FILE *objfile;
     68 FILE *listfile;
     69 
     70 char *c_name;
     71 char in_name[PATH_MAX + 1];
     72 
     73 struct input {
     74 	FILE	*fp;
     75 	struct input *next;
     76 	int	lineno;
     77 	char	name[128];
     78 } *pending_input;
     79 
     80 jmp_buf synerrjmp;
     81 
     82 void	setext(char *, const char *, const char *);
     83 __dead static void	usage(void);
     84 int	yyparse(void);
     85 
     86 void	c_dumpbuf(void);
     87 
     88 int
     89 main(int argc, char **argv)
     90 {
     91 	char * volatile hex_name;
     92 	char * volatile list_name;
     93 	int c;
     94 
     95 	hex_name = list_name = 0;
     96 
     97 	/* parse options */
     98 	while ((c = getopt(argc, argv, "o:l:c:")) != -1) {
     99 		switch (c) {
    100 		case 'o':
    101 			if (hex_name)
    102 				usage();
    103 			hex_name = optarg;
    104 			break;
    105 		case 'c':
    106 			if (c_name)
    107 				usage();
    108 			c_name = optarg;
    109 			break;
    110 		case 'l':
    111 			if (list_name)
    112 				usage();
    113 			list_name = optarg;
    114 			break;
    115 		default:
    116 			usage();
    117 		}
    118 	}
    119 
    120 	/* get source file */
    121 	argc -= optind;
    122 	argv += optind;
    123 	if (argc == 0) {
    124 		infile = stdin;
    125 		strlcpy(in_name, "<stdin>", sizeof(in_name));
    126 	} else if (argc == 1) {
    127 		strlcpy(in_name, *argv, sizeof(in_name));
    128 		if ((infile = fopen(in_name, "r")) == NULL)
    129 			err(1, "fopen");
    130 	} else
    131 		usage();
    132 
    133 	/* Pass 1 */
    134 	pending_input = NULL;
    135 	current_infile = infile;
    136 
    137 	yydebug = YYDEBUG_VALUE;
    138 	pass2 = 0;
    139 	pc = 0;
    140 	lineno = 0;
    141 	while( get_line(line, MAXLINE) ){
    142 		if( !setjmp(synerrjmp) ){
    143 			lex_init(line);
    144 			yyparse();
    145 		}
    146 	}
    147 	if( err_count > 0 )
    148 		exit(1);
    149 
    150 	/* Open output files */
    151 	if (hex_name == 0)
    152 		objfile = stdout;
    153 	else if ((objfile = fopen(hex_name, "w")) == NULL)
    154 		err(1, "fopen");
    155 	if (c_name) {
    156 		fprintf(objfile, "/*\n"
    157 		    " * This file was automatically created from\n"
    158 		    " * a TMS34010 assembler output file.\n"
    159 		    " * Do not edit manually.\n"
    160 		    " */\n"
    161 		    "#include <sys/types.h>\n"
    162 		    "u_int16_t %s[] = {\n\t", c_name);
    163 	}
    164 	if (list_name)
    165 		if ((listfile = fopen(list_name, "w")) == NULL)
    166 			err(1, "fopen");
    167 
    168 	/* Pass 2 */
    169 	pass2 = 1;
    170 	rewind(infile);
    171 	current_infile = infile;
    172 	pc = 0;
    173 	lineno = 0;
    174 	reset_numeric_labels();
    175 	while( get_line(line, MAXLINE) ){
    176 		line_pc = pc;
    177 		if( !setjmp(synerrjmp) ){
    178 			lex_init(line);
    179 			yyparse();
    180 		}
    181 		listing();
    182 	}
    183 
    184 	if (c_name) {
    185 		c_dumpbuf();
    186 		fprintf(objfile, "\n\t0\n};\n");
    187 	}
    188 
    189 	exit(err_count != 0);
    190 }
    191 
    192 void
    193 setext(char *out, const char *in, const char *ext)
    194 {
    195 	const char *p;
    196 
    197 	p = strrchr(in, '.');
    198 	if( p != NULL ){
    199 		memcpy(out, in, p - in);
    200 		strcpy(out + (p - in), ext);
    201 	} else {
    202 		strcpy(out, in);
    203 		strcat(out, ext);
    204 	}
    205 }
    206 
    207 void
    208 push_input(char *fn)
    209 {
    210 	FILE *f;
    211 	struct input *p;
    212 
    213 	f = fopen(fn, "r");
    214 	if( f == NULL ){
    215 		p1err("Can't open input file %s", fn);
    216 		return;
    217 	}
    218 	new(p);
    219 	p->fp = current_infile;
    220 	p->lineno = lineno;
    221 	strlcpy(p->name, in_name, sizeof(p->name));
    222 	p->next = pending_input;
    223 	current_infile = f;
    224 	lineno = 1;
    225 	strlcpy(in_name, fn, sizeof(in_name));
    226 	pending_input = p;
    227 }
    228 
    229 int
    230 get_line(char *lp, int maxlen)
    231 {
    232 	struct input *p;
    233 
    234 	while( fgets(lp, maxlen, current_infile) == NULL ){
    235 		if( (p = pending_input) == NULL )
    236 			return 0;
    237 		/* pop the input stack */
    238 		fclose(current_infile);
    239 		current_infile = p->fp;
    240 		strlcpy(in_name, p->name, sizeof(in_name));
    241 		lineno = p->lineno;
    242 		pending_input = p->next;
    243 		free(p);
    244 	}
    245 	++lineno;
    246 	return 1;
    247 }
    248 
    249 void
    250 perr(const char *fmt, ...)
    251 {
    252 	va_list ap;
    253 	char error_string[256];
    254 
    255 	if( !pass2 )
    256 		return;
    257 	fprintf(stderr, "Error in line %d: ", lineno);
    258 	va_start(ap, fmt);
    259 	vsprintf(error_string, fmt, ap);
    260 	va_end(ap);
    261 	fprintf(stderr, "%s\n", error_string);
    262 	list_error(error_string);
    263 	++err_count;
    264 }
    265 
    266 void
    267 p1err(const char *fmt, ...)
    268 {
    269 	va_list ap;
    270 
    271 	fprintf(stderr, "Pass 1 error in line %d: ", lineno);
    272 	va_start(ap, fmt);
    273 	vfprintf(stderr, fmt, ap);
    274 	va_end(ap);
    275 	fprintf(stderr, "\n");
    276 	++err_count;
    277 }
    278 
    279 void
    280 yyerror(const char *errs)
    281 {
    282 
    283 	perr("%s", errs);
    284 	longjmp(synerrjmp, 1);
    285 }
    286 
    287 static void
    288 usage(void)
    289 {
    290 	fprintf(stderr,
    291 		"Usage: gspa [-c c_array_name] [-l list_file] [-o hex_file] [infile]\n");
    292 	exit(1);
    293 }
    294