/* main.c */ /********************************************* * Main Program for Symbolic Assembler * * Author: Douglas W. Jones, Jan. 23, 2003 * * Revised: Douglas W. Jones, June 9, 2004 * * Revised: Douglas W. Jones, July 12, 2004 * \*MP3*\ *********************************************/ /* version number and authorship */ /* VERSION defined by Makefile */ /* AUTHOR defined by Makefile */ /* maximum length of the output file name */ /* NAMELEN defined by Makefile */ #include #include #include #include #include "boolean.h" #include "exception.h" #include "stringpool.h" #include "symboltable.h" #include "objectcode.h" #include "lexical.h" #include "parser.h" /********************************************* * Private main program data * *********************************************/ /* the input, object and listing files */ /*MP3*/ static FILE * in; static FILE * out; static FILE * obj; /*MP3*/ /* program options */ static BOOLEAN dump = FALSE; /********************************************* * The code * *********************************************/ static void arggripe( char * name, char * msg ) /* gripe about an invalid command line argument given: name, argv[0], the program name msg, the error message to output WARNING: terminates program! */ { fputs( name, stderr ); fputs( msg, stderr ); exit(-1); } static void getmyargs( int argc, char * argv[] ) /* get the program's command line arguments arguments accepted are -l -- sets outname to the string given for -o -- sets outname to the string given for \*MP3*\ -d -- sets dump to true - -- outputs a help message -- sets inname to the string given for */ { /* pointers to input and output file names */ char * inname = NULL; char * outname = NULL; char * objname = NULL; /*MP3*/ /* buffer to hold name being edited */ char editname[NAMELEN]; int i; /* walk through command line arguments */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { /* argument is an option */ if (strcmp( argv[i], "-l") == 0) { i++; if (outname != NULL) { arggripe( argv[0], " -l " "-l duplicated\n" ); } else if (i >= argc) { arggripe( argv[0], " -l ; " " not found\n" ); } else { outname = argv[i]; } /*MP3*/ } else if (strcmp( argv[i], "-o") == 0) { /*MP3*/ /************************************* \*MP3*\ * note: this block of code repeats * \*MP3*\ * the above, and it would be nice * \*MP3*\ * to break it off into a subroutine * \*MP3*\ * but this isn't done here * \*MP3*\ *************************************/ /*MP3*/ i++; /*MP3*/ if (objname != NULL) { /*MP3*/ arggripe( argv[0], " -l " /*MP3*/ "-l duplicated\n" ); /*MP3*/ } else if (i >= argc) { /*MP3*/ arggripe( argv[0], " -l ; " /*MP3*/ " not found\n" ); /*MP3*/ } else { /*MP3*/ objname = argv[i]; /*MP3*/ } } else if (strcmp( argv[i], "-d") == 0) { dump = TRUE; } else { /* any other option results in help message */ arggripe( argv[0], " [-l ] [-d]\n" " assemble EAL code from ,\n" " listing directed to to " " (defaults to .l),\n" " where =" " .;\n" " -d adds symbol table to listing.\n" "\n EAL " VERSION " by " AUTHOR ".\n" ); } } else { /* argument must be */ if (inname != NULL) { arggripe( argv[0], " " " duplicated!\n" ); } else { inname = argv[i]; } } /* end if */ } /* end for */ /* next, see if any arguments weren't supplied */ if (inname == NULL) { /* if missing input name, error! */ arggripe( argv[0], " " " missing!\n" ); } if (outname == NULL) { int len = strlen( inname ); char * dot; if (len > (NAMELEN - 3)) { arggripe( argv[0], " " " name too long!\n" ); } /* if missing output name, derive it from input name */ strcpy( editname, inname ); /* patch .l suffix onto input */ dot = strrchr( editname, '.' ); if (dot == NULL) dot = &editname[len]; strcpy( dot, ".l" ); outname = editname; } /* next, see arguments are rational */ if (strcmp(inname, outname) == 0) { arggripe( argv[0], " -l " " output will overwrite input!\n" ); } /* next, try to open files */ in = fopen( inname, "r" ); if (in == NULL) { arggripe( argv[0], " " " could not open input!\n" ); } out = fopen( outname, "w" ); if (out == NULL) { arggripe( argv[0], " -l " " could not open output!\n" ); } /* next, deal with object file */ /*MP3*/ /************************************* \*MP3*\ * note: this block of code repeats * \*MP3*\ * the above, and it would be nice * \*MP3*\ * to break it off into a subroutine * \*MP3*\ * but this isn't done here * \*MP3*\ *************************************/ /*MP3*/ if (objname == NULL) { /*MP3*/ int len = strlen( inname ); /*MP3*/ char * dot; /*MP3*/ /*MP3*/ if (len > (NAMELEN - 3)) { /*MP3*/ arggripe( argv[0], " " /*MP3*/ " name too long!\n" ); /*MP3*/ } /*MP3*/ /*MP3*/ /* if missing object name, derive it from input name */ /*MP3*/ strcpy( editname, inname ); /*MP3*/ /*MP3*/ /* patch .o suffix onto input */ /*MP3*/ dot = strrchr( editname, '.' ); /*MP3*/ if (dot == NULL) dot = &editname[len]; /*MP3*/ strcpy( dot, ".o" ); /*MP3*/ /*MP3*/ objname = editname; /*MP3*/ } /*MP3*/ /*MP3*/ /* next, see arguments are rational */ /*MP3*/ if (strcmp(inname, objname) == 0) { /*MP3*/ arggripe( argv[0], " -l " /*MP3*/ " object will overwrite input!\n" ); /*MP3*/ } /*MP3*/ /*MP3*/ /* next, try to open object file */ /*MP3*/ obj = fopen( objname, "w" ); /*MP3*/ if (obj == NULL) { /*MP3*/ arggripe( argv[0], " -o " /*MP3*/ " could not open object!\n" ); /*MP3*/ } /*MP3*/ } int main(int argc, char * argv[]) { /* initialization */ EXCEPT_INIT( pool_full, "Unhandled string pool overflow" ); EXCEPT_INIT( sym_full, "Unhandled symbol table overflow" ); getmyargs( argc, argv ); pool_init(); sym_init(); object_init( NULL ); /*MP3*/ lex_init( in, NULL, NULL ); parse_init(); /* first pass of 2-pass assembly */ parse_program(); if (fseek( in, 0, SEEK_SET )) { arggripe( argv[0], " " " could not seek in input!\n" ); } lex_init( in, out, stderr ); /* second pass of 2-pass assembly */ object_init( obj ); /*MP3*/ parse_program(); /* if requested, append a symbol table dump to the listing */ if (dump) parse_dump( out ); exit(0); }