blob: f2746b67ff4d9f5d8f3360f26c4b1ee2d57c9803 [file] [log] [blame]
/* %%%%%%%%%%%%%%%%%%%% (c) William Landi 1991 %%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/* Permission to use this code is granted as long as the copyright */
/* notice remains in place. */
/* ============================== pass1.c ================================== */
/* Drives pass1 of the assembler, but lets other routines do the real work */
#include <stdio.h>
#include <string.h>
#include "assem.h"
#include "scan_line.h"
#include "sym_tab.h"
#include "op_tab.h"
#include "convert.h"
#include "buffer.h"
#include "constants.h"
#include "pseudo.h"
#define START_LEGAL_1 0 /* = May see a START legally */
#define SEEN_START_1 1 /* = Have seen a START */
/* SEND_START_OP Global that contains whether or not */
/* a START operator has been seen */
int SEEN_START_OP = START_LEGAL_1;
#define NO_END_SEEN_1 0 /* = Haven't seen an END */
#define END_SEEN_1 1 /* = Have seen an END but haven't */
/* found any code after it */
#define END_SEEN_WITH_CODE_1 2 /* = Have seen an END and code after it */
#define START_OF_CODE_1 3 /* = Start of code */
/* SEEN_END_OP Flag to determine if seen an end since */
/* start of last module or not. If so it */
/* also indicated if any code seen since */
/* end (so only one 'code after end' error */
/* is generated. */
int SEEN_END_OP = START_OF_CODE_1;
/* LOCATION_EXCEEDS_MEM_SIZE Indicates if location counter is greater*/
/* then the memory size. */
int LOCATION_EXCEEDS_MEM_SIZE = FALSE_1;
/* -------------------------- CHANGE_LOCATION ------------------------------ */
/* LOCATION = LOCATION + INCREMENT unless this puts LOCATION past MEM_SIZE, */
/* or if the location has already exceeded the memory size. */
void CHANGE_LOCATION(int *LOCATION,int INCREMENT,FILE *OUTPUT)
{
if (!LOCATION_EXCEEDS_MEM_SIZE)
if ( ((*LOCATION + INCREMENT) > MEM_SIZE_1) || (*LOCATION == MEM_SIZE_1))
{
LOCATION_EXCEEDS_MEM_SIZE = TRUE_1;
(void) fprintf(OUTPUT,
"eERROR[12]: Location exceeds the memory size (%d)\n",
MEM_SIZE_1);
(*LOCATION) = MEM_SIZE_1 - 1;
} else (*LOCATION) += INCREMENT;
}
/* ---------------------- CAPITALIZE_STRING -------------------------------- */
/* Make all lower case letters in the string STR upper case letters */
void CAPITALIZE_STRING(char STR[])
{
int I;
for (I=0; I<= (strlen(STR)); I++)
if ((STR[I] >= 'a') && (STR[I] <= 'z'))
STR[I] = STR[I] - 'a' + 'A';
}
/* --------------------------- PASS1 --------------------------------------- */
/* 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");
}