/* l2xidbug.c Interactive SLD debugging routines for LTX2X interpreter */ /* Written by: Peter Wilson, CUA pwilson@cme.nist.gov */ /* This code is partly based on algorithms presented by Ronald Mak in */ /* "Writing Compilers & Interpreters", John Wiley & Sons, 1991 */ #include #include "l2xicmon.h" #include "l2xierr.h" #include "l2xiscan.h" #include "l2xisymt.h" #include "l2xiexec.h" #include "l2xiidbg.h" #define MAX_BREAKS 16 #define MAX_WATCHES 16 #define COMMAND_QUERY "Command? " /* EXTERNALS */ extern int level; extern SYMTAB_NODE_PTR symtab_display[]; extern STACK_ITEM_PTR tos; extern int line_number; extern int buffer_offset; extern BOOLEAN print_flag; extern ICT *code_segmentp; extern ICT *statement_startp; extern int ctoken; extern int exec_line_number; extern int isynt_error_count; extern char *bufferp; extern int ch; extern char source_buffer[]; extern char word_string[]; extern int token; extern LITERAL literal; extern BOOLEAN block_flag; extern ICT *code_buffer; extern ICT *code_bufferp; extern ICT *code_segmentp; extern BOOLEAN is_value_undef(); /* GLOBALS */ FILE *console; BOOLEAN debugger_command_flag, /* TRUE during debug command */ halt_flag, /* TRUE to pause for debug command */ trace_flag, /* TRUE to trace statement */ step_flag, /* TRUE to single-step */ entry_flag, /* TRUE to trace routine entry */ exit_flag, /* TRUE to trace routine exit */ traceall_flag, /* TRUE to trace everything */ stack_flag; /* TRUE to watch the stack */ int break_count; /* count of breakpoints */ int break_list[MAX_BREAKS]; /* list of breakpoints */ int watch_count; /* count of watches */ SYMTAB_NODE_PTR watch_list[MAX_WATCHES]; /* list of watches */ typedef struct { /* watch structure */ SYMTAB_NODE_PTR watch_idp; /* id node watched variable */ BOOLEAN store_flag; /* TRUE to trace stores */ BOOLEAN fetch_flag; /* TRUE to trace fetches */ } WATCH_STRUCT, *WATCH_STRUCT_PTR; /* char *symbol_strings[EOTC]; */ /* array of the strings which form tokens */ char *symbol_strings[] = { #define sctc(a, b, c) c, #include "l2xisctc.h" #undef sctc }; /* array of strings which corresponding to form types */ char *form2str[] = { #define fotc(a, b, c, d) d, #define sotc(a, b, c, d) #define sftc(a, b, c, d) d, #include "l2xisftc.h" #undef fotc #undef sotc #undef sftc }; /* array of strings which corresponding to stack types */ char *stack2str[] = { #define fotc(a, b, c, d) #define sotc(a, b, c, d) b, #define sftc(a, b, c, d) b, #include "l2xisftc.h" #undef fotc #undef sotc #undef sftc }; /********************************************************************/ /* init_debugger() Initialise interactive debugger */ init_debugger() { int i; if (SLD_OFF) return; /* initialise the globals */ /* console = fopen("CON", "r"); */ console = stdin; /* init_symbol_strings(); */ /* code_buffer = alloc_bytes(MAX_SOURCE_LINE_LENGTH + 1); */ print_flag = FALSE; halt_flag = block_flag = TRUE; debugger_command_flag = trace_flag = step_flag = entry_flag = exit_flag = FALSE; traceall_flag = stack_flag = FALSE; break_count = 0; for (i = 0; i store_flag = TRUE; wp->fetch_flag = TRUE; } } else if (strcmp(word_string, "unwatch") == 0) { remove_watch(); } else if (strcmp(word_string, "store") == 0) { wp = allocate_watch(); if (wp != NULL) { wp->store_flag = TRUE; } } else if (strcmp(word_string, "fetch") == 0) { wp = allocate_watch(); if (wp != NULL) { wp->fetch_flag = TRUE; } } else if (strcmp(word_string, "show") == 0) { show_value(); } else if (strcmp(word_string, "assign") == 0) { assign_variable(); } else if (strcmp(word_string, "where") == 0) { print_statement(); get_token(); } else if (strcmp(word_string, "kill") == 0) { printf("Program killed.\n"); exit(0); } else if (strcmp(word_string, "traceall") == 0) { traceall_flag = TRUE; get_token(); } else if (strcmp(word_string, "untraceall") == 0) { traceall_flag = FALSE; get_token(); } else if (strcmp(word_string, "stack") == 0) { stack_flag = TRUE; stack_debug(); get_token(); } else if (strcmp(word_string, "unstack") == 0) { stack_flag = FALSE; get_token(); } return; } /* end execute_debugger_command */ /********************************************************************/ /* TRACING ROUTINES */ /********************************************************************/ /* trace_statement_execution() Called just before the execution */ /* of each statement */ trace_statement_execution() { if (SLD_OFF) return; if (traceall_flag) { sprintf(dbuffer, ">> Stmt %d\n", exec_line_number); log_print(dbuffer); } if (break_count > 0) { int i; /* check if this statement is a breakpoint */ for (i = 0; i < break_count; i++) { if (exec_line_number == break_list[i]) { printf("\nBreakpoint"); print_statement(); halt_flag = TRUE; break; } } } /* pause to read debugger command */ if (halt_flag) { read_debugger_command(); halt_flag = step_flag; } /* if single stepping, print the current statement */ /* if tracing, print the current line number */ if (step_flag) print_statement(); if (trace_flag && !traceall_flag) print_line_number(); } /* end trace_statement_execution */ /********************************************************************/ /********************************************************************/ /* trace_routine_entry(idp) Called at entry to a routine */ trace_routine_entry(idp) SYMTAB_NODE_PTR idp; /* routine id */ { if (SLD_OFF) return; if (traceall_flag) { sprintf(dbuffer, ">> Entering routine %s\n", idp->name); log_print(dbuffer); } else if (entry_flag) { printf("\nEntering %s\n", idp->name); } } /* end trace_routine_entry */ /********************************************************************/ /********************************************************************/ /* trace_routine_exit(idp) Called at exit from a routine */ trace_routine_exit(idp) SYMTAB_NODE_PTR idp; /* routine id */ { if (SLD_OFF) return; if (traceall_flag) { sprintf(dbuffer, ">> Exiting routine %s\n", idp->name); log_print(dbuffer); } else if (exit_flag) { printf("\nExiting %s\n", idp->name); } } /* end trace_routine_exit */ /********************************************************************/ /********************************************************************/ /* trace_data_store(idp, idp_tp, targetp, target_tp) Called just */ /* before storing data in a variable */ trace_data_store(idp, idp_tp, targetp, target_tp) SYMTAB_NODE_PTR idp; /* id of target variable */ TYPE_STRUCT_PTR idp_tp; /* ptr to idp's type */ STACK_ITEM_PTR targetp; /* ptr to target location */ TYPE_STRUCT_PTR target_tp; /* ptr to target's type */ { if (SLD_OFF) return; if (traceall_flag) { sprintf(dbuffer, ">> %s", idp->name); log_print(dbuffer); if (idp_tp->form == ARRAY_FORM || idp_tp->form == BAG_FORM || idp_tp->form == LIST_FORM || idp_tp->form == SET_FORM ) { log_print("[*]"); } else if (idp_tp->form == ENTITY_FORM) { log_print(".*"); } print_data_value_debug(targetp, target_tp, ":="); } /* check if variable is being watched for stores */ else if ((idp->info != NULL) && ((WATCH_STRUCT_PTR) idp->info)->store_flag) { printf("\nAt %d: Store %s", exec_line_number, idp->name); if (idp_tp->form == ARRAY_FORM || idp_tp->form == BAG_FORM || idp_tp->form == LIST_FORM || idp_tp->form == SET_FORM ) { printf("[*]"); } else if (idp_tp->form == ENTITY_FORM) { printf(".*"); } print_data_value(targetp, target_tp, ":="); } return; } /* end trace_data_store */ /********************************************************************/ /********************************************************************/ /* trace_data_fetch(idp, tp, datap) Called just */ /* before fetching data from a variable */ trace_data_fetch(idp, tp, datap) SYMTAB_NODE_PTR idp; /* id of target variable */ TYPE_STRUCT_PTR tp; /* ptr to idp's type */ STACK_ITEM_PTR datap; /* ptr to data */ { TYPE_STRUCT_PTR idp_tp = idp->typep; if (SLD_OFF) return; if (traceall_flag) { sprintf(dbuffer, ">> %s", idp->name); log_print(dbuffer); if (idp_tp->form == ARRAY_FORM || idp_tp->form == BAG_FORM || idp_tp->form == LIST_FORM || idp_tp->form == SET_FORM ) { log_print("[*]"); } else if (idp_tp->form == ENTITY_FORM) { log_print(".*"); } print_data_value_debug(datap, tp, "="); } /* check if variable is being watched for fetches */ else if ((idp->info != NULL) && ((WATCH_STRUCT_PTR) idp->info)->fetch_flag) { printf("\nAt %d: Fetch %s", exec_line_number, idp->name); if (idp_tp->form == ARRAY_FORM || idp_tp->form == BAG_FORM || idp_tp->form == LIST_FORM || idp_tp->form == SET_FORM ) { printf("[*]"); } else if (idp_tp->form == ENTITY_FORM) { printf(".*"); } print_data_value(datap, tp, "="); } return; } /* end trace_data_fetch */ /********************************************************************/ /* PRINTING ROUTINES */ /********************************************************************/ /* print_statement() Uncrunch and print a statement */ print_statement() { int tk; /* token code */ BOOLEAN done = FALSE; ICT *csp = statement_startp; /* entry_debug("print_statement"); */ printf("\nAt %3d:", exec_line_number); do { switch (tk = *csp++) { case SEMICOLON: case END: case ELSE: case THEN: case UNTIL: case BEGIN: case OF: case STATEMENT_MARKER: { done = TRUE; break; } default: { done = FALSE; switch(tk) { case ADDRESS_MARKER: { csp++; break; } case IDENTIFIER: case NUMBER_LITERAL: case STRING_LITERAL: { SYMTAB_NODE_PTR np = *((SYMTAB_NODE_PTR *) csp); printf(" %s", np->name); csp++; break; } default: { printf(" %s", symbol_strings[tk]); break; } } /* end switch */ } } /* end switch */ } while (!done); /* end do */ printf("\n"); /* exit_debug("print_statement"); */ } /* end print_statement */ /********************************************************************/ /********************************************************************/ /* print_line_number() Print the current line number */ print_line_number() { printf("<%d>", exec_line_number); } /* end print_line_number */ /********************************************************************/ /********************************************************************/ /* print_data_value(datap, tp, str) Print a data value */ print_data_value(datap, tp, str) STACK_ITEM_PTR datap; /* ptr to data value */ TYPE_STRUCT_PTR tp; /* ptr to type of stack item */ char *str; /* " = " or " := " */ { STACK_TYPE stype; LOGICAL_REP log; TYPE_FORM form; form = tp->form; if (form == ARRAY_FORM || form == BAG_FORM || form == LIST_FORM || form == SET_FORM || form == ENTITY_FORM ) { printf(" %s <%s>\n", str, form2str[form]); return; } stype = get_stackval_type(datap); if (stype == STKUDF) { printf(" %s %c\n", str, get_undef(datap)); } else if (stype == STKINT) { printf(" %s %d\n", str, get_integer(datap)); } else if (stype == STKREA) { printf(" %s %0.6g\n", str, get_real(datap)); } else if (stype == STKLOG) { log = get_logical(datap); if (log == TRUE_REP) { printf(" %s %s\n", str, "TRUE"); } else if (log == FALSE_REP) { printf(" %s %s\n", str, "FALSE"); } else { printf(" %s %s\n", str, "UNKNOWN"); } } else if (stype == STKSTR) { printf(" %s %s\n", str, get_stacked_string(datap)); } return; } /* end print_data_value */ /********************************************************************/ /********************************************************************/ /* print_data_value_debug(datap, tp, str) Print a data value */ print_data_value_debug(datap, tp, str) STACK_ITEM_PTR datap; /* ptr to data value */ TYPE_STRUCT_PTR tp; /* ptr to type of stack item */ char *str; /* " = " or " := " */ { STACK_TYPE stype; LOGICAL_REP log; TYPE_FORM form; form = tp->form; if (form == ARRAY_FORM || form == BAG_FORM || form == LIST_FORM || form == SET_FORM || form == ENTITY_FORM ) { sprintf(dbuffer, " %s <%s>\n", str, form2str[form]); log_print(dbuffer); return; } stype = get_stackval_type(datap); if (stype == STKUDF) { sprintf(dbuffer, " %s %c\n", str, get_undef(datap)); log_print(dbuffer); } else if (stype == STKINT) { sprintf(dbuffer, " %s %d\n", str, get_integer(datap)); log_print(dbuffer); } else if (stype == STKREA) { sprintf(dbuffer, " %s %0.6g\n", str, get_real(datap)); log_print(dbuffer); } else if (stype == STKLOG) { log = get_logical(datap); if (log == TRUE_REP) { sprintf(dbuffer, " %s %s\n", str, "TRUE"); } else if (log == FALSE_REP) { sprintf(dbuffer, " %s %s\n", str, "FALSE"); } else { sprintf(dbuffer, " %s %s\n", str, "UNKNOWN"); } log_print(dbuffer); } else if (stype == STKSTR) { sprintf(dbuffer, " %s %s\n", str, get_stacked_string(datap)); log_print(dbuffer); } return; } /* end print_data_value_debug */ /********************************************************************/ /* BREAKPOINTS AND WATCHES */ /********************************************************************/ /* set_breakpoint() Set a breakpoint, or print all breakpoints in */ /* the break list */ set_breakpoint() { int i, number; get_token(); switch (token) { case SEMICOLON: { /* no line number --- list all breakpoints */ printf("Statement breakpoints at:\n"); for (i = 0; i < break_count; i++) { printf("%5d\n", break_list[i]); } break; } case NUMBER_LITERAL: { /* set breakpoint by appending to list */ if (literal.type == INTEGER_LIT) { number = literal.value.integer; if ((number > 0) && (number <= line_number)) { if (break_count < MAX_BREAKS) { break_list[break_count] = number; ++break_count; } else { printf("Break list is full.\n"); } } else { error(VALUE_OUT_OF_RANGE); } } else { error(UNEXPECTED_TOKEN); } get_token(); break; } } /* end switch */ } /* end set_breakpoint */ /********************************************************************/ /********************************************************************/ /* remove_breakpoint() Remove a specified breakpoint, or all */ remove_breakpoint() { int i, j, number; get_token(); switch (token) { case SEMICOLON: { /* no line number --- remove all breakpoints */ for (i = 0; i < break_count; i++) { break_list[i] = 0; } break_count = 0; break; } case NUMBER_LITERAL: { /* remove breakpoint from list, and move others up */ if (literal.type == INTEGER_LIT) { number = literal.value.integer; if (number > 0) { for (i = 0; i < break_count; i++) { if (break_list[i] == number) { break_list[i] = 0; --break_count; for (j = i; j < break_count; j++) { break_list[j] = break_list[j+1]; } } } } } else { error(VALUE_OUT_OF_RANGE); } get_token(); break; } } /* end switch */ } /* end remove_breakpoint */ /********************************************************************/ /********************************************************************/ /* allocate_watch() Return a pointer to a watch structure, */ /* or print all variables being watched */ WATCH_STRUCT_PTR allocate_watch() { int i; SYMTAB_NODE_PTR idp; WATCH_STRUCT_PTR wp; get_token(); switch (token) { case SEMICOLON: { /* no variable, print them all */ printf("Variables being watched:\n"); for (i = 0; i < watch_count; i++) { idp = watch_list[i]; if (idp != NULL) { wp = (WATCH_STRUCT_PTR) idp->info; printf("%16s ", idp->name); if (wp->store_flag) printf(" (store)"); if (wp->fetch_flag) printf(" (fetch)"); printf("\n"); } } return(NULL); } case IDENTIFIER: { search_and_find_all_symtab(idp); get_token(); switch (idp->defn.key) { case UNDEFINED: { return(NULL); } case CONST_DEFN: case VAR_DEFN: case ATTRIBUTE_DEFN: case VALPARM_DEFN: case VARPARM_DEFN: { if (idp->info != NULL) { /* being watched, return ptr to structure */ return((WATCH_STRUCT_PTR) idp->info); } else if (watch_count < MAX_WATCHES) { /* a new structure */ wp = alloc_struct(WATCH_STRUCT); wp->store_flag = FALSE; wp->fetch_flag = FALSE; idp->info = (char *) wp; watch_list[watch_count] = idp; watch_count++; return(wp); } else { printf("Watch list is full.\n"); return(NULL); } } default: { error(INVALID_IDENTIFIER_USAGE); return(NULL); } } /* end switch */ break; } } /* end switch */ } /* end allocate_watch */ /********************************************************************/ /********************************************************************/ /* remove_watch() Remove a variable from the watch list, */ /* or remove all variables being watched */ remove_watch() { int i, j; SYMTAB_NODE_PTR idp; WATCH_STRUCT_PTR wp; get_token(); switch (token) { case SEMICOLON: { /* no variable, remove them all */ for (i = 0; i < watch_count; i++) { if ((idp = watch_list[i]) != NULL) { wp = (WATCH_STRUCT_PTR) idp->info; watch_list[i] = NULL; idp->info = NULL; free(wp); } } watch_count = 0; break; } case IDENTIFIER: { /* remove it from the list and move other up */ search_and_find_all_symtab(idp); get_token(); if ((idp != NULL) && (idp->info != NULL)) { wp = (WATCH_STRUCT_PTR) idp->info; for (i = 0; i < watch_count; i++) { if (watch_list[i] == idp) { watch_list[i] = NULL; idp->info = NULL; free(wp); --watch_count; for (j = i; j < watch_count; j++) { watch_list[j] = watch_list[j + 1]; } break; } } } break; } } /* end switch */ } /* end remove_watch */ /********************************************************************/ /* SHOW and ASSIGN */ /********************************************************************/ /* show-value() Print the value of an expression */ show_value() { get_token(); switch (token) { case SEMICOLON: { error(INVALID_EXPRESSION); break; } default: { /* parse and execute expression from code buffer */ TYPE_STRUCT_PTR expression(); TYPE_STRUCT_PTR tp = expression(); /* parse */ ICT *save_code_segmentp = code_segmentp; int save_ctoken = ctoken; if (isynt_error_count > 0) break; /* switch to the code buffer */ code_segmentp = code_buffer + 1; get_ctoken(); exec_expression(); /* execute */ /* print and then pop the value */ if ((tp->form == ARRAY_FORM) || (tp->form == BAG_FORM) || (tp->form == LIST_FORM) || (tp->form == SET_FORM) || (tp->form == ENTITY_FORM)) { print_data_value(get_address(tos), tp, " "); } else { print_data_value(tos, tp, " "); } pop(); /* resume the code segment */ code_segmentp = save_code_segmentp; ctoken = save_ctoken; break; } } /* end switch */ } /* end show_value */ /********************************************************************/ /********************************************************************/ /* assign_variable() Exexcute an assignment statement */ assign_variable() { get_token(); switch (token) { case SEMICOLON: { error(MISSING_VARIABLE); break; } case IDENTIFIER : { /* parse and execute the assignment statement from code buffer */ SYMTAB_NODE_PTR idp; ICT *save_code_segmentp = code_segmentp; int save_ctoken = ctoken; search_and_find_all_symtab(idp); assignment_statement(idp); /* parse */ if (isynt_error_count > 0) break; /* switch to the code buffer */ code_segmentp = code_buffer + 1; get_ctoken(); idp = get_symtab_cptr(); exec_assignment_statement(idp); /* execute */ /* resume the code segment */ code_segmentp = save_code_segmentp; ctoken = save_ctoken; break; } } /* end switch */ } /* end assign_variable */ /********************************************************************/ /* STACK */ /********************************************************************/ /* stack_debug() Print runtime stack */ extern STACK_ITEM *stack; /* runtime stack */ extern STACK_ITEM_PTR tos; /* top of stack */ extern STACK_ITEM_PTR stack_frame_basep; /* ptr to stack frame base */ extern STACK_ITEM_PTR maxtos; /* current max top of stack */ stack_debug() { STACK_ITEM_PTR basep = stack; /* base of stack */ STACK_ITEM_PTR i; if (!stack_flag) return; log_print("\n The runtime stack with: "); stack_frame_debug(); for (i = basep; i <= tos; i++) { stack_item_debug(i); } return; } /* end stack_debug */ /********************************************************************/ /********************************************************************/ /* tos_debug() Print top of runtime stack */ tos_debug() { if (!stack_flag) return; log_print(" Top of runtime stack."); stack_item_debug(tos); return; } /* end tos_debug */ /********************************************************************/ /********************************************************************/ /* stack_access_debug(s, sptr) Print stack access kind */ stack_access_debug(s, sptr) char s[]; /* access kind */ STACK_ITEM_PTR sptr; /* stack position */ { if (!stack_flag) return; sprintf(dbuffer, " %-7s ==>", s); log_print(dbuffer); stack_item_debug(sptr); if (sptr > maxtos) { /* probably looking at data area */ log_print(" Accessed data area:\n"); data_item_debug(sptr); } return; } /* end stack_access_debug */ /********************************************************************/ /********************************************************************/ /* stack_item_debug(sptr) Print a runtime stack item */ stack_item_debug(sptr) STACK_ITEM_PTR sptr; /* ptr to stack item */ { STACK_TYPE stype; if (!stack_flag) return; if ((sptr < stack) || (sptr > maxtos)) { /* out of stack range */ runtime_warning(INVALID_STACK_ACCESS); } stype = sptr->type; switch (stype) { case STKINT: { sprintf(dbuffer, " (Entry %d : %s is %d)\n", sptr, stack2str[stype], sptr->value.integer); log_print(dbuffer); break; } case STKREA: { sprintf(dbuffer, " (Entry %d : %s is %f)\n", sptr, stack2str[stype], sptr->value.real); log_print(dbuffer); break; } case STKLOG: { sprintf(dbuffer, " (Entry %d : %s is ", sptr, stack2str[stype]); log_print(dbuffer); if (sptr->value.integer == FALSE_REP) sprintf(dbuffer, "FALSE)\n"); else if (sptr->value.integer == TRUE_REP) sprintf(dbuffer, "TRUE)\n"); else sprintf(dbuffer, "UNKNOWN)\n"); log_print(dbuffer); break; } case STKSTR: { sprintf(dbuffer, " (Entry %d : %s is %d)\n", sptr, stack2str[stype], sptr->value.string); log_print(dbuffer); break; } case STKARY: case STKADD: { sprintf(dbuffer, " (Entry %d : %s is %d)\n", sptr, stack2str[stype], sptr->value.address); log_print(dbuffer); break; } case STKUDF: { /* undefined */ sprintf(dbuffer, " (Entry %d : %s is '%c')\n", sptr, stack2str[stype], sptr->value.integer); log_print(dbuffer); break; } case STKBAG: case STKLST: case STKSET: { sprintf(dbuffer, " (Entry %d : %s is %d)\n", sptr, stack2str[stype], sptr->value.head); log_print(dbuffer); break; } case STKENT: { sprintf(dbuffer, " (Entry %d : %s is %d)\n", sptr, stack2str[stype], sptr->value.address); log_print(dbuffer); break; } default: { sprintf(dbuffer, " (Entry %d : unknown type (%d))\n", sptr, sptr->type); log_print(dbuffer); break; } } return; } /* end stack_item_debug */ /********************************************************************/ /********************************************************************/ /* data_item_debug(sptr) Print data of array/entity item */ data_item_debug(sptr) STACK_ITEM_PTR sptr; /* ptr to 'start' of data item */ { STACK_TYPE kind; STACK_ITEM_PTR aptr = sptr; int n = 1; int maxn = 20; /* max number of elements to be printed */ if (!stack_flag) return; kind = aptr->type; while ( (kind >= STKINT) && (kind <= STKADD) && (n <= maxn) ) { stack_item_debug(aptr); aptr++; n++; kind = aptr->type; } return; } /* end data_item_debug */ /********************************************************************/ /********************************************************************/ /* stack_frame_debug() print the stack frame base pointer */ stack_frame_debug() { if (!stack_flag) return; sprintf(dbuffer, " (Stack frame base at %d)\n", stack_frame_basep); log_print(dbuffer); return; } /* end stack_frame_debug */ /********************************************************************/ /********************************************************************/ /* expression_type_debug(tptr) print type of type */ extern TYPE_STRUCT_PTR integer_typep, real_typep, boolean_typep; extern TYPE_STRUCT_PTR logical_typep, string_typep, binary_typep, generic_typep, any_typep; expression_type_debug(tptr) TYPE_STRUCT_PTR tptr; /* pointer to type structure */ { if (!stack_flag) return; if (tptr == integer_typep) { log_print(" Type is: INTEGER TYPE\n"); return; } else if (tptr == real_typep) { log_print(" Type is: REAL TYPE\n"); return; } else if (tptr == boolean_typep) { log_print(" Type is: BOOLEAN TYPE\n"); return; } else if (tptr == logical_typep) { log_print(" Type is: LOGICAL TYPE\n"); return; } else if (tptr == string_typep) { log_print(" Type is: STRING TYPE\n"); return; } else if (tptr == binary_typep) { log_print(" Type is: BINARY TYPE\n"); return; } else if (tptr == generic_typep) { log_print(" Type is: GENERIC TYPE\n"); return; } else if (tptr == any_typep) { log_print(" Type is: INDETERMINATE TYPE\n"); return; } switch (tptr->form) { case NO_FORM: { log_print(" Type is: NO FORM\n"); return; } case SCALAR_FORM: { log_print(" Type is: SCALAR FORM\n"); return; } case ENUM_FORM: { log_print(" Type is: ENUM FORM\n"); return; } case SUBRANGE_FORM: { log_print(" Type is: SUBRANGE FORM\n"); return; } case ARRAY_FORM: { log_print(" Type is: ARRAY of "); expression_type_debug(tptr->info.array.elmt_typep); return; } case BAG_FORM: { log_print(" Type is: BAG of "); expression_type_debug(tptr->info.dynagg.elmt_typep); return; } case LIST_FORM: { log_print(" Type is: LIST of "); expression_type_debug(tptr->info.dynagg.elmt_typep); return; } case SET_FORM: { log_print(" Type is: SET of "); expression_type_debug(tptr->info.dynagg.elmt_typep); return; } case ENTITY_FORM: { log_print(" Type is: ENTITY FORM\n"); return; } case STRING_FORM: { log_print(" Type is: STRING FORM\n"); return; } default: { log_print(" Type is: UNKNOWN\n"); return; } } /* end switch */ } /* end expression_type_debug */ /********************************************************************/