/* xyz */ /* * Copyright (c) 1991, 1992, 1993, 1994, 1995 by Wayne C. Gramlich. * All rights reserved. * * Permission to use, copy, modify, distribute, and sell this software * for any purpose is hereby granted without fee provided that the above * copyright notice and this permission are retained. The author makes * no representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. */ /* The command loop for the debugger: */ #ifndef ERROR_EXPORTS_H #include "error_exports.h" #endif #ifndef FILE_DEFS_H #include "file_defs.h" #endif #ifndef HEAP_EXPORTS_H #include "heap_exports.h" #endif #ifndef LINT_H #include "lint.h" #endif #ifndef LIBC_EXPORTS_H #include "libc_exports.h" #endif #ifndef ROUTINE_INFO_DEFS_H #include "routine_info_defs.h" #endif #ifndef RUN_TIME_DEFS_H #include "run_time_defs.h" #endif #ifndef STHEADERS_H #include "stheaders.h" #endif #ifndef STR_EXPORTS_H #include "str_exports.h" #endif #ifndef UNIX_ASSERT_H #include "unix_assert.h" #endif #ifndef UNIX_CTYPE_H #include "unix_ctype.h" #endif /* #ifndef UNIX_DLFCN_H */ /* #include "unix_dlfcn.h" */ /* #endif */ #ifndef UNIX_FCNTL_H #include "unix_fcntl.h" #endif #ifndef UNIX_MEMORY_H #include "unix_memory.h" #endif #ifndef UNIX_SYS_STAT_H #include "unix_sys_stat.h" #endif #ifndef UNIX_STDLIB_H #include "unix_stdlib.h" #endif #ifndef UNIX_UNISTD_H #include "unix_unistd.h" #endif #ifndef VECTOR_DEFS_H #include "vector_defs.h" #endif typedef void *Out_stream; Out_stream out_stream__standard; /* Total kludge (common symbol */ extern Run_time run__time__global; LOCAL void alias_command(Run_time); LOCAL int alias_compare(Alias, Alias, int); LOCAL void button_command(Run_time); LOCAL void cd_command(Run_time); LOCAL int continue_command(Run_time); LOCAL void debug_command(Run_time); LOCAL void delete_command(Run_time); LOCAL void echo_command(Run_time); LOCAL void help_command(Run_time); LOCAL void in_command(Run_time); LOCAL void module_command(Run_time); LOCAL void out_command(Run_time); LOCAL void print_command(Run_time); LOCAL void printenv_command(Run_time); LOCAL void quit_command(Run_time); LOCAL void rerun_command(Run_time); LOCAL void run_command(Run_time); LOCAL void setenv_command(Run_time); LOCAL void show_command(Run_time); LOCAL void source_command(Run_time); LOCAL void stack_command(Run_time); LOCAL void status_command(Run_time); LOCAL int step_command(Run_time); LOCAL int step_in_command(Run_time); LOCAL int step_out_command(Run_time); LOCAL int step_over_command(Run_time); LOCAL int step_to_command(Run_time); LOCAL void stop_at_command(Run_time); LOCAL void stop_command(Run_time); LOCAL void stop_in_command(Run_time); LOCAL void unalias_command(Run_time); LOCAL void unbutton_command(Run_time); LOCAL void undebug_command(Run_time); LOCAL void unstop_at_command(Run_time); LOCAL void unstop_command(Run_time); LOCAL void unstop_in_command(Run_time); LOCAL void unsetenv_command(Run_time); /* * alias_command(run_time) * This routine will parse and execute an alias command. */ LOCAL void alias_command( Run_time run_time) { Alias alias; Vec(Alias) aliases; Str command; int index; Str name; int size; if (run__time__eol_test(run_time)) { run__time__eol_read(run_time); aliases = run_time->aliases; vec_sort(Alias, aliases, alias_compare, 0); size = vec_size(Alias, aliases); for (index = 0; index < size; index++) { alias = vec_fetch(Alias, aliases, index); (void)printf("%8s - %s\n", alias->name, alias->command); } } else { name = run__time__argument_read(run_time, "No alias name"); command = run__time__argument_read(run_time, "No alias value"); run__time__eol_read(run_time); if (command != (Str)0) { run__time__alias_set(run_time, name, command); } } } /* * alias_compare(alias1, alias2, zilch) * This routine will return -1, 0, or 1, depending upon whether the * name of "alias1" is lexically less than, equal to, or greater than * the name of "alias2". */ /* ARGSUSED */ LOCAL int alias_compare( Alias alias1, Alias alias2, int zilch) { return strcmp(alias1->name, alias2->name); } /* * button_command(run_time) * This routine will parse and execute a button command. */ LOCAL void button_command( Run_time run_time) { Str button_name; Dbx_button selection; Str selection_name; int chr; selection_name = run__time__argument_read(run_time, "No selection specified"); chr = run__time__chr_non_white_peek(run_time); if ((chr == '"') || (chr == '\'')) { button_name = run__time__string_read(run_time, "No button name specified"); } else { button_name = run__time__argument_read(run_time, "No button name specfied"); } run__time__eol_read(run_time); if (button_name == (Str)0) { /* Error already printed */ return; } if (strequal(selection_name, "ignore")) { selection = Dbx_button_ignore; } else if (strequal(selection_name, "expand")) { selection = Dbx_button_expand; } else if (strequal(selection_name, "literal")) { selection = Dbx_button_literal; } else { (void)fprintf(stderr, "`%s' is not a valid button selection; " "try `ignore' instead!\n", selection_name); return; } run__time__button(run_time, button_name, selection); } /* * cd_command(run_time) * This routine will parse and execute a cd command. */ LOCAL void cd_command( Run_time run_time) { char buffer[2000]; Str directory; directory = run__time__argument_read(run_time, "No directory specified"); run__time__eol_read(run_time); if (chdir(directory) != 0) { (void)fprintf(stderr, "Could not change directory to `%s'!\n", directory); return; } assert(getcwd(buffer, sizeof buffer) != (Str)0); run_time->directory = strdupl(buffer, run_time->heap); if (run_time->last_in_file != (Stdio)0) { (void)fclose(run_time->last_in_file); } run_time->last_file_name = (Str)0; run_time->last_in_file = (Stdio)0; run_time->last_module = (module___object *)0; } /* * continue_command(run_time) * This routine will parse and execute a continue command. */ LOCAL int continue_command( Run_time run_time) { activation___object *activation; routine___object *routine; routine__info__type routine_info; run__time__eol_read(run_time); run_time->run_mode = Run_mode_continue; activation = run_time->leaf_activation; if (activation == (activation___object *)0) { return 1; } routine = activation->routine; routine_info = run__time__routine_info_get(run_time, routine); activation->breakpoints = routine_info->breakpoints; return 1; } /* * debug_command(run_time) * This routine will parse and execute a debug command. */ LOCAL void debug_command( Run_time run_time) { char command[2000]; int fd; Stdio pipe_file; Str program; /* Read in the program name: */ program = run__time__argument_read(run_time, "No program name specified"); run__time__eol_read(run_time); if (program == (Str)0) { /* Error already printed. */ return; } /* Verify that the file exists: */ fd = open(program, O_RDONLY, 0); if (fd < 0) { (void)fprintf(stderr, "`%s' does not appear to be a program!\n", program); return; } (void)close(fd); #ifdef OLD /* Verify that the file is linked w/libstipple.so: */ (void)sprintf(command, "ldd %s | grep libstipple", program); pipe_file = popen(command, "r"); assert(pipe_file != (Stdio)0); if (getc(pipe_file) == EOF) { (void)fprintf(stderr, "Program `%s' does not appear " "to be a STIPPLE program!\n", program); return; } (void)fclose(pipe_file); #endif /* OLD */ /* We should close all extraneous fd's here! */ /* Exec the program: */ run__time__env_state_set(run_time, Std_state_ready); run__time__env_str_set(run_time, "STD_ARGC", "0"); run__time__env_str_set(run_time, "STD_NAME", program); run__time__env_int_set(run_time, "STD_PIPE", run_time->pipe_fd); run__time__exec(run_time); assert_fail(); } /* * delete_command(run_time) * This routine will parse and execute a delete command. */ LOCAL void delete_command( Run_time run_time) { Event event; Vec(Event) events; int event_number; int size; event_number = run__time__int_read(run_time, "No event number"); run__time__eol_read(run_time); if (event_number < 0) { /* Error already printed */ return; } events = run_time->events; size = vec_size(Event, events); if (event_number <= size) { event = vec_fetch(Event, events, event_number - 1); if (event->file_name != (Str)0) { event->file_name = (Str)0; return; } } (void)fprintf(stderr, "There is no event %d!\n", event_number); } /* * echo_command(run_time) * This routine will parse and execute an echo command. */ LOCAL void echo_command( Run_time run_time) { Str arg; Vec(Str) args; int index; int size; args = vec_create(Str, run_time->heap); while (!run__time__eol_test(run_time)) { arg = run__time__argument_read(run_time, "No argument"); vec_append(Str, args, arg); } run__time__eol_read(run_time); (void)printf("echo"); size = vec_size(Str, args); for (index = 0; index < size; index++) { arg = vec_fetch(Str, args, index); (void)printf(" %s", arg); } (void)printf("\n"); } /* * help_command(run_time) * This routine will parse and execute the help command. */ LOCAL void help_command( Run_time run_time) { Str *cmds; Debug_cmd debug_cmd; Str *helps; run__time__eol_read(run_time); cmds = &run_time->debug_cmds[0]; helps = &run_time->debug_help[0]; for (debug_cmd = (Debug_cmd)0; debug_cmd < Debug_cmd_last; debug_cmd++) { (void)printf("%10s - %s\n", cmds[(int)debug_cmd], helps[(int)debug_cmd]); } } /* * in_command(run_time) * This routine will parse and execute an in command. */ LOCAL void in_command( Run_time run_time) { activation___object *activation; run__time__eol_read(run_time); if (run_time->leaf_activation == run_time->current_activation) { (void)fprintf(stderr, "Already at deepest frame!\n"); return; } for (activation = run_time->leaf_activation; activation != (activation___object *)0; activation = activation->previous) { if (activation->previous == run_time->current_activation) { run_time->current_activation = activation; break; } } } /* * module_command(run_time) * This routine will parse and execute a module command. */ LOCAL void module_command( Run_time run_time) { int index; module___object *module; Vec(module___object *) modules; Str module_name; int size; modules = run_time->modules; size = vec_size(module___object, modules); if (run__time__eol_test(run_time)) { /* List all modules: */ run__time__eol_read(run_time); for (index = 0; index < size; index++) { module = vec_fetch(module___object *, modules, index); (void)printf("%s %s\n", module->module_name, module->file_name); } } else { /* Goto a selected module: */ module_name = run__time__argument_read(run_time, "No module name specified"); run__time__eol_read(run_time); if (module_name == (Str)0) { /* Error already printed */ return; } for (index = 0; index < size; index++) { module = vec_fetch(module___object *, modules, index); if (strequal(module->module_name, module_name)) { break; } } if (index >= size) { (void)fprintf(stderr,"Could not find module `%s'!\n", module_name); } else { (void)printf("Found it!\n"); } } } /* * out_command(run_time) * This routine will parse and execute an out command. */ LOCAL void out_command( Run_time run_time) { activation___object *activation; run__time__eol_read(run_time); activation = run_time->current_activation; if (activation->previous == (activation___object *)0) { (void)fprintf(stderr, "Already at main()!\n"); return; } activation = activation->previous; run_time->current_activation = activation; } /* * print_command(run_time) * This routine will parse and print a print command. */ LOCAL void print_command( Run_time run_time) { activation___object *activation; int index; routine___object *routine; int size; Str var_name; variable___object *variable; variable___object *variables; var_name = run__time__argument_read(run_time, "No variable specified"); run__time__eol_read(run_time); if (var_name == (Str)0) { /* Error already printed */ return; } activation = run_time->current_activation; routine = activation->routine; variables = routine->variables; size = routine->variables_count; for (index = 0; index < size; index++) { variable = &variables[index]; if ((variable->kind == variable__kind__return) || !strequal(var_name, variable->name)) { continue; } (void)printf("%s = ", var_name); run_time->run_mode = Run_mode_continue; switch (variable->flavor) { case variable__flavor__unparam: { print__unparam__routine print_routine; print_routine = (print__unparam__routine) variable->print_routine; run__time__signals_enable(); (*print_routine)( *((void **)((int)activation->frame + variable->offset)), (void *)out_stream__standard); run__time__signals_disable(); break; } case variable__flavor__static: { print__proc__var *print_routine; print_routine = *((print__proc__var **) variable->print_routine); run__time__signals_enable(); (*print_routine->routine)( *((void **)((int)activation->frame + variable->offset)), (void *)out_stream__standard, print_routine->block); run__time__signals_disable(); break; } case variable__flavor__block: { print__proc__var *print_routine; void *block; block = *((void **)activation->frame); print_routine = *( (print__proc__var **)((int)block + (int)variable->print_routine) ); run__time__signals_enable(); (*print_routine->routine)( *((void **)((int)activation->frame + variable->offset)), (void *)out_stream__standard, print_routine->block); run__time__signals_disable(); break; } default: assert_fail(); } (void)printf("\n"); return; } (void)fprintf(stderr, "`%s' is not a valid variable!\n", var_name); } /* * printenv_command(run_time) * This routine will parse and print a printenv command. */ LOCAL void printenv_command( Run_time run_time) { extern Str *environ; Str env_var; Str *env_vars; run__time__eol_read(run_time); env_vars = environ; while ((env_var = *env_vars++) != (Str)0) { (void)printf("%s\n", env_var); } } /* * pwd_command(run_time) * This routine will parse and execute a pwd command. */ LOCAL void pwd_command( Run_time run_time) { char directory[2000]; run__time__eol_read(run_time); if (getcwd(directory, sizeof(directory)) == (Str)0) { (void)fprintf(stderr, "Could not get current working directory!\n"); } else { (void)printf("%s\n", directory); } } /* * quit_command(run_time) * This routine will parse and execute a quit command. */ LOCAL void quit_command( Run_time run_time) { extern void _exit(int); run__time__eol_read(run_time); run__time__pipe_command(run_time, Dbxtool_cmd_quit); run__time__pipe_integer(run_time, 0); _exit(0); } /* * rerun_command(run_time) * This routine will parse and execut a rerun command. */ LOCAL void rerun_command( Run_time run_time) { run__time__eol_read(run_time); run__time__env_state_set(run_time, Std_state_running); run__time__env_int_set(run_time, "STD_ARGC", 0); run__time__exec(run_time); } /* * run_command(run_time) * This routine will parse and execute a run command. */ LOCAL void run_command( Run_time run_time) { Str arg; int argc; char env_var_name[50]; argc = 0; for (;;) { if (run__time__eol_test(run_time)) { break; } arg = run__time__argument_read(run_time, ""); (void)sprintf(env_var_name, "STD_ARG%d", argc); run__time__env_str_set(run_time, env_var_name, arg); argc++; } run__time__eol_read(run_time); if (argc > 0) { run__time__env_int_set(run_time, "STD_ARGC", argc); } run__time__env_state_set(run_time, Std_state_running); run__time__exec(run_time); } /* * setenv_command(run_time) * This routine will parse and execute a setenv command. */ LOCAL void setenv_command( Run_time run_time) { int chr; Str name; Str value; name = run__time__argument_read(run_time, "No environment variable name specified"); chr = run__time__chr_non_white_peek(run_time); if ((chr == '\'') || (chr == '"')) { value = run__time__string_read(run_time, "Bad environment variable value"); } else { value = run__time__argument_read(run_time, "Bad environment variable value"); } run__time__eol_read(run_time); if (value != (Str)0) { run__time__env_str_set(run_time, name, value); } } /* * show_command(run_time) * This routine will parse and execute a show command. */ LOCAL void show_command( Run_time run_time) { run__time__eol_read(run_time); (void)fprintf(stderr, "`show' not implemented yet!\n"); } /* * source_command(run_time) * This routine will parse and execute a source command. */ LOCAL void source_command( Run_time run_time) { int duplicate; Vec(File) in_file_stack; Str file_name; File new_in_file; int index; int size; File tmp_in_file; in_file_stack = run_time->in_file_stack; file_name = run__time__argument_read(run_time, "No source file name specified"); run__time__eol_read(run_time); if (file_name == (Str)0) { /* Error already printed! */ return; } /* Don't permit recursive source statements: */ duplicate = strequal(file_name, run_time->in_file->file_name); size = vec_size(File, in_file_stack); for (index = 0; index < size; index++) { tmp_in_file = vec_fetch(File, in_file_stack, index); if (strequal(file_name, tmp_in_file->file_name)) { duplicate = 1; break; } } if (duplicate) { (void)fprintf(stderr, "Recursive source commands are not permitted (%s)!\n", file_name); return; } new_in_file = file_open(file_name, 0, run_time->heap); if (new_in_file == (File)0) { (void)fprintf(stderr, "Could not open %s\n", file_name); return; } vec_append(File, in_file_stack, run_time->in_file); run_time->in_file = new_in_file; } /* * stack_command(run_time) * This routine will parse and execute a stack command. */ LOCAL void stack_command( Run_time run_time) { activation___object *activation; activation___object *fault; Vec(activation___object *) faults; int fault_index; routine___object *routine; routine__info__type routine_info; run__time__eol_read(run_time); faults = run_time->faults; fault_index = vec_size(activation___object *, faults) - 1; for (activation = run_time->leaf_activation; activation != (activation___object *)0; activation = activation->previous) { routine = activation->routine; if (fault_index < 0) { fault = (activation___object *)0; } else { fault = vec_fetch(activation___object *, faults, fault_index); } if (activation == fault) { (void)printf("--- ---\n"); fault_index--; } if (activation == run_time->leaf_activation) { (void)printf("=> "); } else if (activation == run_time->current_activation){ (void)printf("-> "); } else { (void)printf(" "); } routine_info = routine->routine_info; assert(routine_info != (routine__info__type)0); (void)printf("%s", routine_info->name); if (!strequal(routine_info->type_name, "global__")) { (void)printf("@%s", routine_info->type_name); } (void)printf("()\n"); } } /* * status_command(run_time) * This routine will parse and execute the status command. */ LOCAL void status_command( Run_time run_time) { Event event; Vec(Event) events; int index; int size; run__time__eol_read(run_time); events = run_time->events; size = vec_size(Event, events); for (index = 0; index < size; index++) { event = vec_fetch(Event, events, index); switch (event->event_kind) { case Event_kind_deleted: break; case Event_kind_stop_at: (void)printf("%3d Stop At \"%s\":%d\n", index + 1, event->file_name, event->line_number); break; case Event_kind_stop_in: if (strequal(event->type_name, "global__")) { (void)printf("%3d Stop In %s\n", index + 1, event->routine_name); } else { (void)printf("%3d Stop In %s@%s\n", index + 1, event->routine_name, event->type_name); } break; default: assert_fail(); } } } /* * step_command(run_time) * This routine will parse and execute a stop command. */ LOCAL int step_command( Run_time run_time) { Str arg; int chr; int result; chr = run__time__chr_non_white_peek(run_time); if ((chr == '\n') || isdigit(chr)) { return step_in_command(run_time); } arg = run__time__argument_read(run_time, "`step' must be followed by `in', `out', `over', `to', or "); run__time__lower_case(arg); if (arg == (Str)0) { /* Error already printed */ result = 0; } else if (strequal(arg, "in")) { result = step_in_command(run_time); } else if (strequal(arg, "out")) { result = step_out_command(run_time); } else if (strequal(arg, "over")) { result = step_over_command(run_time); } else if (strequal(arg, "to")) { result = step_to_command(run_time); } else { (void)fprintf(stderr, "`%s' is not valid after `step'!\n", arg); return 0; } return result; } /* * step_in_command(run_time) * This routine will parse and execute a step_in command. */ LOCAL int step_in_command( Run_time run_time) { activation___object *activation; routine___object *routine; run__time__eol_read(run_time); run_time->run_mode = Run_mode_step_in; activation = run_time->leaf_activation; if (activation == (activation___object *)0) { return 1; } routine = activation->routine; run__time__breakpoints_prepare(run_time, routine); activation->breakpoints = run_time->breakpoints_stop; return 1; } /* * step_out_command(run_time) * This routine will parse and execute a step_out command. */ LOCAL int step_out_command( Run_time run_time) { activation___object *activation; routine___object *routine; run__time__eol_read(run_time); activation = run_time->leaf_activation; routine = activation->routine; run__time__breakpoints_prepare(run_time, routine); activation->breakpoints = run_time->breakpoints_none; run_time->run_mode = Run_mode_step_out; run_time->out_activation = activation; return 1; } /* * step_over_command(run_time) * This routine will parse and execute a step_over command. */ LOCAL int step_over_command( Run_time run_time) { activation___object *activation; routine___object *routine; run__time__eol_read(run_time); run_time->run_mode = Run_mode_step_over; activation = run_time->leaf_activation; if (activation == (activation___object *)0) { return 1; } run_time->over_activation = activation; routine = activation->routine; run__time__breakpoints_prepare(run_time, routine); activation->breakpoints = run_time->breakpoints_stop; return 1; } /* * step_to_command(run_time) * This routine will parse and execute a step_to command. */ LOCAL int step_to_command( Run_time run_time) { /* This code is incomplete: */ run__time__breakpoint_at(run_time, 1); run_time->run_mode = Run_mode_continue; return 1; } /* * stop_at_command(run_time) * This routine will parse and execute a stop_at command. */ LOCAL void stop_at_command( Run_time run_time) { run__time__breakpoint_at(run_time, 1); } /* * stop_command(run_time) * This routine will parse and execute a stop command. */ LOCAL void stop_command( Run_time run_time) { Str in_or_at; in_or_at = run__time__argument_read(run_time, "stop must be followed by either `in' or `at'"); run__time__lower_case(in_or_at); if (in_or_at == (Str)0) { /* Error message already printed. */ run__time__eol_read(run_time); } else if (strequal(in_or_at, "at")) { run__time__breakpoint_at(run_time, 1); } else if (strequal(in_or_at, "in")) { run__time__breakpoint_in(run_time, 1); } else { (void)fprintf(stderr, "`%s' is not `in' or `at'!\n", in_or_at); run__time__eol_read(run_time); } } /* * stop_in_command(run_time) * This routine will parse and execute a stop_at command. */ LOCAL void stop_in_command( Run_time run_time) { run__time__breakpoint_in(run_time, 1); } /* * unalias_command(run_time) * This routine will parse and execute an unalias command. */ LOCAL void unalias_command( Run_time run_time) { Alias alias; Vec(Alias) aliases; int index; Str name; int size; name = run__time__argument_read(run_time, "No alias name specified"); run__time__eol_read(run_time); if (name == (Str)0) { /* Error already printed. */ return; } aliases = run_time->aliases; size = vec_size(Alias, aliases); for (index = 0; index < size; index++) { alias = vec_fetch(Alias, aliases, index); if (strequal(name, alias->name)) { break; } } if (index >= size) { (void)fprintf(stderr, "`%s' is not in alias table!\n", name); } else { vec_delete(Alias, aliases, index); } } /* * unbutton_command(run_time) * This routine will parse and execute an unbutton command. */ LOCAL void unbutton_command( Run_time run_time) { Str button_name; int chr; chr = run__time__chr_non_white_peek(run_time); if ((chr == '"') || (chr == '\'')) { button_name = run__time__string_read(run_time, "No button name specified"); } else { button_name = run__time__argument_read(run_time, "No button name specfied"); } run__time__eol_read(run_time); if (button_name == (Str)0) { /* Error already printed */ return; } run__time__unbutton(run_time, button_name); } /* * undebug_command(run_time) * This routine will parse and execute an undebug command. */ LOCAL void undebug_command( Run_time run_time) { run__time__eol_read(run_time); run__time__env_state_set(run_time, Std_state_none); /* We really should exec std here to free up swap! */ } /* * unsetenv_command(run_time) * This routine will parse and execute an unsetenv command. */ LOCAL void unsetenv_command( Run_time run_time) { Str name; name = run__time__argument_read(run_time, "No environment variable specified"); run__time__eol_read(run_time); if (name != (Str)0) { if (run__time__env_delete(run_time, name)) { (void)fprintf(stderr, "`%s' is not an" " enviroment variable!\n", name); } } } /* * unstop_at_command(run_time) * This routine will parse and execute a unstop_at command. */ LOCAL void unstop_at_command( Run_time run_time) { run__time__breakpoint_at(run_time, 0); } /* * unstop_command(run_time) * This routine will parse and execute an unstop command. */ LOCAL void unstop_command( Run_time run_time) { Str arg; arg = run__time__argument_read(run_time, "`unstop' must be followed by `at' or `in'"); run__time__lower_case(arg); if (arg == (Str)0) { /* Error already printed. */ return; } else if (strequal(arg, "at")) { run__time__breakpoint_at(run_time, 0); } else if (strequal(arg, "in")) { run__time__breakpoint_in(run_time, 0); } else { (void)fprintf(stderr, "`%s' is not valid; use `in' or `at' instead!\n", arg); } } /* * unstop_in_command(run_time) * This routine will parse and execute a unstop_at command. */ LOCAL void unstop_in_command( Run_time run_time) { run__time__breakpoint_in(run_time, 0); } /* * run__time__cmd_loop() * This routine performs the debugger command loop. */ void run__time__cmd_loop(void) { activation___object *activation; Alias alias; Vec(Alias) aliases; Str cmd; Str *cmds; activation___object *current_activation; Debug_cmd debug_cmd; int do_prompt; Vec(File) in_file_stack; int index; activation___object *last_activation; routine___object *routine; routine__info__type routine_info; Run_time run_time; int size; /* Prompt the user for a command: */ run__time__signals_disable(); run_time = run__time__global; activation = run_time->leaf_activation; if (activation != (activation___object *)0) { int line_number; routine = activation->routine; routine_info = run__time__routine_info_get(run_time, routine); line_number = vec_fetch(int, routine_info->line_numbers, activation->breakpoint); run__time__line_display(run_time, routine, line_number, 0); } last_activation = run_time->leaf_activation; aliases = run_time->aliases; in_file_stack = run_time->in_file_stack; cmds = &run_time->debug_cmds[0]; do_prompt = 1; for (;;) { current_activation = run_time->current_activation; if ((run_time->leaf_activation != (activation___object *)0) && (current_activation != (activation___object *)0) && (current_activation != last_activation)) { int breakpoint; int line_number; last_activation = run_time->current_activation; routine = last_activation->routine; routine_info = run__time__routine_info_get(run_time, routine); breakpoint = last_activation->breakpoint; line_number = vec_fetch(int, routine_info->line_numbers, breakpoint); run__time__line_display(run_time, routine, line_number, 1); } do_prompt = 1; if (vec_empty(File, in_file_stack)) { switch (run_time->eol_chr) { case EOF: do_prompt = 0; break; case '\n': break; case ';': do_prompt = 0; break; default: assert_fail(); } } else { do_prompt = 0; } if (do_prompt) { (void)fprintf(stdout, "(std) "); (void)fflush(stdout); } else if (run_time->echo && !vec_empty(File, in_file_stack)) { (void)fprintf(stdout, "(std%d) ", vec_size(File, in_file_stack)); (void)fflush(stdout); } /* Read the command name: */ if (run__time__eol_test(run_time)) { run__time__eol_read(run_time); continue; } cmd = run__time__argument_read(run_time, "Command error"); if (cmd == (Str)0) { run__time__eol_read(run_time); continue; } /* Perform any alias substitution: */ run__time__lower_case(cmd); size = vec_size(Alias, aliases); for (index = 0; index < size; index++) { alias = vec_fetch(Alias, aliases, index); if (strequal(alias->name, cmd)) { cmd = alias->command; break; } } /* Search for the command: */ for (debug_cmd = (Debug_cmd)0; debug_cmd < Debug_cmd_last; debug_cmd++) { if (strequal(cmd, cmds[(int)debug_cmd])) { break; } } if (debug_cmd == Debug_cmd_last) { (void)fprintf(stderr, "`%s' is not a valid command!\n", cmd); run__time__eol_read(run_time); continue; } /* The following commands are always permitted: */ switch (debug_cmd) { case Debug_cmd_alias: alias_command(run_time); continue; case Debug_cmd_button: button_command(run_time); continue; case Debug_cmd_cd: cd_command(run_time); continue; case Debug_cmd_debug: debug_command(run_time); continue; case Debug_cmd_echo: echo_command(run_time); continue; case Debug_cmd_help: help_command(run_time); continue; case Debug_cmd_printenv: printenv_command(run_time); continue; case Debug_cmd_pwd: pwd_command(run_time); continue; case Debug_cmd_quit: quit_command(run_time); continue; case Debug_cmd_setenv: setenv_command(run_time); continue; case Debug_cmd_source: source_command(run_time); continue; case Debug_cmd_unalias: unalias_command(run_time); continue; case Debug_cmd_unbutton: unbutton_command(run_time); continue; case Debug_cmd_unsetenv: unsetenv_command(run_time); continue; } /* No other commands are permitted until program is loaded. */ if (run_time->std_state == Std_state_none) { run__time__eol_read(run_time); (void)fprintf(stderr, "Please use `debug' command " "to load a program first!\n"); continue; } /* * These commands are additionally permitted before and * after execution. */ switch (debug_cmd) { case Debug_cmd_delete: delete_command(run_time); continue; case Debug_cmd_module: module_command(run_time); continue; case Debug_cmd_rerun: rerun_command(run_time); continue; case Debug_cmd_run: run_command(run_time); continue; case Debug_cmd_stack: stack_command(run_time); continue; case Debug_cmd_status: status_command(run_time); continue; case Debug_cmd_stop: stop_command(run_time); continue; case Debug_cmd_stop_at: stop_at_command(run_time); continue; case Debug_cmd_stop_in: stop_in_command(run_time); continue; case Debug_cmd_undebug: undebug_command(run_time); continue; case Debug_cmd_unstop: unstop_command(run_time); continue; case Debug_cmd_unstop_at: unstop_at_command(run_time); continue; case Debug_cmd_unstop_in: unstop_in_command(run_time); continue; } /* Some commands still work even with a dead program: */ switch (debug_cmd) { case Debug_cmd_in: in_command(run_time); continue; case Debug_cmd_out: out_command(run_time); continue; case Debug_cmd_print: print_command(run_time); continue; case Debug_cmd_show: show_command(run_time); continue; } /* We are either running or the program failed horribly: */ switch (run_time->std_state) { case Std_state_done: (void)fprintf(stderr, "Program execution terminated!\n"); /* FALLTHRU */ case Std_state_ready: (void)fprintf(stderr, "Please use `run' or `rerun' command " "to start program execution!\n"); run__time__eol_read(run_time); continue; } if (run_time->std_state == Std_state_failed) { (void)fprintf(stderr, "Program encountered a fatal failure. " "Execution can not be resumed!\n"); run__time__eol_read(run_time); continue; } /* We must be running, all other commands are OK: */ assert(run_time->std_state == Std_state_running); switch (debug_cmd) { case Debug_cmd_continue: if (continue_command(run_time)) { goto resume; } continue; case Debug_cmd_step: if (step_command(run_time)) { goto resume; } continue; case Debug_cmd_step_in: if (step_in_command(run_time)) { goto resume; } continue; case Debug_cmd_step_out: if (step_out_command(run_time)) { goto resume; } continue; case Debug_cmd_step_over: if (step_over_command(run_time)) { goto resume; } continue; case Debug_cmd_step_to: if (step_to_command(run_time)) { goto resume; } continue; } /* All commands should be dispatched by here! */ assert_fail(); } /* Resume execution: */ resume: run__time__signals_enable(); }