JAM_RETURN_TYPE jam_init_stack(void) /* */ /* Description: Initialize the stack. The stack is located after the */ /* symbol table in the workspace buffer. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int size = 0; JAM_RETURN_TYPE return_code = JAMC_SUCCESS; void **symbol_table = NULL; if (jam_workspace != NULL) { symbol_table = (void **) jam_workspace; jam_stack = (JAMS_STACK_RECORD *) &symbol_table[JAMC_MAX_SYMBOL_COUNT]; size = (JAMC_MAX_SYMBOL_COUNT * sizeof(void *)) + (JAMC_MAX_NESTING_DEPTH * sizeof(JAMS_STACK_RECORD)); if (jam_workspace_size < size) { return_code = JAMC_OUT_OF_MEMORY; } } else { jam_stack = jam_malloc( JAMC_MAX_NESTING_DEPTH * sizeof(JAMS_STACK_RECORD)); if (jam_stack == NULL) { return_code = JAMC_OUT_OF_MEMORY; } } if (return_code == JAMC_SUCCESS) { for (index = 0; index < JAMC_MAX_NESTING_DEPTH; ++index) { jam_stack[index].type = JAM_ILLEGAL_STACK_TYPE; jam_stack[index].iterator = (JAMS_SYMBOL_RECORD *) 0; jam_stack[index].for_position = 0L; jam_stack[index].stop_value = 0L; jam_stack[index].step_value = 0L; jam_stack[index].push_value = 0L; jam_stack[index].return_position = 0L; } } return (return_code); }
JAM_RETURN_TYPE jam_init_symbol_table() /* */ /* Description: Initializes the symbol table. The symbol table is */ /* located at the beginning of the workspace buffer. */ /* */ /* Returns: JAMC_SUCCESS for success, or JAMC_OUT_OF_MEMORY if the */ /* size of the workspace buffer is too small to hold the */ /* desired number of symbol records. */ /* */ /****************************************************************************/ { int index = 0; JAM_RETURN_TYPE status = JAMC_SUCCESS; if (jam_workspace != NULL) { jam_symbol_table = (JAMS_SYMBOL_RECORD **) jam_workspace; jam_symbol_bottom = (void *) (((long)jam_workspace) + ((long)jam_workspace_size)); if (jam_workspace_size < (JAMC_MAX_SYMBOL_COUNT * sizeof(void *))) { status = JAMC_OUT_OF_MEMORY; } } else { jam_symbol_table = (JAMS_SYMBOL_RECORD **) jam_malloc( (JAMC_MAX_SYMBOL_COUNT * sizeof(void *))); if (jam_symbol_table == NULL) { status = JAMC_OUT_OF_MEMORY; } } if (status == JAMC_SUCCESS) { for (index = 0; index < JAMC_MAX_SYMBOL_COUNT; ++index) { jam_symbol_table[index] = NULL; } } return (status); }
JAM_RETURN_TYPE jam_add_symbol ( JAME_SYMBOL_TYPE type, char *name, long value, long position ) /* */ /* Description: Adds a new symbol to the symbol table. If the symbol */ /* name already exists in the symbol table, it is an error */ /* unless the symbol type and the position in the file */ /* where the symbol was declared are identical. This is */ /* necessary to allow labels and variable declarations */ /* inside loops and subroutines where they may be */ /* encountered multiple times. */ /* */ /* Returns: JAMC_SUCCESS for success, or JAMC_REDEFINED_SYMBOL */ /* if symbol was already declared elsewhere, or */ /* JAMC_OUT_OF_MEMORY if symbol table is full. */ /* */ /****************************************************************************/ { char r, l; int ch_index = 0; int hash = 0; long init_list_value = 0L; BOOL match = FALSE; BOOL identical_redeclaration = FALSE; JAM_RETURN_TYPE status = JAMC_SUCCESS; JAMS_SYMBOL_RECORD *symbol_record = NULL; JAMS_SYMBOL_RECORD *prev_symbol_record = NULL; /* * Check for legal characters in name, and legal name length */ while (name[ch_index] != JAMC_NULL_CHAR) { if (!jam_is_name_char(name[ch_index++])) status = JAMC_ILLEGAL_SYMBOL; } if ((ch_index == 0) || (ch_index > JAMC_MAX_NAME_LENGTH)) { status = JAMC_ILLEGAL_SYMBOL; } /* * Get hash key for this name */ hash = jam_hash(name); /* * Get pointer to first symbol record corresponding to this hash key */ symbol_record = jam_symbol_table[hash]; /* * Then check for duplicate entry in symbol table */ while ((status == JAMC_SUCCESS) && (symbol_record != NULL) && (!identical_redeclaration)) { match = TRUE; ch_index = 0; do { r = symbol_record->name[ch_index]; l = name[ch_index]; match = (r == l); ++ch_index; } while (match && (r != '\0') && (l != '\0')); if (match) { /* * Check if symbol was already declared identically * (same name, type, and source position) */ if ((symbol_record->position == position) && (jam_phase == JAM_DATA_PHASE)) { if ((type == JAM_INTEGER_ARRAY_WRITABLE) && (symbol_record->type == JAM_INTEGER_ARRAY_INITIALIZED)) { type = JAM_INTEGER_ARRAY_INITIALIZED; } if ((type == JAM_BOOLEAN_ARRAY_WRITABLE) && (symbol_record->type == JAM_BOOLEAN_ARRAY_INITIALIZED)) { type = JAM_BOOLEAN_ARRAY_INITIALIZED; } } if ((symbol_record->type == type) && (symbol_record->position == position)) { /* * For identical redeclaration, simply assign the value */ identical_redeclaration = TRUE; if (jam_version != 2) { symbol_record->value = value; } else { if ((type != JAM_PROCEDURE_BLOCK) && (type != JAM_DATA_BLOCK) && (jam_current_block != NULL) && (jam_current_block->type == JAM_PROCEDURE_BLOCK)) { symbol_record->value = value; } } } else { status = JAMC_REDEFINED_SYMBOL; } } prev_symbol_record = symbol_record; symbol_record = symbol_record->next; } /* * If no duplicate entry found, add the symbol */ if ((status == JAMC_SUCCESS) && (symbol_record == NULL) && (!identical_redeclaration)) { /* * Check initialization list -- if matching name is found, * override the initialization value with the new value */ if (((type == JAM_INTEGER_SYMBOL) || (type == JAM_BOOLEAN_SYMBOL)) && (jam_init_list != NULL)) { if ((jam_version != 2) && jam_check_init_list(name, &init_list_value)) { /* value was found -- override old value */ value = init_list_value; } } /* * Add the symbol */ if (jam_workspace != NULL) { jam_symbol_bottom = (void *) (((long)jam_symbol_bottom) - sizeof(JAMS_SYMBOL_RECORD)); symbol_record = (JAMS_SYMBOL_RECORD *) jam_symbol_bottom; if ((long)jam_heap_top > (long)jam_symbol_bottom) { status = JAMC_OUT_OF_MEMORY; } } else { symbol_record = (JAMS_SYMBOL_RECORD *) jam_malloc(sizeof(JAMS_SYMBOL_RECORD)); if (symbol_record == NULL) { status = JAMC_OUT_OF_MEMORY; } } if (status == JAMC_SUCCESS) { symbol_record->type = type; symbol_record->value = value; symbol_record->position = position; symbol_record->parent = jam_current_block; symbol_record->next = NULL; if (prev_symbol_record == NULL) { jam_symbol_table[hash] = symbol_record; } else { prev_symbol_record->next = symbol_record; } ch_index = 0; while ((ch_index < JAMC_MAX_NAME_LENGTH) && (name[ch_index] != '\0')) { symbol_record->name[ch_index] = name[ch_index]; ++ch_index; } symbol_record->name[ch_index] = '\0'; } } return (status); }