| home | contents | previous | next page | send comment | send link | add bookmark |

EXC_MAIN.CPP

main executor

/*-------------------------------------------------------------------*
     T interpreter execution module

     File:     exc_main.cpp

     Module:   interpreter

     by:  Stephen R. Schmitt
 *-------------------------------------------------------------------*/

#include "tpl_data.h"
#include <assert.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <values.h>

/*
 *   External variables
 */
       /* in tpl_main.cpp */
extern bool Debug_flag;                             // true in debug mode
extern char *User_screen;                           // full screen buffer
extern char *Debug_screen;                          // full screen buffer
extern int User_col, User_lin;                      // cursor location
#ifdef DEBUG
 extern char *Op[];
#endif
       /* in exc_dbug.cpp */
extern bool Trace_flag;
extern bool Set_no_trace;

/*
 *   Global declarations
 */
OPCODE Operator;                                    // current opcode
MEMORY_PTR *CSeg,                                   // code segments
            DSeg,                                   // stack segment
            SSeg;                                   // data segment
int IPtr,                                           // instruction pointer
    SNum,                                           // segment number
    SPtr,                                           // stack pointer
    BPtr;                                           // base pointer
double DEAX;                                        // real number register
long EAX;                                           // integer register
long EBX;                                           // integer register
long ECX;                                           // integer register
char AL;                                            // byte value register
int AX,                                             // index value register
    BX,                                             // base index register
    CX;                                             // count register
char String[MAX_STRING_LENGTH];                     // string buffer
FILE *File_ptr;                                     // for turing i/o
int Skip_base_ptr;                                  // at which skip set

/*-------------------------------------------------------------------*
    Code Section
 *-------------------------------------------------------------------*/

/*
 *   "interpret" processes intermediate code by calling appropriate
 *   interpreter routines.
 *
 *   returns:  nothing
 */
void interpret()
{
    int line_num;

    if (Debug_flag == true)
        init_debugger();

    // Initialize the interpreter
    SSeg = new MEMORY[MAX_STACK_SIZE];              // create runtime stack
    if (SSeg == NULL)
        runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
    else
        memset(SSeg, '\0', MAX_STACK_SIZE * sizeof(MEMORY));

    SPtr = 0;                                       // set stack pointer
    BPtr = 0;                                       // set base pointer
    SNum = 0;                                       // set code segment
    IPtr = 0;                                       // set code pointer

    Operator = CSeg[SNum][IPtr].op.code1;           // first instruction

    // main interpreter loop
    while ((Operator != RETP   )&&                  // end of program
           (Operator != NO_CODE))                   // end of segment
    {
        switch (Operator)
        {
        case STATEMENT:
            line_num = CSeg[SNum][IPtr].op.offset;
            IPtr++;
            if ((Debug_flag)&&(Trace_flag)&&(SNum != 0 ))
            {
                trace_statement_execution(
                    CSeg[SNum][IPtr].string.ptr, line_num);
            }
            break;

        case EXITZ:
            line_num = CSeg[SNum][IPtr].op.offset;
            if (SSeg[SPtr].index == 0)
            {
                if (!Debug_flag)
                    printf("assert false on line: %d\n", line_num);

                goto interpret_exit;
            }
            decr_sptr();
            break;

        case SKIP:
            if (Set_no_trace)
            {
                Trace_flag = false;
                Set_no_trace = false;
                Skip_base_ptr = BPtr;
            }
            break;

        case UNSKIP:
            if (BPtr == Skip_base_ptr)
                Trace_flag = true;
            break;

        case PUSH:
            push();
            break;

        case POP:
            pop();
            break;

        case CALL:
            incr_sptr();
            SSeg[SPtr].address.segment = SNum;
            SSeg[SPtr].address.offset  = IPtr;
            SSeg[SPtr].address.ax      = AX;
            SSeg[SPtr].address.bx      = BX;
            SNum = CSeg[SNum][IPtr].op.segment;
            IPtr = -1;
            break;

        case RETF:
            SNum = SSeg[SPtr].address.segment;
            IPtr = SSeg[SPtr].address.offset;
            AX   = SSeg[SPtr].address.ax;
            BX   = SSeg[SPtr].address.bx;
            decr_sptr();
            break;

        case INC_sp:
            incr_sptr();
            break;

        case INC_sp_string:
            incr_sptr();
            new_string();
            break;

        case DEC_sp:
            decr_sptr();
            break;

        case DEC_sp_string:
            delete_string();
            decr_sptr();
            break;

        case ADD_xi_offset:
            add_xi_offset();
            break;

        case ADD_xi_imm:
            SSeg[SPtr].integer += CSeg[SNum][IPtr].op.offset;
            break;

        case MOV_ax_imm:
            AX = CSeg[SNum][IPtr].op.offset;
            break;

        case MOV_bx_imm:
            BX = CSeg[SNum][IPtr].op.offset;
            break;

        case MOV_bp_sp:
            BPtr = SPtr;
            break;

        case PUT_str:
            put_str();
            break;

        case GET_str:
            get_str();
            break;

        case GET_item:
            get_item();
            break;

        case FORMAT_STR:
            format_str();
            break;

        case FORMAT_CHR:
            format_chr();
            break;

        case FORMAT_INDEX:
            format_index();
            break;

        case SET_file_ptr:
            real_to_int();
            File_ptr = (FILE *) SSeg[SPtr].integer;
            decr_sptr();
            break;

        case SET_stdin:
            File_ptr = stdin;
            break;

        case SET_stdout:
            File_ptr = stdout;
            break;

        case FLUSH_stdin:
            fflush(stdin);
            break;

        case RMUL:
            SSeg[SPtr - 1].real = SSeg[SPtr - 1].real * SSeg[SPtr].real;
            decr_sptr();
            break;

        case RDIV:
            if (SSeg[SPtr].real == 0.0)
                runtime_error(M_DIVISION, M_BY, M_ZERO, M_0);
            SSeg[SPtr - 1].real = SSeg[SPtr - 1].real / SSeg[SPtr].real;
            decr_sptr();
            break;

        case RADD:
            SSeg[SPtr - 1].real = SSeg[SPtr - 1].real + SSeg[SPtr].real;
            decr_sptr();
            break;

        case RSUB:
            SSeg[SPtr - 1].real = SSeg[SPtr - 1].real - SSeg[SPtr].real;
            decr_sptr();
            break;

        case RNEG:
            SSeg[SPtr].real = - SSeg[SPtr].real;
            break;

        case RPOW:
            if (SSeg[SPtr - 1].real <= 0.0)
                runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);
            SSeg[SPtr - 1].real = pow(SSeg[SPtr - 1].real, SSeg[SPtr].real);
            decr_sptr();
            break;

        case IMUL:
            real_to_int();
            EAX = SSeg[SPtr].integer;
            decr_sptr();
            real_to_int();
            SSeg[SPtr].integer = SSeg[SPtr].integer * EAX;
            int_to_real();
            break;

        case IDIV:
            real_to_int();
            EAX = SSeg[SPtr].integer;
            decr_sptr();
            real_to_int();
            if (EAX == 0)
                runtime_error(M_DIVISION, M_BY, M_ZERO, M_0);
            SSeg[SPtr].integer = SSeg[SPtr].integer / EAX;
            int_to_real();
            break;

        case IADD:
            real_to_int();
            EAX = SSeg[SPtr].integer;
            decr_sptr();
            real_to_int();
            SSeg[SPtr].integer = SSeg[SPtr].integer + EAX;
            int_to_real();
            break;

        case ISUB:
            real_to_int();
            EAX = SSeg[SPtr].integer;
            decr_sptr();
            real_to_int();
            SSeg[SPtr].integer = SSeg[SPtr].integer - EAX;
            int_to_real();
            break;

        case INEG:
            real_to_int();
            SSeg[SPtr].integer = - SSeg[SPtr].integer;
            int_to_real();
            break;

        case IPOW:
            ipow();
            break;

        case IMOD:
            real_to_int();
            EAX = SSeg[SPtr].integer;
            decr_sptr();
            real_to_int();
            if (EAX == 0)
                runtime_error(M_DIVISION, M_BY, M_ZERO, M_0);
            SSeg[SPtr].integer = SSeg[SPtr].integer % EAX;
            int_to_real();
            break;

        case STRCAT:
            str_cat();
            break;

        case TEST_NUMBER:
        case TEST_INDEX:
        case TEST_STRING:
        case TEST_CHAR:
            test();
            break;

        case LOGIC_NOT:
        case LOGIC_OR:
        case LOGIC_AND:
        case LOGIC_NOR:
        case LOGIC_NAND:
        case LOGIC_XOR:
            logic();
            break;

        case JMP:
            IPtr = CSeg[SNum][IPtr].op.offset - 1;
            break;

        case JNZ:
            AX = SSeg[SPtr].index;
            decr_sptr();
            if (AX != 0)
                IPtr = CSeg[SNum][IPtr].op.offset - 1;
            break;

        case JZ:
            AX = SSeg[SPtr].index;
            decr_sptr();
            if (AX == 0)
                IPtr = CSeg[SNum][IPtr].op.offset - 1;
            break;

        case CALL_stnd:
            standard_routine();
            break;

        default:
            SNum = SNum;
            assert(0);
            break;
        }

        if (kbhit())
        {
            if (getch() == 27) /* Esc */
                goto interpret_exit;
        }

        IPtr++;
        Operator = CSeg[SNum][IPtr].op.code1;
    }
interpret_exit:
    return;
}

/*
 *   "push" interprets push command by calling appropriate
 *   interpreter routines.
 *
 *   returns:  nothing
 */
void push()
{
    int xi;

    Operator = CSeg[SNum][IPtr].op.code2;
    int segment = CSeg[SNum][IPtr].op.segment;
    int offset  = CSeg[SNum][IPtr].op.offset;

    switch (Operator)
    {
    case REG_BP:
        incr_sptr();
        SSeg[SPtr].index = BPtr;
        break;

    case IMM_64:
        IPtr++;
        incr_sptr();
        SSeg[SPtr].real = CSeg[SNum][IPtr].real;
        break;

    case IMM_32:
        IPtr++;
        incr_sptr();
        SSeg[SPtr].integer = CSeg[SNum][IPtr].integer;
        int_to_real();
        break;

    case IMM_16:
        IPtr++;
        incr_sptr();
        SSeg[SPtr].index = CSeg[SNum][IPtr].index;
        break;

    case IMM_8:
        IPtr++;
        incr_sptr();
        SSeg[SPtr].byte = CSeg[SNum][IPtr].byte;
        break;

    case IMM_STR:
        IPtr++;
        incr_sptr();
        new_string();
        strcpy(SSeg[SPtr].string.ptr, CSeg[SNum][IPtr].string.ptr);
        break;

    case ADDR:
        if (segment != 0)
            offset = offset + BPtr;                 // abs stack address
        incr_sptr();
        SSeg[SPtr].address.segment = segment;
        SSeg[SPtr].address.offset = offset;
        break;

    case ADDR_ADDR:
        if (segment != 0)
            offset = offset + BPtr;                 // abs stack address
        incr_sptr();
        SSeg[SPtr].address.segment = SSeg[offset].address.segment;
        SSeg[SPtr].address.offset = SSeg[offset].address.offset;
        break;

    case MEM_64:
        incr_sptr();
        if (segment == 0)
            SSeg[SPtr].real = DSeg[offset].real;
        else
            SSeg[SPtr].real = SSeg[offset + BPtr].real;
        break;

    case MEM_32:
        incr_sptr();
        if (segment == 0)
        {
            SSeg[SPtr].integer = DSeg[offset].integer;
            int_to_real();
        }
        else
            SSeg[SPtr].real = SSeg[offset + BPtr].real;
        break;

    case MEM_16:
        incr_sptr();
        if (segment == 0)
            SSeg[SPtr].index = DSeg[offset].index;
        else
            SSeg[SPtr].index = SSeg[offset + BPtr].index;
        break;

    case MEM_8:
        incr_sptr();
        if (segment == 0)
            SSeg[SPtr].byte = DSeg[offset].byte;
        else
            SSeg[SPtr].byte = SSeg[offset + BPtr].byte;
        break;

    case MEM_STR:
        incr_sptr();
        new_string();
        if (segment == 0)
            strcpy(SSeg[SPtr].string.ptr, DSeg[offset].string.ptr);
        else
            strcpy(SSeg[SPtr].string.ptr, SSeg[offset + BPtr].string.ptr);
        break;

    case MEM_64_xi:
        xi = (int)SSeg[SPtr].integer;               //  replace XI instead of incr SPtr
        if (segment == 0)
            SSeg[SPtr].real = DSeg[offset + xi].real;
        else
            SSeg[SPtr].real = SSeg[offset + xi + BPtr].real;
        break;

    case MEM_32_xi:
        xi = (int)SSeg[SPtr].integer;
        if (segment == 0)
        {
            SSeg[SPtr].integer = DSeg[offset + xi].integer;
            int_to_real();
        }
        else
            SSeg[SPtr].real = SSeg[offset + xi + BPtr].real;
        break;

    case MEM_16_xi:
        xi = (int)SSeg[SPtr].integer;
        if (segment == 0)
            SSeg[SPtr].index = DSeg[offset + xi].index;
        else
            SSeg[SPtr].index = SSeg[offset + xi + BPtr].index;
        break;

    case MEM_8_xi:
        xi = (int)SSeg[SPtr].integer;
        if (segment == 0)
            SSeg[SPtr].byte = DSeg[offset + xi].byte;
        else
            SSeg[SPtr].byte = SSeg[offset + xi + BPtr].byte;
        break;

    case MEM_STR_8_xi:
        xi = (int)SSeg[SPtr].integer;
        if (segment == 0)
            SSeg[SPtr].byte = DSeg[offset].string.ptr[xi];
        else
            SSeg[SPtr].byte = SSeg[offset + BPtr].string.ptr[xi];
        break;

    case MEM_STR_xi:
        xi = (int)SSeg[SPtr].integer;
        new_string();
        if (segment == 0)
            strcpy(SSeg[SPtr].string.ptr, DSeg[offset + xi].string.ptr);
        else
            strcpy(SSeg[SPtr].string.ptr, SSeg[offset + xi + BPtr].string.ptr);
        break;

    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:
        if (segment == 0)
        {
            segment = DSeg[offset].address.segment;
            offset  = DSeg[offset].address.offset;
        }
        else
        {
            segment = SSeg[offset + BPtr].address.segment;
            offset  = SSeg[offset + BPtr].address.offset;
        }
        switch (Operator)
        {
        case PTR_64:
            incr_sptr();
            if (segment == 0)
                SSeg[SPtr].real = DSeg[offset].real;
            else
                SSeg[SPtr].real = SSeg[offset].real;
            break;

        case PTR_32:
            incr_sptr();
            if (segment == 0)
            {
                SSeg[SPtr].integer = DSeg[offset].integer;
                int_to_real();
            }
            else
                SSeg[SPtr].real = SSeg[offset].real;
            break;

        case PTR_16:
            incr_sptr();
            if (segment == 0)
                SSeg[SPtr].index = DSeg[offset].index;
            else
                SSeg[SPtr].index = SSeg[offset].index;
            break;

        case PTR_8:
            incr_sptr();
            if (segment == 0)
                SSeg[SPtr].byte = DSeg[offset].byte;
            else
                SSeg[SPtr].byte = SSeg[offset].byte;
            break;

        case PTR_STR:
            incr_sptr();
            new_string();
            if (segment == 0)
                strcpy(SSeg[SPtr].string.ptr, DSeg[offset].string.ptr);
            else
                strcpy(SSeg[SPtr].string.ptr, SSeg[offset].string.ptr);
            break;

        case PTR_64_xi:
            xi = (int)SSeg[SPtr].integer;           //  replace XI instead of incr SPtr
            if (segment == 0)
                SSeg[SPtr].real = DSeg[offset + xi].real;
            else
                SSeg[SPtr].real = SSeg[offset + xi].real;
            break;

        case PTR_32_xi:
            xi = (int)SSeg[SPtr].integer;
            if (segment == 0)
            {
                SSeg[SPtr].integer = DSeg[offset + xi].integer;
                int_to_real();
            }
            else
                SSeg[SPtr].real = SSeg[offset + xi].real;
            break;

        case PTR_16_xi:
            xi = (int)SSeg[SPtr].integer;
            if (segment == 0)
                SSeg[SPtr].index = DSeg[offset + xi].index;
            else
                SSeg[SPtr].index = SSeg[offset + xi].index;
            break;

        case PTR_8_xi:
            xi = (int)SSeg[SPtr].integer;
            if (segment == 0)
                SSeg[SPtr].byte = DSeg[offset + xi].byte;
            else
                SSeg[SPtr].byte = SSeg[offset + xi].byte;
            break;

        case PTR_STR_8_xi:
            xi = (int)SSeg[SPtr].integer;
            if (segment == 0)
                SSeg[SPtr].byte = DSeg[offset].string.ptr[xi];
            else
                SSeg[SPtr].byte = SSeg[offset].string.ptr[xi];
            break;

        case PTR_STR_xi:
            xi = (int)SSeg[SPtr].integer;
            new_string();
            if (segment == 0)
                strcpy(SSeg[SPtr].string.ptr, DSeg[offset + xi].string.ptr);
            else
                strcpy(SSeg[SPtr].string.ptr, SSeg[offset + xi].string.ptr);
            break;
        }
        break;

    default:
        assert(0);
        break;
    }
}

/*
 *   "pop" interprets pop command by calling appropriate
 *   interpreter routines.
 *
 *   returns:  nothing
 */
void pop()
{
    int xi;

    Operator = CSeg[SNum][IPtr].op.code2;
    int offset  = CSeg[SNum][IPtr].op.offset;
    int segment = CSeg[SNum][IPtr].op.segment;

    switch (Operator)
    {
    case REG_BP:
        BPtr = SSeg[SPtr].index;
        decr_sptr();
        break;

    case MEM_64:
        if (segment == 0)
            DSeg[offset].real = SSeg[SPtr].real;
        else
            SSeg[offset + BPtr].real = SSeg[SPtr].real;
        decr_sptr();
        break;

    case MEM_32:
        real_to_int();
        if (segment == 0)
            DSeg[offset].integer = SSeg[SPtr].integer;
        else
            SSeg[offset + BPtr].real = (double) SSeg[SPtr].integer;
        decr_sptr();
        break;

    case MEM_16:
        if (segment == 0)
            DSeg[offset].index = SSeg[SPtr].index;
        else
            SSeg[offset + BPtr].index = SSeg[SPtr].index;
        decr_sptr();
        break;

    case MEM_8:
        if (segment == 0)
            DSeg[offset].byte = SSeg[SPtr].byte;
        else
            SSeg[offset + BPtr].byte = SSeg[SPtr].byte;
        decr_sptr();
        break;

    case MEM_STR:
        strcpy(String, SSeg[SPtr].string.ptr);
        delete_string();
        decr_sptr();
        if (segment == 0)
        {
            assert(DSeg[offset].string.sig == SIGNATURE);

            if (strlen(String) < DSeg[offset].string.len)
                strcpy(DSeg[offset].string.ptr, String);
            else
                runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);
        }
        else
        {
            assert(SSeg[offset + BPtr].string.sig == SIGNATURE);
            strcpy(SSeg[offset + BPtr].string.ptr, String);
        }
        break;

    case MEM_64_xi:
        xi = (int)SSeg[SPtr-1].integer;
        if (segment == 0)
            DSeg[offset + xi].real = SSeg[SPtr].real;
        else
            SSeg[offset + xi + BPtr].real = SSeg[SPtr].real;
        decr_sptr();
        decr_sptr();
        break;

    case MEM_32_xi:
        xi = (int)SSeg[SPtr-1].integer;             // XI is below data
        real_to_int();
        if (segment == 0)
            DSeg[offset + xi].integer = SSeg[SPtr].integer;
        else
            SSeg[offset + xi + BPtr].real = (double) SSeg[SPtr].integer;
        decr_sptr();
        decr_sptr();                                // need additional pop to remove XI
        break;

    case MEM_16_xi:
        xi = (int)SSeg[SPtr-1].integer;
        if (segment == 0)
            DSeg[offset + xi].index = SSeg[SPtr].index;
        else
            SSeg[offset + xi + BPtr].index = SSeg[SPtr].index;
        decr_sptr();
        decr_sptr();
        break;

    case MEM_8_xi:
        xi = (int)SSeg[SPtr-1].integer;
        if (segment == 0)
            DSeg[offset + xi].byte = SSeg[SPtr].byte;
        else
            SSeg[offset + xi + BPtr].byte = SSeg[SPtr].byte;
        decr_sptr();
        decr_sptr();
        break;

    case MEM_STR_8_xi:
        xi = (int)SSeg[SPtr-1].integer;
        if (segment == 0)
            DSeg[offset].string.ptr[xi] = SSeg[SPtr].byte;
        else
            SSeg[offset + BPtr].string.ptr[xi] = SSeg[SPtr].byte;
        decr_sptr();
        decr_sptr();
        break;

    case MEM_STR_xi:
        xi = (int)SSeg[SPtr-1].integer;
        strcpy(String, SSeg[SPtr].string.ptr);
        delete_string();
        decr_sptr();
        decr_sptr();
        if (segment == 0)
        {
            assert(DSeg[offset + xi].string.sig == SIGNATURE);

            if (strlen(String) < DSeg[offset + xi].string.len)
                strcpy(DSeg[offset + xi].string.ptr, String);
            else
                runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);
        }
        else
        {
            assert(SSeg[offset + xi + BPtr].string.sig == SIGNATURE);
            strcpy(SSeg[offset + xi + BPtr].string.ptr, String);
        }
        break;

    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:
        if (segment == 0)
        {
            segment = DSeg[offset].address.segment;
            offset  = DSeg[offset].address.offset;
        }
        else
        {
            segment = SSeg[offset + BPtr].address.segment;
            offset  = SSeg[offset + BPtr].address.offset;
        }
        switch (Operator)
        {
        case PTR_64:
            if (segment == 0)
                DSeg[offset].real = SSeg[SPtr].real;
            else
                SSeg[offset].real = SSeg[SPtr].real;
            decr_sptr();
            break;

        case PTR_32:
            real_to_int();
            if (segment == 0)
                DSeg[offset].integer = SSeg[SPtr].integer;
            else
                SSeg[offset].real = (double) SSeg[SPtr].integer;
            decr_sptr();
            break;

        case PTR_16:
            if (segment == 0)
                DSeg[offset].index = SSeg[SPtr].index;
            else
                SSeg[offset].index = SSeg[SPtr].index;
            decr_sptr();
            break;

        case PTR_8:
            if (segment == 0)
                DSeg[offset].byte = SSeg[SPtr].byte;
            else
                SSeg[offset].byte = SSeg[SPtr].byte;
            decr_sptr();
            break;

        case PTR_STR:
            strcpy(String, SSeg[SPtr].string.ptr);
            delete_string();
            decr_sptr();
            if (segment == 0)
            {
                assert(DSeg[offset].string.sig == SIGNATURE);

                if (strlen(String) < DSeg[offset].string.len)
                    strcpy(DSeg[offset].string.ptr, String);
                else
                    runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);
            }
            else
            {
                assert(SSeg[offset].string.sig == SIGNATURE);
                strcpy(SSeg[offset].string.ptr, String);
            }
            break;

        case PTR_64_xi:
            xi = (int)SSeg[SPtr-1].integer;         // XI is below data
            if (segment == 0)
                DSeg[offset + xi].real = SSeg[SPtr].real;
            else
                SSeg[offset + xi].real = SSeg[SPtr].real;
            decr_sptr();
            decr_sptr();                            // need additional pop to remove XI
            break;

        case PTR_32_xi:
            xi = (int)SSeg[SPtr-1].integer;
            real_to_int();
            if (segment == 0)
                DSeg[offset + xi].integer = SSeg[SPtr].integer;
            else
                SSeg[offset + xi].real = (double) SSeg[SPtr].integer;
            decr_sptr();
            decr_sptr();
            break;

        case PTR_16_xi:
            xi = (int)SSeg[SPtr-1].integer;
            if (segment == 0)
                DSeg[offset + xi].index = SSeg[SPtr].index;
            else
                SSeg[offset + xi].index = SSeg[SPtr].index;
            decr_sptr();
            decr_sptr();
            break;

        case PTR_8_xi:
            xi = (int)SSeg[SPtr-1].integer;
            if (segment == 0)
                DSeg[offset + xi].byte = SSeg[SPtr].byte;
            else
                SSeg[offset + xi].byte = SSeg[SPtr].byte;
            decr_sptr();
            decr_sptr();
            break;

        case PTR_STR_8_xi:
            xi = (int)SSeg[SPtr-1].integer;
            if (segment == 0)
                DSeg[offset].string.ptr[xi] = SSeg[SPtr].byte;
            else
                SSeg[offset].string.ptr[xi] = SSeg[SPtr].byte;
            decr_sptr();
            decr_sptr();
            break;

        case PTR_STR_xi:
            xi = (int)SSeg[SPtr-1].integer;
            strcpy(String, SSeg[SPtr].string.ptr);
            delete_string();
            decr_sptr();
            decr_sptr();
            if (segment == 0)
            {
                assert(DSeg[offset + xi].string.sig == SIGNATURE);

                if (strlen(String) < DSeg[offset + xi].string.len)
                    strcpy(DSeg[offset].string.ptr, String);
                else
                    runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);
            }
            else
            {
                assert(SSeg[offset + xi].string.sig == SIGNATURE);
                strcpy(SSeg[offset + xi].string.ptr, String);
            }
            break;
        }
        break;

    default:
        assert(0);
        break;
    }
}

/*
 *   "test" interprets test commands which compare the top two
 *   stack values.
 *
 *   returns:  nothing
 */
void test()
{
    switch (Operator)
    {
    case TEST_INDEX:
        AX = SSeg[SPtr].index;
        decr_sptr();
        AX = SSeg[SPtr].index - AX;
        if (AX == 0)
            SSeg[SPtr].index = 0;
        else if (AX > 0)
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = -1;
        break;

    case TEST_NUMBER:
        DEAX = SSeg[SPtr].real;
        decr_sptr();
        DEAX = SSeg[SPtr].real - DEAX;
        if (DEAX == 0.0)
            SSeg[SPtr].index = 0;
        else if (DEAX > 0.0)
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = -1;
        break;

    case TEST_STRING:
        strcpy(String, SSeg[SPtr].string.ptr);
        delete_string();
        decr_sptr();
        AX = strcmp(SSeg[SPtr].string.ptr, String);
        delete_string();
        SSeg[SPtr].index = AX;
        break;

    case TEST_CHAR:
        AL = SSeg[SPtr].byte;
        decr_sptr();
        AL = SSeg[SPtr].byte - AL;
        if (AL == 0)
            SSeg[SPtr].index = 0;
        else if (AL > 0)
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = -1;
        break;
    }

    Operator = CSeg[SNum][IPtr].op.code2;

    switch (Operator)
    {
    case TEST_EQ:
        if (SSeg[SPtr].index == 0)
            SSeg[SPtr].index = 1;                   // true
        else
            SSeg[SPtr].index = 0;                   // false
        break;

    case TEST_NE:
        if (SSeg[SPtr].index != 0)
            SSeg[SPtr].index = 1;                   // true
        else
            SSeg[SPtr].index = 0;                   // false
        break;

    case TEST_GT:
        if (SSeg[SPtr].index > 0)
            SSeg[SPtr].index = 1;                   // true
        else
            SSeg[SPtr].index = 0;                   // false
        break;

    case TEST_GE:
        if (SSeg[SPtr].index >= 0)
            SSeg[SPtr].index = 1;                   // true
        else
            SSeg[SPtr].index = 0;                   // false
        break;

    case TEST_LT:
        if (SSeg[SPtr].index < 0)
            SSeg[SPtr].index = 1;                   // true
        else
            SSeg[SPtr].index = 0;                   // false
        break;

    case TEST_LE:
        if (SSeg[SPtr].index <= 0)
            SSeg[SPtr].index = 1;                   // true
        else
            SSeg[SPtr].index = 0;                   // false
        break;

    default:
        assert(0);
        break;
    }
}


/*
 *  "add_xi_offset" adds array index value to offset for 
 *  data structure element
 *
 *  returns:  nothing
 */
void add_xi_offset()
{
    real_to_int();                                  // index at SP
                                                    // XI is at SP-1 now
    if( 0 <= SSeg[SPtr].integer && SSeg[SPtr].integer <= AX )
        SSeg[SPtr-1].integer += SSeg[SPtr].integer * BX;
    else
        runtime_error(M_INTEGER, M_OUT, M_OF, M_RANGE, M_0);

    decr_sptr();
}

void put_str()
{
    if ((Debug_flag == true) && (File_ptr == stdout))
        write_to_user_screen(SSeg[SPtr].string.ptr);
    else
        fprintf(File_ptr, "%s", SSeg[SPtr].string.ptr);

    delete_string();
    decr_sptr();
}

void get_str()
{
    int get_width;
    char *eol_ptr;

    get_width = SSeg[SPtr].real;
    decr_sptr();

    if ((get_width < 0) || (get_width > MAX_STRING_LENGTH))
        runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);

    if (Debug_flag && (File_ptr == stdin))          // swap screens
        debug_to_user_screen();

    fgets(String, get_width + 1, File_ptr);

    if (Debug_flag && (File_ptr == stdin))          // re-swap screens
        user_to_debug_screen();

    // remove any new line character
    eol_ptr = strchr(String, '\n');
    if (eol_ptr)
        *eol_ptr = NULL;

    incr_sptr();
    new_string();
    strcpy(SSeg[SPtr].string.ptr, String);
}

void get_item()
{
    if (Debug_flag && (File_ptr == stdin))          // swap screens
        debug_to_user_screen();

    fscanf(File_ptr, "%s", String);

    if (Debug_flag && (File_ptr == stdin))          // re-swap screens
        user_to_debug_screen();

    incr_sptr();
    new_string();
    strcpy(SSeg[SPtr].string.ptr, String);
}

void format_str()
{
    int str_width = (int)SSeg[SPtr].real;
    decr_sptr();

    if (str_width > MAX_STRING_LENGTH)
        str_width = MAX_STRING_LENGTH;

    sprintf(String, "%-*s", str_width, SSeg[SPtr].string.ptr);
    strcpy(SSeg[SPtr].string.ptr, String);
}

void format_chr()
{
    int str_width = (int)SSeg[SPtr].real;
    decr_sptr();

    if (str_width > MAX_STRING_LENGTH)
        str_width = MAX_STRING_LENGTH;

    char byte = SSeg[SPtr].byte;
    new_string();
    SSeg[SPtr].string.ptr[0] = byte;
    SSeg[SPtr].string.ptr[1] = NULL;
    sprintf(String, "%-*s", str_width, SSeg[SPtr].string.ptr);
    strcpy(SSeg[SPtr].string.ptr, String);
}

void format_index()
{
    int str_width = (int) SSeg[SPtr].real;
    decr_sptr();

    if (str_width > MAX_STRING_LENGTH)
        str_width = MAX_STRING_LENGTH;

    int index = SSeg[SPtr].index;
    new_string();
    sprintf(String, "%-*d", str_width, index);
    strcpy(SSeg[SPtr].string.ptr, String);
}

void new_string()
{
    // already allocated?
    assert(SSeg[SPtr].string.sig != SIGNATURE);

    char *ptr = new char[MAX_STRING_LENGTH];
    if (ptr)
    {
        SSeg[SPtr].string.ptr = ptr;
        SSeg[SPtr].string.len = MAX_STRING_LENGTH;
        SSeg[SPtr].string.sig = SIGNATURE;
    }
    else
        runtime_error(M_OUT, M_OF, M_MEMORY, M_0);
}

void delete_string()
{
    // allocated?
    assert(SSeg[SPtr].string.sig == SIGNATURE);

    delete SSeg[SPtr].string.ptr;
    SSeg[SPtr].string.ptr = NULL;
    SSeg[SPtr].string.len = 0;
    SSeg[SPtr].string.sig = 0;
}

void ipow()
{
    real_to_int();
    long integer = SSeg[SPtr].integer;
    decr_sptr();

    real_to_int();
    if (SSeg[SPtr].integer <= 0.0)
        runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);
    else
    {
        long base = 1;
        for (long i = integer; i > 0; i--)
            base = base*SSeg[SPtr].integer;

        SSeg[SPtr].integer = base;
        int_to_real();
    }
}

void str_cat()
{
    int length = strlen(SSeg[SPtr].string.ptr);
    strcpy(String, SSeg[SPtr].string.ptr);
    delete_string();
    decr_sptr();
    length += strlen(SSeg[SPtr].string.ptr);

    if (length <= MAX_STRING_LENGTH)
        strcat(SSeg[SPtr].string.ptr, String);
    else
        runtime_error(M_VALUE, M_OUT, M_OF, M_RANGE, M_0);
}

void logic()
{
    int index = SSeg[SPtr].index;
    decr_sptr();

    switch (Operator)
    {
    case LOGIC_NOT:
        incr_sptr();
        if (index)
            SSeg[SPtr].index = 0;
        else
            SSeg[SPtr].index = 1;
        break;

    case LOGIC_OR:
        if (SSeg[SPtr].index || index)
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = 0;
        break;

    case LOGIC_NOR:
        if (!(SSeg[SPtr].index || index))
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = 0;
        break;

    case LOGIC_AND:
        if (SSeg[SPtr].index && index)
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = 0;
        break;

    case LOGIC_NAND:
        if (!(SSeg[SPtr].index && index))
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = 0;
        break;

    case LOGIC_XOR:
        if ((!SSeg[SPtr].index && index) || ( SSeg[SPtr].index && !index))
            SSeg[SPtr].index = 1;
        else
            SSeg[SPtr].index = 0;
        break;
    }
}

/*
 *   "debug_to_user_screen" replaces the debug screen with the
 *   user screen
 *
 *   returns:  nothing
 */
void debug_to_user_screen()
{
    gettext(1, 1, 80, 25, Debug_screen);            // save debug screen
    puttext(1, 1, 80, 25, User_screen);             // restore user screen
    gotoxy(User_col + 1, User_lin + 1);             // restore cursor
    _setcursortype(_NORMALCURSOR);
}

/*
 *   "user_to_debug_screen" replaces the user screen with the
 *   debug screen
 *
 *   returns:  nothing
 */
void user_to_debug_screen()
{
    User_col = wherex() - 1;                        // save cursor location
    User_lin = wherey() - 1;
    gettext(1, 1, 80, 25, User_screen);             // save user screen
    puttext(1, 1, 80, 25, Debug_screen);            // restore debug screen
    _setcursortype(_NOCURSOR);
}

/*
 *   "write_to_user_screen" writes a string to the user screen buffer
 *   and updates values representing the cursor as if it were on
 *   the screen
 *
 *   returns:       nothing
 */
void write_to_user_screen(char *string)             // item to write
{
    int i = 0;
    while (string[i] != NULL)
    {
        int j = 2*(80*User_lin + User_col);

        if (string[i] == '\n')
        {
            i++;
            User_col = 0;
            User_lin++;
        }
        else if (string[i] == '\t')
        {
            i++;
            User_col += 8;
        }
        else
        {
            User_screen[j] = string[i];
            i++;
            User_col++;
        }

        if (User_col > 79)
        {
            User_col = 0;
            User_lin++;
        }

        if (User_lin > 24)
        {
            User_lin = 24;
            move_up_user_screen();
        }
    }
}

/*
 *   "move_up_user_screen" shifts all characters in the user screen
 *   up by one line and clears the bottom line
 *
 *   returns:       nothing
 */
void move_up_user_screen()
{
    int i;

    for (i = 160; i < 4000; i++)                    // shift screen up
        User_screen[i - 160] = User_screen[i];

    for (i = 3840; i < 4000; i += 2)                // clear bottom line
        User_screen[i] = ' ';
}

| home | contents | previous | next page | send comment | send link | add bookmark |

Copyright © 2004, Stephen R. Schmitt