/* l2xistup LTX2X interpreter initialisation and start up code */
#include <stdio.h>
#include "getopt.h"
#include "l2xicmon.h"
#include "l2xisymt.h"
#include "l2xiexec.h"
#include "l2xierr.h" /* need this for MISSING_ENDCODE */
#include "l2xiscan.h" /* need this for SEMICOLON, etc */
#include "l2xiprse.h" /* need this for if_token_get_else_error */
#include "l2xiidbg.h"
#ifndef l2xicpr_h
#include "l2xicpr.h" /* the before/after token lists */
#endif
/* EXTERNALS */
/* extern int exec_line_number; */
/* extern char word_string[]; */
/* extern SYMTAB_NODE_PTR symtab_display[]; */
/* extern int level; */
extern TYPE_STRUCT_PTR integer_typep, real_typep,
boolean_typep;
extern int exec_stmt_count;
extern STACK_ITEM *stack;
/* extern SYMTAB_NODE_PTR program(); */
extern SYMTAB_NODE_PTR create_dummy_prog();
extern int DEBUG; /* defined in l2xlib.c */
extern int cl_debug; /* defined in l2xlib.c */
extern int cdebug; /* defined in l2xlib.c */
extern int edebug; /* defined in l2xlib.c */
extern BOOLEAN executed_return; /* TRUE iff return statement executed */
/* GLOBALS */
char THE_TITLE[] = "THE INTERPRETER";
char INT_FILE_VERSION[] = "Version 0.1";
char INT_FILE_DATE[] = "January 1997";
/* int DEBUG = 0; debugging level */
int Dbasic = 1; /* DEBUG >= Dbasic -> basic debugging */
int Danalyze = 2; /* DEBUG >= Danalyze -> declaration analysis debugging */
int Dtrace = 3; /* DEBUG >= Dtrace -> trace routine call tree */
int Dscan = 4; /* DEBUG >= Dscan -> source buffer debugging */
int Dtraceall = 5; /* DEBUG >= Dtraceall -> */
int Dott = 100; /* Hopefully, too high for all debugging */
extern int SLD_OFF; /* FALSE to enable source level debugger */
ICT *code_buffer; /* code buffer */
ICT *code_bufferp; /* code buffer ptr */
FILE *ferr; /* error o/p */
FILE *fcodeseg; /* code segment o/p */
FILE *filout; /* output file */
/* EXTERNALS */
extern ICT *create_code_segment();
extern TYPE_STRUCT dummy_type;
extern TOKEN_CODE statement_start_list[];
extern TOKEN_CODE token;
extern TOKEN_CODE ctoken;
extern ICT *code_segmentp;
extern FILE *source_file; /* file the scanner reads */
extern FILE *yyout; /* output file for LTX2X */
extern int get_ct_linenum(); /* gets current ct line number */
extern void set_ct_linenum(); /* sets current ct line number */
extern int line_number; /* interp scanners line number */
extern FILE *filerr; /* LTX2X's error file */
/* FORWARDS */
/* SYMTAB_NODE_PTR create_dummy_prog(); */
void start_code();
/***************************************************************************/
/* code_setup(filtabin) Initialise the scanner, etc then */
/* call the start_code routine to do the work. */
SYMTAB_NODE_PTR code_setup(filtabin)
FILE *filtabin; /* input file */
{
char optchar;
int n, k;
SYMTAB_NODE_PTR program_idp;
/* BOOLEAN cdebug = TRUE; if TRUE enable source Code debug */
/* BOOLEAN edebug = TRUE; if TRUE enable Execution debug */
/* print the banner */
/*
* fprintf(stdout, "\n %s", THE_TITLE);
* fprintf(stdout, "\n (%s, %s)\n", INT_FILE_VERSION, INT_FILE_DATE);
*/
/* open output log files */
/* ferr = fopen("interp.err", "w"); */
ferr = filerr; /* set error file to be ltx2x's */
fcodeseg = fopen("interp.csg", "w");
/* fprintf(stdout, "\nLog file is interp.err\n"); */
fprintf(stdout, "Code segment log file is interp.csg\n");
fprintf(ferr, "Error log file for %s (%s, %s)\n",
THE_TITLE, INT_FILE_VERSION, INT_FILE_DATE);
fprintf(ferr, "Author: Peter Wilson (Catholic University and NIST)\n");
fprintf(ferr, "Email any comments or suggestions to:
[email protected]\n\n");
fprintf(ferr, "Code segment log file is interp.csg\n\n");
/* set the output file */
filout = yyout;
/* set debug level for source Code */
if (cdebug) {
DEBUG = cl_debug;
}
else {
DEBUG = 0;
}
/* initialise the scanner */
/* init_scanner(argv[k]); */
line_number = get_ct_linenum(); /* set scanner's line number counter */
init_scanner(filtabin);
/* initialise code buffer */
code_buffer = alloc_array(ICT, MAX_CODE_BUFFER_SIZE);
code_bufferp = code_buffer;
if (DEBUG >= Dbasic) {
sprintf(dbuffer, "Initialised: code_buffer = %d, code_bufferp = %d\n",
code_buffer, code_bufferp);
debug_print(dbuffer);
}
/* initialise the symbol table */
init_symtab();
if (DEBUG >= Dbasic) {
sprintf(dbuffer, "Initialised the symbol table\n");
debug_print(dbuffer);
}
/* create an artificial program node */
program_idp = create_dummy_prog();
/* parse the remainder of the code */
/* zero or more declarations, followed by zero or more statements */
start_code(program_idp);
/* Don't think we want this as everyting from now on is in prog scope */
/* program_idp->defn.info.routine.local_symtab = exit_scope(); */
program_idp->defn.info.routine.code_segment = create_code_segment();
analyze_block(program_idp->defn.info.routine.code_segment);
/* reset CT line number to the scanner's value */
set_ct_linenum(line_number);
return(program_idp);
/* free the stack */
/*
free(stack);
fprintf(filout, "\n\nCompleted. %ld statements executed. \n\n",
exec_stmt_count);
if (DEBUG >= Dbasic) {
sprintf(dbuffer, "\n\n***That's all for run4\n\n");
debug_print(dbuffer);
}
return(program_idp);
*/
} /* end CODE_SETUP */
/***************************************************************************/
/***************************************************************************/
/* SYMTAB_NODE_PTR create_dummy_prog() create an artifical program node */
/* much of this code comes from `program_header' */
SYMTAB_NODE_PTR old_create_dummy_prog()
{
SYMTAB_NODE_PTR prog_idp;
prog_idp = alloc_struct(SYMTAB_NODE);
/* use dummy program name */
/* strcpy(word_string, "_PrOgRaM"); */
/* search_and_enter_local_symtab(prog_idp); */
prog_idp->defn.key = PROG_DEFN;
prog_idp->defn.info.routine.key = DECLARED;
prog_idp->defn.info.routine.parm_count = 0;
prog_idp->defn.info.routine.total_parm_size = 0;
prog_idp->defn.info.routine.total_local_size = 0;
prog_idp->typep = &dummy_type;
prog_idp->label_index = 0;
enter_scope(NULL);
prog_idp->defn.info.routine.locals = NULL;
prog_idp->defn.info.routine.parms = NULL;
return(prog_idp);
} /* end CREATE_DUMMY_PROG */
/***************************************************************************/
TOKEN_CODE ltx2x_start_declarations_list[] = {XCONSTANT, XLOCAL, PROCEDURE,
FUNCTION, 0};
/***************************************************************************/
/* start_code(rtn_idp) Parse the starting code, which consists of */
/* declarations, followed by zero or more statements */
/* ends at token ENDCODE */
/* ( similar to block in interp ) */
void start_code(rtn_idp)
SYMTAB_NODE_PTR rtn_idp; /* id of `program' or routine */
{
extern BOOLEAN block_flag;
get_token();
if (token == ENDCODE) {
crunch_token();
crunch_statement_marker();
return;
}
if (token_in(declaration_start_list)) {
declarations(rtn_idp);
/* error synchronization: Should be ; */
synchronize(ltx2x_follow_decls_list, NULL, NULL);
}
else {
skip_declarations(rtn_idp);
}
if (token == ENDCODE) {
crunch_token();
crunch_statement_marker();
return;
}
/* if (token == BEGIN) {
* crunch_token();
* }
*/
block_flag = TRUE;
/* now for possibly empty list of statements */
statement_block();
/* if (token_in(statement_start_list)) {
* crunch_token();
* statements();
* }
*/
block_flag = FALSE;
return;
} /* end START_CODE */
/***************************************************************************/
/***************************************************************************/
/* statements() process a set of statements */
/* originally based on `compound_statement' */
/* at entry, token is (crunched) start of a statement */
/* at exit, token is after closing ; of a statement */
statements()
{
entry_debug("statements");
/* get_token(); */
while (token_in(statement_start_list)) {
statement();
get_token();
}
exit_debug("statements");
return;
} /* end STATEMENTS */
/***************************************************************************/
/***************************************************************************/
/* statement_block() Process a list of statements ended by END_CODE */
/* at entry, token is start of a statement or ENDCODE */
/* at exit, parsing is complete */
statement_block()
{
entry_debug("statement_block");
if (token_in(statement_start_list)) {
crunch_token();
statements();
}
if (token != ENDCODE) {
error(MISSING_ENDCODE);
}
else {
crunch_statement_marker();
/* crunch_token(); */
}
exit_debug("statement_block");
return;
} /* end STATEMENT_BLOCK */
/***************************************************************************/
/***************************************************************************/
/* code_action(filtabin) Parsing for CODE: */
/* */
ICT *code_action(filtabin)
FILE *filtabin; /* the input file */
{
extern BOOLEAN block_flag;
entry_debug("code_action");
/* set the file and the line number for the scanner */
source_file = filtabin;
line_number = get_ct_linenum();
get_token();
if (token == ENDCODE) {
crunch_token();
crunch_statement_marker();
exit_debug("code_action at ENDCODE");
return(create_code_segment());
}
/* if (token == BEGIN) {
* crunch_token();
* }
*/
block_flag = TRUE;
/* now for possibly empty list of statements */
statement_block();
/* if (token_in(statement_start_list)) {
* crunch_token();
* statements();
* }
*/
block_flag = FALSE;
/* reset the CT line number to the scanner's value */
set_ct_linenum(line_number);
/* store results in a new code segment, and return it */
exit_debug("code_action");
return(create_code_segment());
} /* end CODE_ACTION */
/***************************************************************************/
/***************************************************************************/
/* exec_startup(prog_idp) Execute the start up code */
/* based on `program' */
exec_startup(prog_idp)
SYMTAB_NODE_PTR prog_idp; /* program id */
{
entry_debug("exec_startup");
/* set debug level for Execution */
if (edebug) {
DEBUG = cl_debug;
}
else {
DEBUG = 0;
}
/* Execute the program */
/* allocate runtime stack and initialise program's stack frame */
init_stack();
/* initialise the debugger */
init_debugger();
/* allocate locals and point to the code */
routine_entry(prog_idp);
/* DO IT */
get_ctoken();
while (ctoken != ENDCODE) exec_statement();
exit_debug("exec_startup");
return;
} /* end EXEC_STARTUP */
/***************************************************************************/
/***************************************************************************/
/* exec_statements(code_seg) Execute set of statements */
/* based on `execute' and `routine_entry' */
exec_statements(code_seg)
ICT *code_seg; /* the code */
{
entry_debug("exec_statements");
if (code_seg == NULL) return;
/* switch to new code segment */
code_segmentp = code_seg;
get_ctoken();
while (ctoken != ENDCODE) exec_statement();
exit_debug("exec_statements");
return;
} /* end EXEC_STATEMENTS */
/***************************************************************************/
/***************************************************************************/
/* exec_algorithm() Execute the body of an algorithm */
/* This is a rewrite of Pascal execute() in l2xixutl.c */
/* call this from exec_declared_routine_call() in l2xixstm.c */
/* (FUNCTION, PROCEDURE ) */
/* last token is END_OF_STATEMENTS */
exec_algorithm(rtn_idp)
SYMTAB_NODE_PTR rtn_idp; /* ponter to the routine */
{
entry_debug("exec_algorithm");
executed_return = FALSE;
routine_entry(rtn_idp);
get_ctoken();
while (ctoken != END_OF_STATEMENTS && !executed_return) exec_statement();
routine_exit(rtn_idp);
exit_debug("exec_algorithm");
return;
} /* end EXEC_ALGORITHM */
/***************************************************************************/
/***************************************************************************/