/* Process the START pseudo operator. */ void PSEUDO_START(char *LABEL_NAME,char *ARGUMENTS,int *LOCATION, SYMBOL_TABLE *SYM_TAB,FILE *OUTPUT_STREAM) { struct SYMBOL_TABLE_ENTRY *TABLE_ENTRY; int VALUE; char *START; if (!SEEN_END_OP) { (void) fprintf(OUTPUT_STREAM,"eERROR[27]: Section %s has no 'end'.\n", MODULE_NAME); OUTPUT_BUFFER(&MOD_REC_BUF,OUTPUT_STREAM,1); LOCATION_EXCEEDS_MEM_SIZE = 0; (void) fprintf(OUTPUT_STREAM,"E\n"); TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,MODULE_NAME,SYM_TAB); (*TABLE_ENTRY).LENGTH = (*LOCATION) - (*TABLE_ENTRY).LOCATION; } if (SEEN_START_OP == SEEN_START_1) (void) fprintf(OUTPUT_STREAM, "eERROR[32]: Multiple STARTs in this file.\n"); SEEN_START_OP = SEEN_START_1; SEEN_END_OP = NO_END_SEEN_1; if (!strcmp(LABEL_NAME,"")) { (void) fprintf(OUTPUT_STREAM,"eERROR[33]: START requires a label.\n"); GET_NEXT_MISSING_LABEL(LABEL_NAME,SYM_TAB); } if (LOOK_UP_SYMBOL(LABEL_NAME,LABEL_NAME,SYM_TAB) != NULL) { (void) fprintf(OUTPUT_STREAM,"eERROR[55]: Multiply defined module name.\n"); (void) strcpy(MODULE_NAME,LABEL_NAME); } else { /* --------------- Modify LABEL_NAMEs symbol table entry to reflect that it */ /* is a module name. */ TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,LABEL_NAME,SYM_TAB); START = ARGUMENTS; VALUE = GET_NUM(&START,MEM_ADDR_SIZE_1+1,10); OUTPUT_BUFFER(&ERROR_REC_BUF,OUTPUT_STREAM,1); if (VALUE < 0) (void) fprintf(OUTPUT_STREAM,"eERROR[34]: Negative starting address.\n"); else (*TABLE_ENTRY).LOCATION = VALUE; if (!IS_BLANK_OR_TAB(*START) && !eoln(*START) && (START != ARGUMENTS)) (void) fprintf(OUTPUT_STREAM, "eERROR[13]: Expected a <space> after the operand, found %c.\n", *START); /* ---------------- Indicate that is a module and the MAIN module. */ (void) strcpy( (*TABLE_ENTRY).MODULE, LABEL_NAME); (void) strcpy(MODULE_NAME,LABEL_NAME); (void) strcpy(MAIN_ROUTINE,LABEL_NAME); (*LOCATION) = (*TABLE_ENTRY).LOCATION; (void) fprintf(OUTPUT_STREAM,"s%s\n",MODULE_NAME); } }
/* Process the EQU pseudo operator. */ void PSEUDO_EQU(char *LABEL_NAME,char *ARGUMENTS,int *LOCATION, SYMBOL_TABLE *SYM_TAB,FILE *OUTPUT_STREAM) { if (!strcmp(LABEL_NAME,"")) (void) fprintf(OUTPUT_STREAM,"eERROR[23]: EQU requires a label.\n"); else { char *START; struct SYMBOL_TABLE_ENTRY *TABLE_ENTRY; int ABS_VAL = ABSOLUTE_VALUE_1; START = ARGUMENTS; TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,LABEL_NAME,SYM_TAB); (*TABLE_ENTRY).LOCATION = GET_EXPRESSION(&START,MEM_ADDR_SIZE_1+1,*LOCATION,SYM_TAB,&ABS_VAL); OUTPUT_BUFFER(&ERROR_REC_BUF,OUTPUT_STREAM,1); (*TABLE_ENTRY).TYPE = ABSOLUTE; if (!IS_BLANK_OR_TAB(*START) && !eoln(*START) && (START != ARGUMENTS)) (void) fprintf(OUTPUT_STREAM, "eERROR[13]: Expected a <space> after the operand, found %c.\n", *START); } }
/* Process the CSECT pseudo operator. */ void PSEUDO_CSECT(char *LABEL_NAME,char *ARGUMENTS,int *LOCATION, SYMBOL_TABLE *SYM_TAB,FILE *OUTPUT_STREAM) { struct SYMBOL_TABLE_ENTRY *TABLE_ENTRY; if (!SEEN_END_OP) { /* --------- If haven't seen an end, then pretend you did. */ (void) fprintf(OUTPUT_STREAM,"eERROR[27]: Section %s has no 'end'.\n", MODULE_NAME); OUTPUT_BUFFER(&MOD_REC_BUF,OUTPUT_STREAM,1); LOCATION_EXCEEDS_MEM_SIZE = 0; (void) fprintf(OUTPUT_STREAM,"E\n"); TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,MODULE_NAME,SYM_TAB); (*TABLE_ENTRY).LENGTH = (*LOCATION) - (*TABLE_ENTRY).LOCATION; } SEEN_END_OP = NO_END_SEEN_1; if (!strcmp(LABEL_NAME,"")) { (void) fprintf(OUTPUT_STREAM,"eERROR[26]: CSECT requires a label.\n"); GET_NEXT_MISSING_LABEL(LABEL_NAME,SYM_TAB); } if (LOOK_UP_SYMBOL(LABEL_NAME,LABEL_NAME,SYM_TAB) != NULL) { (void) fprintf(OUTPUT_STREAM,"eERROR[55]: Multiply defined module name.\n"); (void) strcpy(MODULE_NAME,LABEL_NAME); } else { /* --------------- Update symbol to reflect fact that LABEL_NAME is a module */ /* name. */ TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,LABEL_NAME,SYM_TAB); (*TABLE_ENTRY).LOCATION = 0; (void) strcpy( (*TABLE_ENTRY).MODULE, LABEL_NAME); (void) strcpy(MODULE_NAME,LABEL_NAME); /* ---------------- Reset location counter to zero */ (*LOCATION) = 0; (void) fprintf(OUTPUT_STREAM,"s%s\n",MODULE_NAME); } }
/* Load the program from the executable file. */ void LOAD(BOOLEAN DEBUG_MODE,int *ERROR,FILE *INPUT) { char *RECORD; /* One record from the input stream */ int LENGTH; /* Used to store length of blocks of */ /* memory affected by text and modification*/ /* records */ int LOCATION = 0; /* Location to load next csect */ char MODULE_NAME[LABEL_SIZE_1+1]; /* Name of a module of program. */ MODULE_NAME[LABEL_SIZE_1] = '\0'; if (feof(INPUT)) (*ERROR) = TRUE_1; else { GET_LINE(&RECORD,INPUT); if ((RECORD[0] != 'S') || (strlen(RECORD) != 14)) (*ERROR) = TRUE_1; else { /* ---------------------------- START RECORD ------------------------------- */ if (DEBUG_MODE) { MAIN_ROUTINE[LABEL_SIZE_1] = '\0'; (void) strncpy(MAIN_ROUTINE,&(RECORD[1]),LABEL_SIZE_1); } STR_TO_NUM(&(RECORD[LABEL_SIZE_1+1]), 5, 16, &START_ADDRESS,ERROR); } } while (!feof(INPUT) && (LOCATION <= MEM_SIZE_1) && !(*ERROR)) { GET_LINE(&RECORD,INPUT); switch (RECORD[0]) { case 'T': /* ---------------------------- TEXT RECORD -------------------------------- */ if (strlen(RECORD) < 9) (*ERROR) = TRUE_1; else { STR_TO_NUM(&(RECORD[1]),6,16,&LOCATION,ERROR); STR_TO_NUM(&(RECORD[7]),2,16,&LENGTH,ERROR); if (strlen(RECORD) != 9+LENGTH*2) (*ERROR) = TRUE_1; else STORE_AT(&(RECORD[9]), LENGTH, LOCATION, MEMORY,ERROR); } break; case 'M': /* ---------------------- MODULE RECORD ------------------------------------ */ if (strlen(RECORD) != (13 + LABEL_SIZE_1)) (*ERROR) = TRUE_1; else if (DEBUG_MODE) { (void) strncpy(MODULE_NAME,&(RECORD[1]),LABEL_SIZE_1); STR_TO_NUM(&(RECORD[9]),6,16,&LOCATION,ERROR); (*ERROR) = !INSERT_IN_SYM_TAB(GLOBAL_1,MODULE_NAME,LOCATION,MODULE, &SYM_TAB); STR_TO_NUM(&(RECORD[15]),6,16,&LENGTH,ERROR); (*LOOK_UP_SYMBOL(GLOBAL_1,MODULE_NAME,&SYM_TAB)).LENGTH = LENGTH; } break; case 'G': /* ----------------------- GLOBAL RECORD ----------------------------------- */ if (strlen(RECORD) != (7 + LABEL_SIZE_1)) (*ERROR) = TRUE_1; else if (DEBUG_MODE) { (void) strncpy(MODULE_NAME,&(RECORD[1]),LABEL_SIZE_1); STR_TO_NUM(&(RECORD[9]),6,16,&LOCATION,ERROR); (*ERROR) = !INSERT_IN_SYM_TAB(GLOBAL_1,MODULE_NAME,LOCATION,GLOBAL, &SYM_TAB); } break; case '\0': default: break; } } if (*ERROR) (void) printf("ERROR: Input is not an executable file. Aborting.\n"); }
/* Process the END pseudo operator. */ void PSEUDO_END(char *LABEL_NAME,char *ARGUMENTS,int *LOCATION, SYMBOL_TABLE *SYM_TAB,FILE *OUTPUT_STREAM) { struct SYMBOL_TABLE_ENTRY *TABLE_ENTRY; SEEN_END_OP = END_SEEN_1; if (strcmp(ARGUMENTS,"")) { char OPERAND_LAB[LABEL_SIZE_1+1]; char *START; START = ARGUMENTS; GET_LABEL(OPERAND_LAB,ARGUMENTS,&START,pass1); OUTPUT_BUFFER(&ERROR_REC_BUF,OUTPUT_STREAM,1); if (strcmp(OPERAND_LAB,"")) { /* ----------- End specifies a start adress. */ struct SYMBOL_TABLE_ENTRY *TABLE_ENTRY; TABLE_ENTRY = LOOK_UP_SYMBOL(MAIN_ROUTINE,OPERAND_LAB,SYM_TAB); if (TABLE_ENTRY == NULL) (void) fprintf(OUTPUT_STREAM,"eERROR[28]: Label %s not defined.\n", OPERAND_LAB); else if ((*TABLE_ENTRY).TYPE == ABSOLUTE) (void) fprintf(OUTPUT_STREAM, "eERROR[28]: Expected label, found constant %s.\n", OPERAND_LAB); else { /* ---------------- Found an valid end statement. Clear modify buffer. */ OUTPUT_BUFFER(&MOD_REC_BUF,OUTPUT_STREAM,1); LOCATION_EXCEEDS_MEM_SIZE = 0; (void) fprintf(OUTPUT_STREAM,"E\n"); if (START_ADDRESS == -1) START_ADDRESS = (*TABLE_ENTRY).LOCATION; else (void) fprintf(OUTPUT_STREAM, "eERROR[54]: Multiple starting addresses. Using first.\n"); } if (!IS_BLANK_OR_TAB(*START) && !eoln(*START) && (START != ARGUMENTS)) (void) fprintf(OUTPUT_STREAM, "eERROR[13]: Expected a <space> after the operand, found %c.\n", *START); } else (void) fprintf(OUTPUT_STREAM, "eERROR[31]: Expected a Symbol, found %s.\n", ARGUMENTS); } else { /* ------------------ End doesn't specify a start address */ /* Clear modify buffer */ OUTPUT_BUFFER(&MOD_REC_BUF,OUTPUT_STREAM,1); LOCATION_EXCEEDS_MEM_SIZE = 0; (void) fprintf(OUTPUT_STREAM,"E\n"); } TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,MODULE_NAME,SYM_TAB); (*TABLE_ENTRY).LENGTH = (*LOCATION) - (*TABLE_ENTRY).LOCATION; (void) strcpy(MODULE_NAME,"_"); (*LOCATION) = 0; }
/* Drives the pass1 process, letting others do the real work. */ void PASS1(FILE *INPUT_FILE,SYMBOL_TABLE *SYM_TABLE,FILE *TEMP_OUTPUT_STREAM) { char LABEL_NAME[LABEL_SIZE_1+1]; /* Place to store a label. */ char OPCODE[LABEL_SIZE_1+1]; /* Place to store an opcode. */ char *ARGUMENTS; /* Pointer to arguments/comments */ char *INPUT_LINE; /* Pointer to whole source line */ int EXTENDED_CODE; /* Boolean: Is this an extended */ /* format instruction. */ int LOCATION_COUNTER =0; MODULE_NAME[0] = '_'; MODULE_NAME[1] = '\0'; (void) INSERT_IN_SYM_TAB(MODULE_NAME,MODULE_NAME,0,RELATIVE,SYM_TABLE); MAIN_ROUTINE[0] = '\0'; LABEL_NAME[0] = '\0'; while (!feof(INPUT_FILE)) { /* --------------------- Get the source line and do some parsing */ SCAN_LINE(LOCATION_COUNTER,&INPUT_LINE,LABEL_NAME, &EXTENDED_CODE,OPCODE,&ARGUMENTS,pass1, TEMP_OUTPUT_STREAM,INPUT_FILE); CAPITALIZE_STRING(LABEL_NAME); CAPITALIZE_STRING(OPCODE); CAPITALIZE_STRING(ARGUMENTS); if (( strcmp(LABEL_NAME,"") || strcmp(OPCODE,"") || EXTENDED_CODE) && (SEEN_END_OP == END_SEEN_1) && strcmp(OPCODE,"CSECT") && strcmp(OPCODE,"START")) { (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[30]: Statements following END.\n"); SEEN_END_OP = END_SEEN_WITH_CODE_1; } if (strcmp(LABEL_NAME,"")) if ( LOOK_UP_SYMBOL(MODULE_NAME,LABEL_NAME,SYM_TABLE) == NULL) { CHANGE_LOCATION(&LOCATION_COUNTER,0,TEMP_OUTPUT_STREAM); if (!LOCATION_EXCEEDS_MEM_SIZE) (void) INSERT_IN_SYM_TAB(MODULE_NAME,LABEL_NAME,LOCATION_COUNTER, RELATIVE,SYM_TABLE); } else (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[6]: %s is a multipy defined label.\n", LABEL_NAME); if (strcmp(OPCODE,"")) { /* --------- Have an OPERATOR. Change location counter depending on format. */ struct OP_ENTRY *OPCODE_INFO; switch ( (*(OPCODE_INFO = LOOK_UP_OP(OPCODE))).FORMAT) { case NOT_FOUND: (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[9]: %s is not a legal OPCODE.\n",OPCODE); break; case ONE: CHANGE_LOCATION(&LOCATION_COUNTER,1,TEMP_OUTPUT_STREAM); if (EXTENDED_CODE) (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[8]: + is an illegal prefix to %s.",OPCODE); break; case TWO: CHANGE_LOCATION(&LOCATION_COUNTER,2,TEMP_OUTPUT_STREAM); if (EXTENDED_CODE) (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[8]: + is an illegal prefix to %s.",OPCODE); break; case THREE_FOUR: if (EXTENDED_CODE) CHANGE_LOCATION(&LOCATION_COUNTER,4,TEMP_OUTPUT_STREAM); else CHANGE_LOCATION(&LOCATION_COUNTER,3,TEMP_OUTPUT_STREAM); break; case PSEUDO: if (EXTENDED_CODE) (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[8]: + is an illegal prefix to %s.",OPCODE); /* ************************************************************************* */ /* The following instruction calls the correct procedure to do what needs to */ /* be done for a particular pseudo operator. The operator table contains */ /* the pointer to the correct routine. */ DO_PSEUDO((*OPCODE_INFO).FUNCTION,LABEL_NAME,ARGUMENTS, &LOCATION_COUNTER,SYM_TABLE,TEMP_OUTPUT_STREAM); break; } } if ((SEEN_END_OP == START_OF_CODE_1) && (strcmp(OPCODE,"") || strcmp(LABEL_NAME,""))) { SEEN_END_OP = NO_END_SEEN_1; (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[35]: No START/CSECT found before statements.\n"); } } OUTPUT_BUFFER(&MOD_REC_BUF,TEMP_OUTPUT_STREAM,1); if (!SEEN_END_OP) (void) fprintf(TEMP_OUTPUT_STREAM, "eERROR[36]: End of File detected without an END statement.\n"); }