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

TPL_MAIN.CPP

main interpreter

/*-------------------------------------------------------------------*
     T Interpreter

     Interprets assignment statements, procedures, and functions

     Use the large memory model when compiling.

     File:     tpl_main.cpp

     Link to:  scn_main.cpp, sym_tabl.cpp,
	       prs_main.cpp, prs_stmt.cpp, prs_decl.cpp,
	       prs_expr.cpp, prs_stnd.cpp, prs_emit.cpp,
	       exc_main.cpp, exc_stnd.cpp, exc_dbug.cpp

     Usage:    ti filename.ext [debug]

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

#include "tpl_data.h"
#include <assert.h>
#include <conio.h>
#include <dos.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 *   External variables
 */
       /* in scn_main.cpp */
extern int Line_count;
extern token_struct Token;

/*
 *    Global declarations
 */
char Srce_file[FILE_NAME_LENGTH];                   // source file name
char Err_msg_file[FILE_NAME_LENGTH];                // for error messages
char Command[32];                                   // interpret command
bool Debug_flag;                                    // call debug if true
char *User_screen;                                  // full screen buffer
char *Debug_screen;                                 // full screen buffer
int User_col, User_lin;                             // cursor location
int Error_count = 0;                                // number of errors
int Video_mode;                                     // of system
FILE *Error_file;                                   // for error messages

#ifdef DEBUG
FILE *c_out;                                        // subprogram segments
FILE *d_out;                                        // data segment
#endif

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

void main(int argc, char *argv[])
{
    init_interpreter(argc, argv[1], argv[2]);

    if (!init_scanner(Srce_file))
    {
        printf("Error: cannot open source file.\n");
        exit(-1);                                   // failure
    }

    list_fopen();                                   // open analysis file
    errm_fopen();                                   // open error msg file

    pass_one();                                     // do first pass
    quit_scanner();

    if (Error_count == 0)
    {
        init_scanner(Srce_file);
        pass_two();                                 // do second pass
        quit_scanner();
    }

    errm_fclose();                                  // close error msg file
    list_fclose();                                  // close analysis file

    if (Error_count == 0)                           // call interpreter
        interpret();

    exit_interpreter();                             // cleanup
}

/*
 *   "init_interpreter" sets interpreter mode
 *
 *   returns:  nothing
 */
void init_interpreter(int argc, char *arg1, char *arg2)
{
    Debug_flag = false;                             // default

    save_video_mode();
    if (argc == 1)
    {
        printf("\n\n");
        printf("\t\t T Interpreter\n\n");
        printf("\t\t Usage: ti filename.ext [debug]\n\n");
        printf("\t\t        Esc key halts interpreter\n\n\n");

#ifndef DEBUG
        exit(0);
#else
        printf("Test file: ");
        scanf("%s", Srce_file);
        fflush(stdin);
        Debug_flag = true;
#endif
    }
    else if (argc == 2)
        strcpy(Srce_file, arg1);
    else if (argc == 3)
    {
        strcpy(Srce_file, arg1);
        strcpy(Command, arg2);

        if (!strcmp(Command, "debug"))              // match?
        {
            Debug_flag = true;
            printf("debug mode set\n");
        }
        else
            Debug_flag = false;
    }

    if (Debug_flag == true)
    {
        Debug_screen = new char[4000];
        User_screen  = new char[4000];

        User_col = wherex() - 1;                    // user screen data
        User_lin = wherey() - 1;
        gettext(1, 1, 80, 25, User_screen);
    }
}

/*
 *   "exit_interpreter" closes files and sets program return value
 *
 *   returns:  nothing
 */
void exit_interpreter()
{
    restore_video_mode();

    if (Debug_flag == true)
    {
        _setcursortype(_NORMALCURSOR);              // restore user screen
        window(1, 1, 80, 25);
        puttext(1, 1, 80, 25, User_screen);
        gotoxy(User_col + 1, User_lin + 1);

        assert(User_screen != NULL);
        delete User_screen;
        assert(Debug_screen != NULL);
        delete Debug_screen;
    }
    else if (Error_count != 0)                      // note errors if any
    {
        fprintf(stderr, "%20d Source lines. \n", Line_count);
        fprintf(stderr, "%20d Total errors. \n", Error_count);
    }

    exit(Error_count);
}

/*
 *   Error messages keyed to enumerated error codes in tpl_data.h
 */
char *M_word[] =
{
    " ",
    " , ", " . ", " ... ",
    " (", ") ", " : ", " := ",
    "argument", "array", "assignment",
    "by",
    "case", "code", "constant", "context",
    "data", "deep", "division", "do",
    "end", "error",
    "failed", "field", "file",
    "for", "function",
    "identifier", "if", "incompatible",
    "integer", "invalid", "item",
    "label", "labels", "large", "loop",
    "many", "memory", "missing",
    "nesting", "not", "number",
    "of", "open", "out", "overflow",
    "parameter", "parameters", "program",
    "range", "real", "record", "redefined", "return",
    "segment", "stack", "subscripts", "syntax",
    "then", "too", "type", "types",
    "undefined", "underflow", "union", "usage",
    "value", "variable",
    "wrong",
    "zero",
};

/*
 *   "compile_error" prints an error message to an error file.
 *   Codes are defined in tpl_data.h and correspond to elements
 *   of "M_word[]".
 *
 *   returns:  nothing
 */
void compile_error(MSG_CODE code, ...)              // message code(s)
{
    va_list ap;
    MSG_CODE arg;
    char message[80];

    Error_count++;                                  // update global

    strcpy(message, M_word[code]);

    va_start(ap, code);
    arg = va_arg(ap, MSG_CODE);

    while (arg != M_0)
    {
        strcat(message, " ");
        strcat(message, M_word[arg]);
        arg = va_arg(ap, MSG_CODE);
    }
    va_end(ap);

    fprintf(Error_file, "%s %03d %06d %03d %s\n",
	    Token.file, Error_count, Token.line, Token.column, message);

    if (Error_count >= 25)
    {
        Error_count++;
        fprintf(Error_file, "%03d %06d %03d Too many errors\n",
                Error_count, Token.line, Token.column);

        errm_fclose();
        list_fclose();
        exit_interpreter();
    }
}

/*
 *   "runtime_error" prints a run-time error message and then
 *   halts program execution.
 *   Codes are defined in tpl_data.h and correspond to elements
 *   of "M_word[]".
 *
 *   returns:  nothing
 */
void runtime_error(MSG_CODE code, ...)              // of error message(s)
{
    va_list ap;
    MSG_CODE arg;
    char message[80];

    strcpy(message, M_word[code]);

    va_start(ap, code);
    arg = va_arg(ap, MSG_CODE);

    while (arg != M_0)
    {
        strcat(message, " ");
        strcat(message, M_word[arg]);
        arg = va_arg(ap, MSG_CODE);
    }
    va_end(ap);

    Error_count++;

    if (Debug_flag)
    {
        // send message to the debug screen
        textattr(RED*16 + WHITE);
        gotoxy(1, SCREEN_BOTTOM);
        clreol();
        cputs("  ERROR:  ");
        cputs(message);

        getch();                                    // wait for key press
        errm_fclose();
        list_fclose();
        exit_interpreter();
    }
    else
    {
        // print error message and exit program
        restore_video_mode();
        fprintf(stderr, "RUN-TIME ERROR: %s \n", message);
        errm_fclose();
        list_fclose();
        exit(Error_count);                          // failure
    }
}

/*
 *   "errm_fopen" opens the error message file which is used by the
 *   editor program.
 *
 *   returns:  nothing
 */
void errm_fopen()
{
    char *str_ptr;                                  // to '.'

    // convert source file name into error message file name
    // then open error file with this name
    strcpy(Err_msg_file, Srce_file);
    str_ptr = strchr(Err_msg_file, '.');
    strcpy(str_ptr, ".ERR");
    Error_file = fopen(Err_msg_file, "w");
}

/*
 *   "errm_fclose" closes the error message file which is used by the
 *   editor program.
 *
 *   returns:  nothing
 */
void errm_fclose()
{
    fclose(Error_file);
    if (Error_count == 0)                           // delete the file
        unlink(Err_msg_file);
}

/*
 *   "save_video_mode" saves the system's video mode
 *
 *   returns:  nothing
 */
void save_video_mode()
{
    union REGS inr, outr;

    inr.h.ah = 0x0F;                                // get video mode
    int86(16, &inr, &outr);                         // call bios
    Video_mode = outr.h.al;
}

/*
 *   "restore_video_mode" restores the system's video mode if
 *   it was changed by a T program and not restored
 *
 *   returns:  nothing
 */
void restore_video_mode()
{
    union REGS inr, outr;

    inr.h.ah = 0x0F;                                // get video mode
    int86(16, &inr, &outr);                         // call bios

    if (Video_mode != outr.h.al)
    {
        inr.h.ah = 0x00;                            // set video mode
        inr.h.al = Video_mode;
        int86(16, &inr, &outr);                     // call bios
    }
}

#ifdef DEBUG

/*
 *   "list_fopen" creates files for debugging.
 *
 *   returns:  nothing
 */
void list_fopen()
{
   c_out = fopen("c.out", "w");
   d_out = fopen("d.out", "w");
}

/*
 *   "list_fclose" closes debugging files and
 *   creates a file for the path log.
 *
 *   returns:  nothing
 */
void list_fclose()
{
   fclose(c_out);
   fclose(d_out);
}

#endif

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

Copyright © 2004, Stephen R. Schmitt