/* Author: Jose Romeo Vela Date: March 24, 2002 email: jrvela@aristasol.com http://www.aristasol.com/ This software is licensed under GNU's GPL. For details see http://www.gnu.org/ Copyright (c) 2002, Jose Romeo Vela ============================================================================== Modifications: 4/9/2002 jrv Show the -b option in the Usage message Added validation to the load_mem function to avoid out of bound memory loading. Added a new function begin_pc to process the -b option. 4/13/2002 jrv2 Added comments. Introduced the save_pc variable to save the -b option just in case that the -l option attempts to overrid it. 4/15/2002 jrv3 Fixed a bug introduced with jrv2. Added the option_b variable to solve the issue. 5/17/2002 jrv4 Standard input and standard output can now be used as input and output for cinc programs. This allows the programmer to type or pipe data to a cinc program when it is executed. If -i is ommited then use standard input (stdin) If -o is ommited then use standard outout (stdout) Depricated option -r, instead introduced option -n. */ #include #include #include #include "config.h" void pusage(void){ /* Display usage information */ printf("\nUsage: cinc [-vrhd] [-l ] [-i ] [-o ] [-b
]\n"); } void phelp(void) { pusage(); printf(" -v Version\n"); printf(" -r Depricated option ignored, see -n\n"); printf(" -n Don't Run Program\n"); printf(" -d Dump Memory\n"); printf(" -h Help\n"); printf(" -l Load program\n"); printf(" -b Begin Address\n"); printf(" -i IN file\n"); printf(" -o OUT file\n"); printf("Cardiac opeation codes:\n"); printf(" code abbr Meaning\n"); printf(" 0 INP Input\n"); printf(" 1 CLA Clear and Add\n"); printf(" 2 ADD Add\n"); printf(" 3 TAC Test Accumulator Contents\n"); printf(" 4 SFT Shift\n"); printf(" 5 OUT Output\n"); printf(" 6 STO Store\n"); printf(" 7 SUB Subtract\n"); printf(" 8 JMP Jump\n"); printf(" 9 HRS Halt and Reset\n\n"); } int begin_pc(char * optarg, struct cardiac_s * cardiac) { /* the begin option is a way to tell cinc what memory address to set the program counter. */ int rc = 0; int addr = 0; sscanf(optarg,"%d",&addr); /* Validate the address */ if ((addr >= 0) && (addr < MAXRAM)) { cardiac->pc = addr; } else { /* Out of bounds */ rc = 2; } return(rc); } int load_mem(char * filename,struct cardiac_s * cardiac) { /* This option loads a cardiac machine code program to memory */ int rc = 0; int addr = 0; int cont = 0; int scan_rc; int set_pc; FILE *load; load = NULL; load = fopen(filename,"r"); if (load == NULL) { rc = 1; return(rc); } set_pc = TRUE; while ( (scan_rc = fscanf(load,"%2d:%4d",&addr,&cont)) > 0 ) { if ( set_pc) { /* by default the program counter will be set to the first address given in the load file. This can be overriden by the -b option */ cardiac->pc=addr; set_pc = FALSE; } if (addr > 0 && addr < MAXRAM) { cardiac->ram[addr] = cont; } else { /* out of bounds attempt */ rc = 2; return(rc); } } fclose(load); return(rc); } int setopts(int argc, char *argv[], struct cardiac_s * cardiac) { int rc = 0; int opt; int exit_code; int save_pc; int option_b = FALSE; /* jrv4 aded two new variables */ int option_i = FALSE; int option_o = FALSE; tty = NULL; cardiac->running=TRUE; while ((opt = getopt(argc,argv,"vrnhdi:o:l:b:")) != -1) { switch (opt) { case 'v' : printf("cinc v %s - CARDIAC emulator\n",VERSION); cardiac->running=FALSE; break; case 'r' : /* depricated option ignore it */ break; case 'n' : cardiac->running=FALSE; break; case 'd' : cardiac->dump=TRUE; break; case 'b' : exit_code = 0; exit_code = begin_pc(optarg,cardiac); if (exit_code) rc = 20+exit_code; save_pc = cardiac->pc; option_b = TRUE; break; case 'l' : exit_code = 0; exit_code = load_mem(optarg,cardiac); if (exit_code) rc = 10+exit_code; break; case 'i': cardiac->IN=fopen(optarg,"r"); if (cardiac->IN==NULL) rc=32; option_i = TRUE; break; case 'o': cardiac->OUT=fopen(optarg,"w"); if (cardiac->OUT==NULL) rc=43; option_o = TRUE; break; case '?': cardiac->running=FALSE; printf("\nFor help, try: cinc -h\n"); rc = 0; break; case 'h': cardiac->running=FALSE; phelp(); rc = 0; break; } } /* jrv4 code to default to stdin and stdout */ if ( ! option_i ) { tty = fopen("/dev/tty","w"); cardiac->IN = stdin; } if ( ! option_o ) { cardiac->OUT = stdout; } if (option_b && (save_pc != cardiac->pc)) { /* the -b option has precedence over the -l option, thus pc needs to be reset to the value specified in the b option. */ cardiac->pc=save_pc; } /*Note: more option validation must be implemented in future version.*/ /* For the time being there may be conflicting options. */ return(rc); }