blob: 68f849623c858db0e60ab336281dc1986fd3de15 [file] [log] [blame]
/* %%%%%%%%%%%%%%%%%%%% (c) William Landi 1991 %%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/* Permission to use this code is granted as long as the copyright */
/* notice remains in place. */
/* ============================ pass2.c =================================== */
/* Drives the pass2 process, but lets other routines do the real work. */
#include <stdio.h>
#include <string.h>
#include "stringI.h"
#include "scan_line.h"
#include "convert.h"
#include "sym_tab.h"
#include "record.h"
#include "assem.h"
#include "constants.h"
#include "buffer.h"
#include "code.h"
/* -------------------------- PASS2 ---------------------------------------- */
/* Drives pass2 */
void PASS2(FILE *INPUT_STREAM,FILE *OBJECT_STREAM,FILE *LISTING_STREAM,
SYMBOL_TABLE *SYM_TAB,int *ERROR)
{
char TAG_FIELD; /* First character to each line of */
/* output is TAG determining what */
/* information that line contains. */
char *REST_OF_LINE; /* Input line minus the tag field. */
struct SYMBOL_TABLE_ENTRY *TABLE_ENTRY;
/* Entry in symbol table for a label */
char LABEL_NAME[LABEL_SIZE_1+1]; /* Place to store a label. */
int ERROR_SINCE_LAST_STATEMENT /* Flag for error detection */
= FALSE_1;
/* --------------------------- Reset module name and NEXT_MISSING_LABEL */
/* to their values at the start of pass1 */
MODULE_NAME[0] = '_';
MODULE_NAME[1] = '\0';
RESET_MISSING_LABEL_NAME();
INITIALIZE_TEXT_RECORD();
while (!feof(INPUT_STREAM)) {
TAG_FIELD = (char) getc(INPUT_STREAM);
switch (TAG_FIELD) {
case 'p':
/* what follows is straight from the source file. Assemble it. */
if (ERROR_SINCE_LAST_STATEMENT) (void) fprintf(LISTING_STREAM,"\n");
ERROR_SINCE_LAST_STATEMENT = FALSE_1;
CODE(INPUT_STREAM,SYM_TAB,OBJECT_STREAM,LISTING_STREAM,
&ERROR_SINCE_LAST_STATEMENT);
(*ERROR) = ((*ERROR) || ERROR_SINCE_LAST_STATEMENT);
OUTPUT_BUFFER(&ERROR_REC_BUF,LISTING_STREAM,2);
break;
case 'e':
/* What follows is an error message from pass1. Pass it to listing file. */
ERROR_SINCE_LAST_STATEMENT = TRUE_1;
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
(void) fprintf(LISTING_STREAM,"%s\n",REST_OF_LINE);
(*ERROR) = TRUE_1;
break;
case 't':
{
/* What follows is a text record (do to BYTE or WORD) generated in pass1 */
/* Handle approperiately. (i.e. Let the text record handler deal with it). */
char TEMP_CH;
int LOCATION;
(void) fscanf(INPUT_STREAM,"%d%c",&LOCATION,&TEMP_CH);
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
if ( TEMP_CH == 'W')
ADD_TO_TEXT_RECORD(REST_OF_LINE,LOCATION,OBJECT_STREAM);
else {
char TEMP[HEX_CHAR_PER_BYTE_1+1];
int DELTA = 0;
for (TEMP[HEX_CHAR_PER_BYTE_1]='\0';!eoln(*REST_OF_LINE);
REST_OF_LINE+=HEX_CHAR_PER_BYTE_1) {
(void) strncpy(TEMP,REST_OF_LINE,HEX_CHAR_PER_BYTE_1);
ADD_TO_TEXT_RECORD(TEMP,(LOCATION+DELTA),OBJECT_STREAM);
DELTA ++;
}
}
}
break;
case 'E':
/* What follows is an end record... pass it and the 'E' to the object file */
/* After printing any text records and modification records that may be */
/* buffered. */
PRT_TEXT_RECORD(OBJECT_STREAM);
INITIALIZE_TEXT_RECORD();
OUTPUT_BUFFER(&MOD_REC_BUF,OBJECT_STREAM,2);
if (!strcmp(MAIN_ROUTINE,MODULE_NAME)) {
char ADDR[MEM_ADDR_SIZE_1/BITS_PER_HALFBYTE_1+2];
if (START_ADDRESS == -1)
START_ADDRESS = (*LOOK_UP_SYMBOL(MODULE_NAME,MODULE_NAME,
SYM_TAB)).LOCATION;
NUM_TO_STR(START_ADDRESS,16,MEM_ADDR_SIZE_1/BITS_PER_HALFBYTE_1+1,
ADDR);
(void) fprintf(OBJECT_STREAM,"E%s\n",ADDR);
} else (void) fprintf(OBJECT_STREAM,"E\n");
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
break;
case 'R':
/* What follows is a refer record. Pass it and the 'R' to the object file. */
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
(void) fprintf(OBJECT_STREAM,"%c%s\n",TAG_FIELD,REST_OF_LINE);
break;
case 'M':
/* What follows is a modification record. Put it on the modification record */
/* buffer. */
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
ADD_TO_END_OF_BUFFER(&MOD_REC_BUF,REST_OF_LINE);
break;
case 'd':
{
/* What follows is a define record. Pass1 didn't know the locations, just */
/* the names. It made sure that the the defs will fit in one record though, */
/* so here, must just put the locations after the names as output to the */
/* object file. */
char TEMP[LABEL_SIZE_1+1];
int AT;
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
(void) fprintf(OBJECT_STREAM,"D");
for (TEMP[LABEL_SIZE_1]='\0';!eoln(*REST_OF_LINE);
REST_OF_LINE+=LABEL_SIZE_1) {
(void) strncpy(TEMP,REST_OF_LINE,LABEL_SIZE_1);
(void) fprintf(OBJECT_STREAM,"%s",TEMP);
for (AT=LABEL_SIZE_1-1;((AT > 0) && (TEMP[AT] == ' '));AT--);
TEMP[AT+1] = '\0';
TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,TEMP,SYM_TAB);
if (TABLE_ENTRY == NULL) {
(void) fprintf(LISTING_STREAM,
"ERROR[41]: %s Undefined label in EXTDEF.\n",
TEMP);
(void) fprintf(OBJECT_STREAM,"000000");
(*ERROR) = 1;
} else if ((*TABLE_ENTRY).TYPE != RELATIVE) {
(void) fprintf(LISTING_STREAM,
"ERROR[42]: %s is wrong type. Expected LABEL, found EXTREF or CONSTANT.\n",
TEMP);
(void) fprintf(OBJECT_STREAM,"000000");
(*ERROR) = 1;
} else PRT_NUM( (*TABLE_ENTRY).LOCATION,16,6,OBJECT_STREAM);
}
(void) fprintf(OBJECT_STREAM,"\n");
}
break;
case 's':
/* what follows is a start record. Means must output a Header record to */
/* object file. */
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
BLANK_STR(LABEL_NAME);
(void) strncpy(LABEL_NAME,REST_OF_LINE,strlen(REST_OF_LINE));
(void) strcpy(MODULE_NAME,REST_OF_LINE);
(void) fprintf(OBJECT_STREAM,"H%s",LABEL_NAME);
TABLE_ENTRY = LOOK_UP_SYMBOL(REST_OF_LINE,REST_OF_LINE,SYM_TAB);
PRT_NUM((*TABLE_ENTRY).LOCATION,16,6,OBJECT_STREAM);
PRT_NUM((*TABLE_ENTRY).LENGTH,16,6,OBJECT_STREAM);
(void) fprintf(OBJECT_STREAM,"\n");
break;
default:
/* Something put out by pass1 that shouldn't be here. */
if (!feof(INPUT_STREAM)) {
GET_LINE(&REST_OF_LINE,INPUT_STREAM);
(void) printf(
"TEMP FILE build incorrectly. This should never happen.\n");
(void) printf("%c%s\n",TAG_FIELD,REST_OF_LINE);
}
break;
} /* END switch (TAG_FIELD) */
} /* END while (!feof(INPUT_STREAM)) */
PRT_TEXT_RECORD(OBJECT_STREAM);
}