/* @@@@ @ @ @ @@@@@ @ @@@@@@ @@@@ @ @ @@ @@ @ @ @ @ @ @ @@@@ @ @ @@ @ @ @ @ @@@@@ @ @ @ @ @ @@@@@ @ @ @@@ @ @ @ @ @ @ @ @ @ @@@ @ @ @@@@ @ @ @ @ @@@@@@ @@@@@@ @@@ @@@@ * simple.c - a compiler for simple * * simple [-l list_name][-o code_file][-nc][-nl][-d][-a][-i][-s][-v] source_file * The options/flags are as follows: * -o name : rename the assembly code file * -l name : rename the output list file * -nc : do not generate code * -nl : do not generate listing * -d : turn off the Tokentrace/Semtrace - default is on * -a : turn on assembler dump to screen * -i : dump Intermediate Representation (AST) after parse * -s : dump symbol table after parse * -v : dump variable addresses (types-later) at beginning * of code generation * -p : turn on Procedure Trace for the parse (sem.c) * -c : turn on Ptrace for codegen.c * -t : turn on Ptrace for the AST * -b : turn on Ptrace for the symboltable * -y : view every parser reduction from yacc * * There are also toggles that are decoded by simple.lex. These are placed * in the input source code and can deliver debugging information. * */ #include #include #include "astdef.h" #define BOOLEAN_LOCAL #include "booldef.h" #include "codegen.h" #define FILEDEF_LOCAL #include "filedef.h" #include "printree.h" #include "sem.h" #include "symtab.h" #include "tracing.h" static void init_simple(void); extern int yyparse(void); static char *usage="usage :\nsimple [-l list_name][-o code_file][-nc][-nl][-d][-a][-i][-s][-v] source_file"; static char *usage_desc[] = { " -o name : rename the assembly code file", " -l name : rename the output list file", " -nc : do not generate code", " -nl : do not generate listing", " -d : turn off Tokentrace/Semstack flag", " -a : turn on assembler dump to screen", " -i : dump Intermediate Representation", " -s : dump Symbol Table after parse", " -v : dump variables addresses", " -p : turn on PtraceSem", " -c : turn on PtraceCode", " -b : turn on PtraceSymtab", " -t : turn on PtraceTree", " -y : view parser reductions (yacc)", "\nCompiler directives (default values in parens):", " %%dmp : Dump the Symbol Table now (off)", " %%c : Toggle code generation (on)", " %%t : Toggle token trace (off)", " %%ss : Toggle semantic stack display (off)", " %%pr : Toggle procedure trace (off)", NULL }; main(argc,argv) int argc; char *argv[]; { int i; int return_code = 0; char *progname; /* for diagnostic output */ char *usage_ptr; FILE *fopen(); Entering("simple.c"); /* MDM Tell user if program not invoked properly...*/ if (argc < 2) { /* Not enough parameters given */ fprintf(stderr,"\n\nNo parameters specified\n"); fprintf(stderr,"%s\n\n", usage); for(i = 0; usage_desc[i]; i++) printf("%s\n", usage_desc[i]); exit( COMPILE_BAD ); } /* since we have command line compiler flag setting (that might * overide the defaults, we must initialize first. */ init_simple(); /* check arguments */ progname = argv[0]; for(i=1 ; i2) CodeName = argv[i]+2; else CodeName = argv[++i]; break; case 'l' : /* interpret the rest of the current argument * or the next argument as the new ListName */ if(strlen(argv[i])>2) ListName = argv[i]+2; else ListName = argv[++i]; break; case 'n' : if(argv[i][2] == 'c') Gencode=FALSE; else if(argv[i][2] == 'l') Listing=FALSE; else{ fprintf(stderr, "%s : Unknown option %s\n", progname,argv[i][1]); fprintf(stderr,"%s\n",usage); exit(1); } break; case 'p': PtraceSem = TRUE; break; case 'c': PtraceCode = TRUE; break; case 't': PtraceTree = TRUE; break; case 'b': PtraceSymtab = TRUE; break; case 'y': SL_dump = TRUE; break; default : fprintf(stderr,"%s : Unknown option %s\n", progname,argv[i][1]); fprintf(stderr,"%s\n",usage); exit(1); } } else /* interpret as SourceName */ SourceName = argv[i]; } /* open source file */ if((SourceFile=fopen(SourceName,"r"))==NULL){ fprintf(stderr,"%s: cannot open %s\n",progname,SourceName); exit(1); } dup2( fileno(SourceFile), fileno(stdin) ); if(Listing){ /* open list file */ if((ListFile=fopen(ListName,"w"))==NULL){ fprintf(stderr, "%s: cannot open %s\n",progname,ListName); exit(1); } } if (AssemblerDump) { printf("\n*** Sending Assembler Code to Screen ***\n"); CodeFile = stdout; } else { if((CodeFile = fopen(CodeName,"w")) == NULL){ printf("Unable to open %s. No code generated.\n", CodeName); return(ERROR); } } if(InitSemantics() != OK) { fprintf(stderr, " from main: Fatal: Unable to initialize semantics.\n"); exit(1); } /* if no syntax errors and no semantic errors generate code */ /* yyparse() will return 0 if no parser errors were encountered */ if(! yyparse()) { if (SymTabDump) DumpSymTab(); if(Intermediatetrace) PrintTree(); if(Gencode) { GenCode(); printf("COMPILATION COMPLETE\n"); } else printf("COMPILATION ABORTED\n"); return_code = COMPILE_OK; } else { return_code = COMPILE_BAD ; printf("NO CODE GENERATED\n"); } fclose(SourceFile); fclose(CodeFile); /* added this for bc */ if (Listing) fclose(ListFile); Leaving("simple.c"); return return_code; } /* main */ /* initialize the compiler */ void init_simple(void) { Gencode = TRUE; Listing = TRUE; Semstacktrace = FALSE; /* these two provide lots of debugging info */ Tokentrace = FALSE; SymTabDump = FALSE; Vartrace = FALSE; Intermediatetrace = FALSE; AssemblerDump = FALSE ; PtraceSem = FALSE ; PtraceCode = FALSE; PtraceSymtab = FALSE; PtraceTree = FALSE; SL_dump = FALSE; CodeName = "s.out"; ListName = "s.list"; }