| home
| contents
| previous
| next page
| send comment
| send link
| add bookmark |
PRS_EMIT.CPP
intermediate code
/*-------------------------------------------------------------------*
Interpreter statement emitter
File: prs_emit.cpp
Module: parser
by: Stephen R. Schmitt
*-------------------------------------------------------------------*/
#include "tpl_data.h"
#include <assert.h>
#include <alloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* External variables
*/
/* in tpl_main.cpp */
extern bool Debug_flag;
#ifdef DEBUG
extern FILE *c_out, *d_out;
#endif
/* in sym_tabl.cpp */
extern TYPE_STRUCT_PTR Integer_typep, Real_typep,
Boolean_typep, Char_typep,
String_typep, Null_typep;
/* in exc_main.cpp */
extern bool Routine_flag;
extern MEMORY_PTR *CSeg;
extern MEMORY_PTR DSeg;
/*
* Global declarations
*/
int CI;
int TI;
int Routine_number;
int Data_item;
MEMORY_PTR Code_buffer;
MEMORY_PTR Temp_buffer;
int Code_label[MAX_LABELS];
int Label_count;
/*-------------------------------------------------------------------*
Code Section
*-------------------------------------------------------------------*/
/*
* "init_emit" creates code buffers and sets code index
* values to starting values
*
* returns: nothing
*/
void init_emit()
{
Routine_number = 2; // main->0, program->1
Data_item = 1;
Code_buffer = new MEMORY[MAX_CODE_SIZE];
if (Code_buffer == NULL)
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
Temp_buffer = new MEMORY[MAX_DATA_SIZE];
if (Temp_buffer == NULL)
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
CSeg = new MEMORY_PTR[MAX_CODE_SEGMENTS];
if (CSeg == NULL)
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
DSeg = new MEMORY[MAX_DATA_SIZE];
if (DSeg == NULL)
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
else
memset(DSeg, '\0', MAX_DATA_SIZE * sizeof(MEMORY));
init_code_segment();
}
/*
* "init_code_segment" resets counters and clears label list
*
* returns: nothing
*/
void init_code_segment()
{
CI = 0;
Label_count = 0;
for (int i = 0; i < MAX_LABELS; i++)
Code_label[i] = 0;
}
/*
* "exit_emit" deletes code buffers
*
* returns: nothing
*/
void exit_emit()
{
assert(Code_buffer != NULL);
delete Code_buffer;
assert(Temp_buffer != NULL);
delete Temp_buffer;
}
/*
* "emit_code_segment" copies a code buffer into a code segment
*
* returns: index number of the segment
*/
void emit_code_segment(SYMTAB_NODE_PTR idp) // of subroutine
{
int i, j, n;
int number = idp->routine.segment;
SYMTAB_NODE_PTR rtne_idp = idp;
if (Routine_flag) // in subprogram
{
Temp_buffer[0].op.code1 = PUSH;
Temp_buffer[0].op.code2 = REG_BP;
Temp_buffer[1].op.code1 = MOV_bp_sp;
n = idp->routine.parm_count; // number of formals
for (i = 0; i < n; i++) // find last formal parm
idp = idp->next;
TI = 2; // initialize
idp = idp->next; // first local
while (idp != NULL) // push onto stack
{
emit_alloc_data(idp); // increment TI
idp = idp->next;
}
CSeg[number] = new MEMORY[CI + TI + 1];
if (CSeg[number])
{
for (i = 0; i < TI; i++)
CSeg[number][i] = Temp_buffer[i];
fixup_code_buffer_addresses(TI);
for (j = 0; j < CI; j++, i++)
CSeg[number][i] = Code_buffer[j];
CSeg[number][CI + TI].op.code1 = NO_CODE;
}
else
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
}
else // in main program
{
CSeg[number] = new MEMORY[CI + 1];
if (CSeg[number])
{
for (i = 0; i < CI; i++)
CSeg[number][i] = Code_buffer[i];
CSeg[number][CI].op.code1 = NO_CODE;
}
else
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
}
D(fprintf(c_out, "%d items of size %d bytes\n", (CI + TI), sizeof(MEMORY)));
init_code_segment();
idp = rtne_idp; // prevent warning
#ifdef DEBUG
list_segment(idp);
#endif
}
/*
* "fixup_code_buffer_addresses" changes label values to offsets
*
* returns: nothing
*/
void fixup_code_buffer_addresses(int ti)
{
int iptr = 0;
int index;
OPCODE op = Code_buffer[iptr].op.code1; // first instruction
while (iptr < CI) // end of segment
{
switch (op)
{
case STATEMENT:
iptr++;
break;
case PUSH:
op = Code_buffer[iptr].op.code2;
switch (op)
{
case IMM_64:
case IMM_32:
case IMM_16:
case IMM_8:
case IMM_STR:
iptr++;
break;
}
break;
case JMP:
case JNZ:
case JZ:
index = Code_buffer[iptr].op.offset;
Code_buffer[iptr].op.offset = Code_label[index] + ti;
break;
}
iptr++;
op = Code_buffer[iptr].op.code1;
}
}
/*
* "emit_pop_local_parm" emits code to pop local parameters on return
* from a declared program, procedure, or function. Local parameters
* follow formal parameters.
*
* returns: nothing
*/
void emit_pop_local_parm(SYMTAB_NODE_PTR idp) // of subroutine
{
SYMTAB_NODE_PTR last_idp;
int n = idp->routine.parm_count; // number of formals
int m = -1; // init count
while (idp != NULL) // when end of chain found
{
last_idp = idp; // save last idp
idp = idp->next;
m++; // count total
}
m -= n; // number of locals
idp = last_idp; // pop last one first
for (int i = 0; i < m; i++)
{
delete_data(idp);
idp = idp->prev; // pop in reverse order
}
}
/*
* "emit_pop_formal_parm" emits code to pop formal parameters on
* return from a declared procedure or function. The first n
* parameters after the subroutine idp are formal parameters.
*
* returns: nothing
*/
void emit_pop_formal_parm(SYMTAB_NODE_PTR idp)
{
int n, i;
n = idp->routine.parm_count; // number of formals
for (i = 0; i < n; i++) // find last formal parm
idp = idp->next;
for (i = 0; i < n; i++) // pop from last to first
{
delete_data(idp);
idp = idp->prev;
}
}
/*
* "emit_operator" generates code item
*
* returns: nothing
*/
void emit_operator(OPCODE code1, OPCODE code2, int segment, int offset)
{
if (CI > MAX_CODE_SIZE)
runtime_error(M_CODE, M_SEGMENT, M_OVERFLOW, M_0);
else
{
Code_buffer[CI].op.code1 = code1;
Code_buffer[CI].op.code2 = code2;
Code_buffer[CI].op.segment = segment;
Code_buffer[CI].op.offset = offset;
CI++;
}
}
/*
* "emit_op_reg_imm" generates code for an immediate register operation.
*
* returns: nothing
*/
void emit_op_reg_imm(OPCODE code, int value)
{
assert(code == ADD_xi_imm || code == MOV_ax_imm || code == MOV_bx_imm);
emit_operator(code, NO_CODE, 0, value);
}
/*
* "emit_index" adds index value to code segment
*
* returns: nothing
*/
void emit_index(int value) // to insert
{
if (CI > MAX_CODE_SIZE)
runtime_error(M_CODE, M_SEGMENT, M_OVERFLOW, M_0);
else
{
Code_buffer[CI].index = value;
CI++;
}
}
/*
* "emit_char" adds a character to code segment
*
* returns: nothing
*/
void emit_char(char value) // to insert
{
if (CI > MAX_CODE_SIZE)
runtime_error(M_CODE, M_SEGMENT, M_OVERFLOW, M_0);
else
{
Code_buffer[CI].byte = value;
CI++;
}
}
/*
* "emit_integer" adds an integer value to code segment
*
* returns: nothing
*/
void emit_integer(long value) // to insert
{
if (CI > MAX_CODE_SIZE)
runtime_error(M_CODE, M_SEGMENT, M_OVERFLOW, M_0);
else
{
Code_buffer[CI].integer = value;
CI++;
}
}
/*
* "emit_real" adds real number value to code segment
*
* returns: nothing
*/
void emit_real(double value) // to insert
{
if (CI > MAX_CODE_SIZE)
runtime_error(M_CODE, M_SEGMENT, M_OVERFLOW, M_0);
else
{
Code_buffer[CI].real = value;
CI++;
}
}
/*
* "emit_string" adds a string to the code segment.
*
* returns: nothing
*/
void emit_string(char *value) // to insert
{
int length = strlen(value);
if (CI > MAX_CODE_SIZE - 1)
runtime_error(M_CODE, M_SEGMENT, M_OVERFLOW, M_0);
else
{
char *p = new char[length + 1];
if (p)
{
Code_buffer[CI].string.ptr = p;
Code_buffer[CI].string.len = length;
Code_buffer[CI].string.sig = SIGNATURE;
strcpy(Code_buffer[CI].string.ptr, value);
}
else
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
CI++;
}
}
/*
* "emit_code_label" adds a label offset value to the code segment
* label list. The offset value is the current location of
* the code index.
*
* returns: nothing
*/
void emit_code_label(int number) // label number
{
assert(number < MAX_LABELS);
Code_label[number] = CI; // assign code index
}
/*
* "next_code_label" returns the next label number.
*
* returns: label number
*/
int next_code_label()
{
Label_count++;
if (Label_count > MAX_LABELS)
compile_error(M_TOO, M_MANY, M_LABELS, M_0);
return Label_count;
}
/*
* "emit_statement_marker" inserts debugging code to locate the
* current source line.
*
* returns: nothing
*/
void emit_statement_marker(char *file, // source file name
int line) // source line number
{
if (Debug_flag) // only in debug mode
{
emit_operator(STATEMENT, NO_CODE, 0, line);
emit_string(file);
}
}
/*
* "emit_push_imm_char" generates code to push a character
* onto the runtime stack.
*
* returns: nothing
*/
void emit_push_imm_char(char value) // value to push
{
emit_operator(PUSH, IMM_8, 0, 0);
emit_char(value);
}
/*
* "emit_push_imm_index" generates code to push an index value
* onto the runtime stack.
*
* returns: nothing
*/
void emit_push_imm_index(int value) // value to push
{
emit_operator(PUSH, IMM_16, 0, 0);
emit_index(value);
}
/*
* "emit_push_imm_integer" generates code to push an integer onto the
* runtime stack.
*
* returns: nothing
*/
void emit_push_imm_integer(long value) // value to push
{
emit_operator(PUSH, IMM_32, 0, 0);
emit_integer(value);
}
/*
* "emit_push_imm_real" generates code to push a real value
* onto the runtime stack.
*
* returns: nothing
*/
void emit_push_imm_real(double value) // value to push
{
emit_operator(PUSH, IMM_64, 0, 0);
emit_real(value);
}
/*
* "emit_push_imm_string" generates code to push a string onto the
* runtime stack.
*
* returns: nothing
*/
void emit_push_imm_string(char *value) // value to push
{
emit_operator(PUSH, IMM_STR, 0, 0);
emit_string(value);
}
/*
* "emit_push_address" generates code to push an address
* onto the runtime stack.
*
* returns: nothing
*/
void emit_push_address(SYMTAB_NODE_PTR idp) // of item
{
int offset = find_offset(idp);
int segment = find_segment(idp);
if (idp->definition == VARPARM_DEFN)
emit_operator(PUSH, ADDR_ADDR, segment, offset);
else
emit_operator(PUSH, ADDR, segment, offset);
}
/*
* "emit_mem_item" generates code to push or pop a declared item
* onto or from the runtime stack.
*
* returns: nothing
*/
void emit_mem_item(OPCODE code1, // push or pop
SYMTAB_NODE_PTR mem_idp, // of id
TYPE_STRUCT_PTR mem_tp) // of item
{
OPCODE code2;
TYPE_STRUCT_PTR tp = mem_idp->typep;
if (tp == Null_typep) // source code error
code2 = NO_CODE;
else if (tp == Real_typep)
code2 = MEM_64;
else if (tp == Integer_typep)
code2 = MEM_32;
else if ((tp == Boolean_typep)||(tp->form == ENUM_FORM))
code2 = MEM_16;
else if (tp == Char_typep)
code2 = MEM_8;
else if (tp->form == STRING_FORM)
{
if (mem_tp == Char_typep)
code2 = MEM_STR_8_xi;
else
code2 = MEM_STR;
}
else if ((tp->form == ARRAY_FORM )||
(tp->form == RECORD_FORM)||
(tp->form == UNION_FORM ))
{
if (mem_tp == Null_typep) // source code error
code2 = NO_CODE;
else if (mem_tp == Real_typep)
code2 = MEM_64_xi;
else if (mem_tp == Integer_typep)
code2 = MEM_32_xi;
else if ((mem_tp == Boolean_typep )||
(mem_tp->form == ENUM_FORM))
code2 = MEM_16_xi;
else if (mem_tp == Char_typep)
code2 = MEM_8_xi;
else if (mem_tp->form == STRING_FORM)
code2 = MEM_STR_xi;
else
assert(0);
}
else
assert(0);
int offset = find_offset(mem_idp);
int segment = find_segment(mem_idp);
emit_operator(code1, code2, segment, offset);
}
/*
* "emit_var_item" generates code to push or pop a var parameter
* onto or from the runtime stack
*
* returns: nothing
*/
void emit_var_item(OPCODE code1, // push or pop
SYMTAB_NODE_PTR var_idp, // of id
TYPE_STRUCT_PTR var_tp ) // of item
{
OPCODE code2;
TYPE_STRUCT_PTR tp = var_idp->typep;
if (tp == Null_typep) // source code error
code2 = NO_CODE;
else if (tp == Real_typep)
code2 = PTR_64;
else if (tp == Integer_typep)
code2 = PTR_32;
else if ((tp == Boolean_typep)||(tp->form == ENUM_FORM))
code2 = PTR_16;
else if (tp == Char_typep)
code2 = PTR_8;
else if (tp->form == STRING_FORM)
{
if (var_tp == Char_typep)
code2 = PTR_STR_8_xi;
else
code2 = PTR_STR;
}
else if ((tp->form == ARRAY_FORM )||
(tp->form == RECORD_FORM)||
(tp->form == UNION_FORM ))
{
if (var_tp == Null_typep) // source code error
code2 = NO_CODE;
else if (var_tp == Real_typep)
code2 = PTR_64_xi;
else if (var_tp == Integer_typep)
code2 = PTR_32_xi;
else if ((var_tp == Boolean_typep)||(var_tp->form == ENUM_FORM))
code2 = PTR_16_xi;
else if (var_tp == Char_typep)
code2 = PTR_8_xi;
else if (var_tp->form == STRING_FORM)
code2 = PTR_STR_xi;
else
assert(0);
}
else
assert(0);
int offset = find_offset(var_idp);
int segment = find_segment(var_idp);
emit_operator(code1, code2, segment, offset);
}
/*
* "emit_return_value" generates code to return a value from a
* function
*
* returns: nothing
*/
void emit_return_value(SYMTAB_NODE_PTR rtne_idp)
{
OPCODE code;
TYPE_STRUCT_PTR tp = rtne_idp->typep;
if (tp == Null_typep) // source code error
code = NO_CODE;
else if (tp == Real_typep)
code = MEM_64;
else if (tp == Integer_typep)
code = MEM_32;
else if ((tp == Boolean_typep)||(tp->form == ENUM_FORM))
code = MEM_16;
else if (tp == Char_typep)
code = MEM_8;
else if (tp->form == STRING_FORM)
code = MEM_STR;
else
assert(0);
int offset = - rtne_idp->routine.parm_count - 2;
emit_operator(POP, code, 1, offset);
}
/*
* "find_offset" obtains the offset address of a stack or data item
* Stack items are relative to the value of the base pointer. When
* a subrountine is called items are placed on the stack as shown:
*
* local2 SP = BP + 2
* local1 SP = BP + 1
* old BP SP = BP
* old SN, IP SP = BP - 1
* arg2 SP = BP - 2
* arg1 SP = BP - 3
* retval SP = BP - 4
*
* When declared, formal parameters precede locals in the chain of
* identifiers starting at the subroutine's
*
* returns: offset value
*/
int find_offset(SYMTAB_NODE_PTR item_idp) // of this item
{
SYMTAB_NODE_PTR idp;
int offset, parm_count;
// search backward until a routine idp is found
idp = item_idp;
while ((idp->definition != MAIN_DEFN)&&
(idp->definition != PROG_DEFN)&&
(idp->definition != PROC_DEFN)&&
(idp->definition != FUNC_DEFN))
idp = idp->prev;
parm_count = idp->routine.parm_count; // formal parameters
// count forward until the item's idp is found
idp = idp->next;
offset = 1;
while (idp != item_idp)
{
if (idp->definition == VARPARM_DEFN)
offset++;
else
offset += idp->typep->size;
idp = idp->next;
}
if (offset > parm_count) // is a local
offset = offset - parm_count;
else // is an argument
offset = offset - parm_count - 2;
return offset;
}
/*
* "find_segment" obtains the segment index number of the routine
* containing the stack or data item
*
* returns: segment index
*/
int find_segment(SYMTAB_NODE_PTR item_idp) // of this item
{
SYMTAB_NODE_PTR idp = item_idp->prev;
// search backward until a routine idp is found
while ((idp->definition != MAIN_DEFN) &&
(idp->definition != PROG_DEFN) &&
(idp->definition != PROC_DEFN) &&
(idp->definition != FUNC_DEFN))
idp = idp->prev;
return idp->routine.segment;
}
/*
* "emit_alloc_data" emits code to push data onto stack
*
* returns: nothing
*/
void emit_alloc_data(SYMTAB_NODE_PTR idp)
{
if (idp->typep->form == ARRAY_FORM)
emit_alloc_array(idp->typep);
else if (idp->typep->form == RECORD_FORM)
emit_alloc_record(idp->typep);
else if (idp->typep->form == UNION_FORM)
emit_alloc_union(idp->typep);
else if (idp->typep->form == STRING_FORM)
{
int length = idp->typep->array.max_index + 1; // zero based!
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp_string;
else
{
D(fprintf(d_out, "%4d %s:str\n", Data_item, idp->name));
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
char *p = new char[length + 1];
if (p)
{
DSeg[Data_item].string.ptr = p;
DSeg[Data_item].string.len = length;
DSeg[Data_item].string.sig = SIGNATURE;
}
else
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
Data_item++;
}
}
else
{
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp;
else
{
D(fprintf(d_out, "%4d %s\n", Data_item, idp->name));
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
Data_item++;
}
}
}
/*
* "emit_alloc_array" allocates memory for an array
*
* returns: next item number
*/
void emit_alloc_array(TYPE_STRUCT_PTR tp)
{
int index = 0;
TYPE_STRUCT_PTR elmt_tp = tp->array.elmt_typep;
assert(elmt_tp->size != 0);
int size = tp->size / elmt_tp->size;
while (size > 0)
{
D(if (!Routine_flag) fprintf(d_out, "%4d (%d)\n", Data_item, index));
if (elmt_tp->form == ARRAY_FORM)
emit_alloc_array(elmt_tp);
else if (elmt_tp->form == RECORD_FORM)
emit_alloc_record(elmt_tp);
else if (elmt_tp->form == UNION_FORM)
emit_alloc_union(elmt_tp);
else if (elmt_tp->form == STRING_FORM)
{
int length = elmt_tp->array.max_index + 1; // zero based!
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp_string;
else
{
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
char *p = new char[length + 1];
if (p)
{
DSeg[Data_item].string.ptr = p;
DSeg[Data_item].string.len = length;
DSeg[Data_item].string.sig = SIGNATURE;
}
else
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
Data_item++;
}
}
else
{
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp;
else
{
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
Data_item++;
}
}
index++;
size--;
}
}
/*
* "emit_alloc_record" allocates memory for a record
*
* returns: next item number
*/
void emit_alloc_record(TYPE_STRUCT_PTR tp)
{
SYMTAB_NODE_PTR item_idp = tp->record_struct.field_symtab;
while (item_idp != NULL)
{
D(if (!Routine_flag) fprintf(d_out, "%4d .%s\n", Data_item, item_idp->name));
if (item_idp->typep->form == ARRAY_FORM)
emit_alloc_array(item_idp->typep);
else if (item_idp->typep->form == RECORD_FORM)
emit_alloc_record(item_idp->typep);
else if (item_idp->typep->form == UNION_FORM)
emit_alloc_union(item_idp->typep);
else if (item_idp->typep->form == STRING_FORM)
{
int length = item_idp->typep->array.max_index + 1; // zero based
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp_string;
else
{
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
char *p = new char[length + 1];
if (p)
{
DSeg[Data_item].string.ptr = p;
DSeg[Data_item].string.len = length;
DSeg[Data_item].string.sig = SIGNATURE;
}
else
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
Data_item++;
}
}
else
{
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp;
else
{
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
Data_item++;
}
}
item_idp = item_idp->next;
}
}
/*
* "emit_alloc_union" allocates memory for a union
*
* returns: next item number
*/
void emit_alloc_union(TYPE_STRUCT_PTR tp)
{
SYMTAB_NODE_PTR item_idp = tp->union_struct.field_symtab;
while (item_idp != NULL)
{
D(if (!Routine_flag) fprintf(d_out, "%4d .%s\n", Data_item, item_idp->name));
if (item_idp->typep->form == ARRAY_FORM)
emit_alloc_array(item_idp->typep);
else if (item_idp->typep->form == RECORD_FORM)
emit_alloc_record(item_idp->typep);
else if (item_idp->typep->form == UNION_FORM)
emit_alloc_union(item_idp->typep);
else if (item_idp->typep->form == STRING_FORM)
{
int length = item_idp->typep->array.max_index + 1; // zero based!
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp_string;
else
{
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
char *p = new char[length + 1];
if (p)
{
DSeg[Data_item].string.ptr = p;
DSeg[Data_item].string.len = length;
DSeg[Data_item].string.sig = SIGNATURE;
}
else
runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
}
}
else
{
if (Routine_flag)
Temp_buffer[TI++].op.code1 = INC_sp;
else
{
if (Data_item > MAX_DATA_SIZE)
runtime_error(M_DATA, M_SEGMENT, M_OVERFLOW, M_0);
}
}
item_idp = item_idp->next;
}
Data_item++;
}
/*
* "delete_data" emits code to delete data from the stack
*
* returns: nothing
*/
void delete_data(SYMTAB_NODE_PTR idp)
{
if (idp->definition == VARPARM_DEFN)
emit_operator(DEC_sp, NO_CODE, 0, 0);
else if (idp->typep->form == ARRAY_FORM)
delete_array(idp->typep);
else if (idp->typep->form == RECORD_FORM)
delete_record(idp->typep);
else if (idp->typep->form == UNION_FORM)
delete_union(idp->typep);
else if (idp->typep->form == STRING_FORM)
emit_operator(DEC_sp_string, NO_CODE, 0, 0);
else
emit_operator(DEC_sp, NO_CODE, 0, 0);
}
/*
* "delete_array" de-allocates memory for an array
*
* returns: next item number
*/
void delete_array(TYPE_STRUCT_PTR tp)
{
TYPE_STRUCT_PTR elmt_tp = tp->array.elmt_typep;
int size = tp->size / elmt_tp->size;
while (size > 0)
{
if (elmt_tp->form == ARRAY_FORM)
delete_array(elmt_tp);
else if (elmt_tp->form == RECORD_FORM)
delete_record(elmt_tp);
else if (elmt_tp->form == UNION_FORM)
delete_union(elmt_tp);
else if (elmt_tp->form == STRING_FORM)
emit_operator(DEC_sp_string, NO_CODE, 0, 0);
else
emit_operator(DEC_sp, NO_CODE, 0, 0);
size--;
}
}
/*
* "delete_record" de-allocates memory for a record
*
* returns: next item number
*/
void delete_record(TYPE_STRUCT_PTR tp)
{
SYMTAB_NODE_PTR item_idp = tp->record_struct.field_symtab;
while (item_idp != NULL)
{
if (item_idp->typep->form == ARRAY_FORM)
delete_array(item_idp->typep);
else if (item_idp->typep->form == RECORD_FORM)
delete_record(item_idp->typep);
else if (item_idp->typep->form == UNION_FORM)
delete_union(item_idp->typep);
else if (item_idp->typep->form == STRING_FORM)
emit_operator(DEC_sp_string, NO_CODE, 0, 0);
else
emit_operator(DEC_sp, NO_CODE, 0, 0);
item_idp = item_idp->next;
}
}
/*
* "delete_union" de-allocates memory for a union
*
* returns: next item number
*/
void delete_union(TYPE_STRUCT_PTR tp)
{
SYMTAB_NODE_PTR item_idp = tp->union_struct.field_symtab;
while (item_idp != NULL)
{
if (item_idp->typep->form == ARRAY_FORM)
delete_array(item_idp->typep);
else if (item_idp->typep->form == RECORD_FORM)
delete_record(item_idp->typep);
else if (item_idp->typep->form == UNION_FORM)
delete_union(item_idp->typep);
else if (item_idp->typep->form == STRING_FORM)
emit_operator(DEC_sp_string, NO_CODE, 0, 0);
else
emit_operator(DEC_sp, NO_CODE, 0, 0);
item_idp = item_idp->next;
}
}
#ifdef DEBUG
/*
* array of strings must match enumerated opcodes defined
* in tpl_data.h
*/
char *Op[] = {
"NO_CODE", "STATEMENT", "EXITZ", "SKIP", "UNSKIP",
"PUSH", "POP", "REG_BP", "ADDR", "ADDR_ADDR",
"IMM_64", "IMM_32", "IMM_16", "IMM_8", "IMM_STR",
"MEM_64", "MEM_32", "MEM_16", "MEM_8", "MEM_STR",
"MEM_64_xi", "MEM_32_xi", "MEM_16_xi", "MEM_8_xi",
"MEM_STR_8_xi", "MEM_STR_xi",
"PTR_64", "PTR_32", "PTR_16", "PTR_8", "PTR_STR",
"PTR_64_xi", "PTR_32_xi", "PTR_16_xi", "PTR_8_xi",
"PTR_STR_8_xi", "PTR_STR_xi",
"INC_sp", "INC_sp_string", "DEC_sp", "DEC_sp_string",
"ADD_xi_offset", "ADD_xi_imm",
"MOV_ax_imm", "MOV_bx_imm",
"MOV_bp_sp",
"PUT_str", "GET_str", "GET_item",
"FORMAT_STR", "FORMAT_CHR", "FORMAT_INDEX",
"SET_file_ptr", "SET_stdin", "SET_stdout", "FLUSH_stdin",
"RMUL", "RDIV", "RADD", "RSUB", "RNEG", "RPOW",
"IMUL", "IDIV", "IADD", "ISUB", "INEG", "IPOW", "IMOD",
"STRCAT",
"TEST_INDEX", "TEST_NUMBER", "TEST_STRING", "TEST_CHAR",
"TEST_EQ", "TEST_NE", "TEST_GT", "TEST_GE", "TEST_LT", "TEST_LE",
"LOGIC_OR", "LOGIC_AND", "LOGIC_NOT",
"LOGIC_NOR", "LOGIC_NAND", "LOGIC_XOR",
"JMP", "JNZ", "JZ",
"CALL", "RETF", "CALL_stnd", "RETP",
"SF_ARCCOS", "SF_ARCSIN", "SF_ARCTAN", "SF_COS", "SF_COSH",
"SP_CURSOR", "SF_GETKEY",
"SF_EXP", "SF_GETEXP", "SF_LN", "SF_LOG2", "SF_LOG10",
"SF_SIN", "SF_SINH", "SF_SQRT",
"SF_TAN", "SF_TANH",
"SF_ABS", "SF_ARCTANXY",
"SF_CEIL", "SF_FLOOR", "SF_ROUND", "SF_SIGN",
"SF_CHR", "SF_CLOSE", "SF_EOFF",
"SF_EREALSTR", "SF_FREALSTR",
"SF_INDEX", "SF_INTREAL", "SF_INTSTR", "SF_LENGTH", "SP_LOCATE",
"SF_ORD", "SF_MAX", "SF_MIN", "SF_OPEN",
"SP_PUTCH", "SP_PUTSTR", "SP_PUTLINE", "SP_PUTPIXEL",
"SF_PRED", "SF_SUCC",
"SF_RAND", "SF_RANDINT", "SP_RANDOMIZE", "SP_RANDSEED",
"SF_REALSTR", "SF_REPEAT",
"SP_SCROLL", "SF_SETEXP", "SP_SETVIDEO", "SF_STRINT", "SF_STRREAL",
"SF_VIDEOMODE", "SF_VIDEOTYPE",
"SP_WATCH"
};
/*
* "list_segment" decodes instructions for debugging
*
* returns: nothing
*/
void list_segment(SYMTAB_NODE_PTR idp)
{
char byte;
int snum, iptr = 0;
int segment, offset, index;
long integer;
double real;
char string[64];
OPCODE op;
snum = idp->routine.segment;
fprintf(c_out, "begin: \"%s\" cseg: %d\n", idp->name, snum);
op = CSeg[snum][iptr].op.code1; // first instruction
while (op != NO_CODE) // end of segment
{
fprintf(c_out, "%3d ", iptr); // item
switch (op)
{
case STATEMENT:
index = CSeg[snum][iptr].op.offset;
iptr++;
strcpy(string, CSeg[snum][iptr].string.ptr);
fprintf(c_out,
"%s file: %s line: %d\n",
Op[op], string, index);
break;
case PUSH:
fprintf(c_out, "%s ", Op[op]);
op = CSeg[snum][iptr].op.code2;
switch (op)
{
case REG_BP:
fprintf(c_out, "%s\n", Op[op]);
break;
case IMM_64:
iptr++;
real = CSeg[snum][iptr].real;
fprintf(c_out, "%s val: %lg\n", Op[op], real);
break;
case IMM_32:
iptr++;
integer = CSeg[snum][iptr].integer;
fprintf(c_out, "%s val: %ld\n", Op[op], integer);
break;
case IMM_16:
iptr++;
index = CSeg[snum][iptr].index;
fprintf(c_out, "%s val: %d\n", Op[op], index);
break;
case IMM_8:
iptr++;
byte = CSeg[snum][iptr].byte;
fprintf(c_out, "%s val: %c\n", Op[op], byte);
break;
case IMM_STR:
iptr++;
index = CSeg[snum][iptr].string.len;
strcpy(string, CSeg[snum][iptr].string.ptr);
if (string[0] == '\n') string[0] = 25;
fprintf(c_out, "%s len: %d str: %s\n", Op[op], index, string);
break;
case ADDR:
case ADDR_ADDR:
case MEM_64:
case MEM_32:
case MEM_16:
case MEM_8:
case MEM_STR:
case MEM_64_xi:
case MEM_32_xi:
case MEM_16_xi:
case MEM_8_xi:
case MEM_STR_8_xi:
case MEM_STR_xi:
case PTR_64:
case PTR_32:
case PTR_16:
case PTR_8:
case PTR_STR:
case PTR_64_xi:
case PTR_32_xi:
case PTR_16_xi:
case PTR_8_xi:
case PTR_STR_8_xi:
case PTR_STR_xi:
segment = CSeg[snum][iptr].op.segment;
offset = CSeg[snum][iptr].op.offset;
fprintf(c_out, "%s dseg: %d off: %d\n", Op[op], segment, offset);
break;
}
break;
case POP:
fprintf(c_out, "%s ", Op[op]);
op = CSeg[snum][iptr].op.code2;
switch (op)
{
case REG_BP:
fprintf(c_out, "%s\n", Op[op]);
break;
case MEM_64:
case MEM_32:
case MEM_16:
case MEM_8:
case MEM_STR:
case MEM_64_xi:
case MEM_32_xi:
case MEM_16_xi:
case MEM_8_xi:
case MEM_STR_8_xi:
case MEM_STR_xi:
case PTR_64:
case PTR_32:
case PTR_16:
case PTR_8:
case PTR_STR:
case PTR_64_xi:
case PTR_32_xi:
case PTR_16_xi:
case PTR_8_xi:
case PTR_STR_8_xi:
case PTR_STR_xi:
segment = CSeg[snum][iptr].op.segment;
offset = CSeg[snum][iptr].op.offset;
fprintf(c_out, "%s dseg: %d off: %d\n", Op[op], segment, offset);
break;
}
break;
case CALL:
segment = CSeg[snum][iptr].op.segment;
fprintf(c_out, "%s cseg: %d\n", Op[op], segment);
break;
case EXITZ:
case SKIP:
case UNSKIP:
case MOV_bp_sp:
case RETF:
case RETP:
case INC_sp:
case INC_sp_string:
case DEC_sp:
case DEC_sp_string:
fprintf(c_out, "%s\n", Op[op]);
break;
case ADD_xi_offset:
fprintf(c_out, "%s\n", Op[op]);
break;
case ADD_xi_imm:
case MOV_ax_imm:
case MOV_bx_imm:
offset = CSeg[snum][iptr].op.offset;
fprintf(c_out, "%s val: %d\n", Op[op], offset);
break;
case PUT_str:
case GET_str:
case GET_item:
case FORMAT_STR:
case FORMAT_CHR:
case FORMAT_INDEX:
case SET_file_ptr:
case SET_stdin:
case SET_stdout:
case FLUSH_stdin:
fprintf(c_out, "%s\n", Op[op]);
break;
case RMUL:
case RDIV:
case RADD:
case RSUB:
case RNEG:
case RPOW:
case IMUL:
case IDIV:
case IADD:
case ISUB:
case INEG:
case IPOW:
case IMOD:
fprintf(c_out, "%s\n", Op[op]);
break;
case STRCAT:
fprintf(c_out, "%s ", Op[op]);
op = CSeg[snum][iptr].op.code2;
fprintf(c_out, "%s\n", Op[op]);
break;
case TEST_NUMBER:
case TEST_INDEX:
case TEST_STRING:
case TEST_CHAR:
fprintf(c_out, "%s ", Op[op]);
op = CSeg[snum][iptr].op.code2;
fprintf(c_out, "%s\n", Op[op]);
break;
case LOGIC_NOT:
case LOGIC_OR:
case LOGIC_AND:
case LOGIC_NOR:
case LOGIC_NAND:
case LOGIC_XOR:
fprintf(c_out, "%s\n", Op[op]);
break;
case JMP:
case JNZ:
case JZ:
offset = CSeg[snum][iptr].op.offset;
fprintf(c_out, "%s loc: %d\n", Op[op], offset);
break;
case CALL_stnd:
fprintf(c_out, "%s ", Op[op]);
op = CSeg[snum][iptr].op.code2;
fprintf(c_out, "%s\n", Op[op]);
break;
default:
exit_interpreter();
break;
}
iptr++;
op = CSeg[snum][iptr].op.code1;
}
fprintf(c_out, "memory available: %lu bytes\n", (unsigned long) coreleft());
fprintf(c_out, "end: \"%s\" cseg: %d\n\n", idp->name, snum);
}
#endif
| home
| contents
| previous
| next page
| send comment
| send link
| add bookmark |
Copyright © 2004, Stephen R. Schmitt