/* $NetBSD: gspa.c,v 1.15 2011/08/30 18:53:41 joerg Exp $ */ /* * GSP assembler main program * * Copyright (c) 1993 Paul Mackerras. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Paul Mackerras. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #ifndef lint __RCSID("$NetBSD: gspa.c,v 1.15 2011/08/30 18:53:41 joerg Exp $"); #endif #include #include #include #include #include #include #include #include #include #include #include "gsp_ass.h" #include "gsp_gram.h" #define YYDEBUG_VALUE 0 extern YYSTYPE yylval; int err_count; char line[MAXLINE]; unsigned lineno; extern int yydebug; short pass2; unsigned pc; unsigned highest_pc; unsigned line_pc; FILE *infile; FILE *current_infile; FILE *objfile; FILE *listfile; char *c_name; char in_name[PATH_MAX + 1]; struct input { FILE *fp; struct input *next; int lineno; char name[128]; } *pending_input; jmp_buf synerrjmp; void setext(char *, const char *, const char *); __dead static void usage(void); int yyparse(void); void c_dumpbuf(void); int main(int argc, char **argv) { char * volatile hex_name; char * volatile list_name; int c; hex_name = list_name = 0; /* parse options */ while ((c = getopt(argc, argv, "o:l:c:")) != -1) { switch (c) { case 'o': if (hex_name) usage(); hex_name = optarg; break; case 'c': if (c_name) usage(); c_name = optarg; break; case 'l': if (list_name) usage(); list_name = optarg; break; default: usage(); } } /* get source file */ argc -= optind; argv += optind; if (argc == 0) { infile = stdin; strlcpy(in_name, "", sizeof(in_name)); } else if (argc == 1) { strlcpy(in_name, *argv, sizeof(in_name)); if ((infile = fopen(in_name, "r")) == NULL) err(1, "fopen"); } else usage(); /* Pass 1 */ pending_input = NULL; current_infile = infile; yydebug = YYDEBUG_VALUE; pass2 = 0; pc = 0; lineno = 0; while( get_line(line, MAXLINE) ){ if( !setjmp(synerrjmp) ){ lex_init(line); yyparse(); } } if( err_count > 0 ) exit(1); /* Open output files */ if (hex_name == 0) objfile = stdout; else if ((objfile = fopen(hex_name, "w")) == NULL) err(1, "fopen"); if (c_name) { fprintf(objfile, "/*\n" " * This file was automatically created from\n" " * a TMS34010 assembler output file.\n" " * Do not edit manually.\n" " */\n" "#include \n" "u_int16_t %s[] = {\n\t", c_name); } if (list_name) if ((listfile = fopen(list_name, "w")) == NULL) err(1, "fopen"); /* Pass 2 */ pass2 = 1; rewind(infile); current_infile = infile; pc = 0; lineno = 0; reset_numeric_labels(); while( get_line(line, MAXLINE) ){ line_pc = pc; if( !setjmp(synerrjmp) ){ lex_init(line); yyparse(); } listing(); } if (c_name) { c_dumpbuf(); fprintf(objfile, "\n\t0\n};\n"); } exit(err_count != 0); } void setext(char *out, const char *in, const char *ext) { const char *p; p = strrchr(in, '.'); if( p != NULL ){ memcpy(out, in, p - in); strcpy(out + (p - in), ext); } else { strcpy(out, in); strcat(out, ext); } } void push_input(char *fn) { FILE *f; struct input *p; f = fopen(fn, "r"); if( f == NULL ){ p1err("Can't open input file %s", fn); return; } new(p); p->fp = current_infile; p->lineno = lineno; strlcpy(p->name, in_name, sizeof(p->name)); p->next = pending_input; current_infile = f; lineno = 1; strlcpy(in_name, fn, sizeof(in_name)); pending_input = p; } int get_line(char *lp, int maxlen) { struct input *p; while( fgets(lp, maxlen, current_infile) == NULL ){ if( (p = pending_input) == NULL ) return 0; /* pop the input stack */ fclose(current_infile); current_infile = p->fp; strlcpy(in_name, p->name, sizeof(in_name)); lineno = p->lineno; pending_input = p->next; free(p); } ++lineno; return 1; } void perr(const char *fmt, ...) { va_list ap; char error_string[256]; if( !pass2 ) return; fprintf(stderr, "Error in line %d: ", lineno); va_start(ap, fmt); vsprintf(error_string, fmt, ap); va_end(ap); fprintf(stderr, "%s\n", error_string); list_error(error_string); ++err_count; } void p1err(const char *fmt, ...) { va_list ap; fprintf(stderr, "Pass 1 error in line %d: ", lineno); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); ++err_count; } void yyerror(const char *errs) { perr("%s", errs); longjmp(synerrjmp, 1); } static void usage(void) { fprintf(stderr, "Usage: gspa [-c c_array_name] [-l list_file] [-o hex_file] [infile]\n"); exit(1); }