X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fcli%2Fcli-script.c;h=5903015be33e9b3b35d34c244cd4147f8ddbc917;hb=3bd0f5efd1910d53733ff9962deee99d7e45d1de;hp=1a91d2dd1865c8b9d6c43060609a4d0f99c316d9;hpb=c03c782ff0dad9272576c5099eec29f7c001602c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 1a91d2dd18..5903015be3 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -1,14 +1,14 @@ /* GDB CLI command scripting. - Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, - 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free - Software Foundation, Inc. + Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, + 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, + 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,9 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "value.h" @@ -30,30 +28,46 @@ #include "gdb_string.h" #include "exceptions.h" #include "top.h" +#include "breakpoint.h" #include "cli/cli-cmds.h" #include "cli/cli-decode.h" #include "cli/cli-script.h" #include "gdb_assert.h" -/* Prototypes for local functions */ +#include "python/python.h" + +/* Prototypes for local functions. */ static enum command_control_type - recurse_read_control_structure (struct command_line *current_cmd); +recurse_read_control_structure (char * (*read_next_line_func) (void), + struct command_line *current_cmd, + void (*validator)(char *, void *), + void *closure); static char *insert_args (char *line); static struct cleanup * setup_user_args (char *p); -static void validate_comname (char *); +static char *read_next_line (void); -/* Level of control structure. */ +/* Level of control structure when reading. */ static int control_level; +/* Level of control structure when executing. */ +static int command_nest_depth = 1; + +/* This is to prevent certain commands being printed twice. */ +static int suppress_next_print_command_trace = 0; + /* Structure for arguments to user defined functions. */ #define MAXUSERARGS 10 struct user_args { struct user_args *next; + /* It is necessary to store a malloced copy of the command line to + ensure that the arguments are not overwritten before they are + used. */ + char *command; struct { char *arg; @@ -73,8 +87,9 @@ build_command_line (enum command_control_type type, char *args) { struct command_line *cmd; - if (args == NULL) + if (args == NULL && (type == if_control || type == while_control)) error (_("if/while commands require arguments.")); + gdb_assert (args != NULL); cmd = (struct command_line *) xmalloc (sizeof (struct command_line)); cmd->next = NULL; @@ -85,14 +100,15 @@ build_command_line (enum command_control_type type, char *args) = (struct command_line **) xmalloc (sizeof (struct command_line *) * cmd->body_count); memset (cmd->body_list, 0, sizeof (struct command_line *) * cmd->body_count); - cmd->line = savestring (args, strlen (args)); + cmd->line = xstrdup (args); + return cmd; } /* Build and return a new command structure for the control commands such as "if" and "while". */ -static struct command_line * +struct command_line * get_command_line (enum command_control_type type, char *arg) { struct command_line *cmd; @@ -104,9 +120,10 @@ get_command_line (enum command_control_type type, char *arg) old_chain = make_cleanup_free_command_lines (&cmd); /* Read in the body of this command. */ - if (recurse_read_control_structure (cmd) == invalid_control) + if (recurse_read_control_structure (read_next_line, cmd, 0, 0) + == invalid_control) { - warning (_("Error reading in control structure.")); + warning (_("Error reading in canned sequence of commands.")); do_cleanups (old_chain); return NULL; } @@ -126,7 +143,6 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, list = cmd; while (list) { - if (depth) ui_out_spaces (uiout, 2 * depth); @@ -149,7 +165,8 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* loop_break to break out of a while loop, print it and continue. */ + /* loop_break to break out of a while loop, print it and + continue. */ if (list->control_type == break_control) { ui_out_field_string (uiout, NULL, "loop_break"); @@ -158,10 +175,18 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* A while command. Recursively print its subcommands and continue. */ - if (list->control_type == while_control) + /* A while command. Recursively print its subcommands and + continue. */ + if (list->control_type == while_control + || list->control_type == while_stepping_control) { - ui_out_field_fmt (uiout, NULL, "while %s", list->line); + /* For while-stepping, the line includes the 'while-stepping' + token. See comment in process_next_line for explanation. + Here, take care not print 'while-stepping' twice. */ + if (list->control_type == while_control) + ui_out_field_fmt (uiout, NULL, "while %s", list->line); + else + ui_out_field_string (uiout, NULL, list->line); ui_out_text (uiout, "\n"); print_command_lines (uiout, *list->body_list, depth + 1); if (depth) @@ -172,12 +197,13 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* An if command. Recursively print both arms before continueing. */ + /* An if command. Recursively print both arms before + continueing. */ if (list->control_type == if_control) { ui_out_field_fmt (uiout, NULL, "if %s", list->line); ui_out_text (uiout, "\n"); - /* The true arm. */ + /* The true arm. */ print_command_lines (uiout, list->body_list[0], depth + 1); /* Show the false arm if it exists. */ @@ -198,7 +224,39 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd, continue; } - /* ignore illegal command type and try next */ + /* A commands command. Print the breakpoint commands and + continue. */ + if (list->control_type == commands_control) + { + if (*(list->line)) + ui_out_field_fmt (uiout, NULL, "commands %s", list->line); + else + ui_out_field_string (uiout, NULL, "commands"); + ui_out_text (uiout, "\n"); + print_command_lines (uiout, *list->body_list, depth + 1); + if (depth) + ui_out_spaces (uiout, 2 * depth); + ui_out_field_string (uiout, NULL, "end"); + ui_out_text (uiout, "\n"); + list = list->next; + continue; + } + + if (list->control_type == python_control) + { + ui_out_field_string (uiout, NULL, "python"); + ui_out_text (uiout, "\n"); + /* Don't indent python code at all. */ + print_command_lines (uiout, *list->body_list, 0); + if (depth) + ui_out_spaces (uiout, 2 * depth); + ui_out_field_string (uiout, NULL, "end"); + ui_out_text (uiout, "\n"); + list = list->next; + continue; + } + + /* Ignore illegal command type and try next. */ list = list->next; } /* while (list) */ } @@ -209,7 +267,8 @@ static void clear_hook_in_cleanup (void *data) { struct cmd_list_element *c = data; - c->hook_in = 0; /* Allow hook to work again once it is complete */ + + c->hook_in = 0; /* Allow hook to work again once it is complete. */ } void @@ -218,7 +277,7 @@ execute_cmd_pre_hook (struct cmd_list_element *c) if ((c->hook_pre) && (!c->hook_in)) { struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c); - c->hook_in = 1; /* Prevent recursive hooking */ + c->hook_in = 1; /* Prevent recursive hooking. */ execute_user_command (c->hook_pre, (char *) 0); do_cleanups (cleanups); } @@ -230,7 +289,8 @@ execute_cmd_post_hook (struct cmd_list_element *c) if ((c->hook_post) && (!c->hook_in)) { struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c); - c->hook_in = 1; /* Prevent recursive hooking */ + + c->hook_in = 1; /* Prevent recursive hooking. */ execute_user_command (c->hook_post, (char *) 0); do_cleanups (cleanups); } @@ -240,10 +300,11 @@ execute_cmd_post_hook (struct cmd_list_element *c) static void do_restore_user_call_depth (void * call_depth) { - int * depth = call_depth; - /* We will be returning_to_top_level() at this point, so we want to - reset our depth. */ - (*depth) = 0; + int *depth = call_depth; + + (*depth)--; + if ((*depth) == 0) + in_user_command = 0; } @@ -266,25 +327,70 @@ execute_user_command (struct cmd_list_element *c, char *args) if (++user_call_depth > max_user_call_depth) error (_("Max user call depth exceeded -- command aborted.")); - old_chain = make_cleanup (do_restore_user_call_depth, &user_call_depth); + make_cleanup (do_restore_user_call_depth, &user_call_depth); /* Set the instream to 0, indicating execution of a user-defined function. */ - old_chain = make_cleanup (do_restore_instream_cleanup, instream); + make_cleanup (do_restore_instream_cleanup, instream); instream = (FILE *) 0; + + /* Also set the global in_user_command, so that NULL instream is + not confused with Insight. */ + in_user_command = 1; + + command_nest_depth++; while (cmdlines) { ret = execute_control_command (cmdlines); if (ret != simple_control && ret != break_control) { - warning (_("Error in control structure.")); + warning (_("Error executing canned sequence of commands.")); break; } cmdlines = cmdlines->next; } + command_nest_depth--; do_cleanups (old_chain); +} + +/* This function is called every time GDB prints a prompt. It ensures + that errors and the like do not confuse the command tracing. */ + +void +reset_command_nest_depth (void) +{ + command_nest_depth = 1; + + /* Just in case. */ + suppress_next_print_command_trace = 0; +} + +/* Print the command, prefixed with '+' to represent the call depth. + This is slightly complicated because this function may be called + from execute_command and execute_control_command. Unfortunately + execute_command also prints the top level control commands. + In these cases execute_command will call execute_control_command + via while_command or if_command. Inner levels of 'if' and 'while' + are dealt with directly. Therefore we can use these functions + to determine whether the command has been printed already or not. */ +void +print_command_trace (const char *cmd) +{ + int i; + + if (suppress_next_print_command_trace) + { + suppress_next_print_command_trace = 0; + return; + } + + if (!source_verbose && !trace_commands) + return; - user_call_depth--; + for (i=0; i < command_nest_depth; i++) + printf_filtered ("+"); + + printf_filtered ("%s\n", cmd); } enum command_control_type @@ -316,7 +422,16 @@ execute_control_command (struct command_line *cmd) break; case continue_control: + print_command_trace ("loop_continue"); + + /* Return for "continue", and "break" so we can either + continue the loop at the top, or break out. */ + ret = cmd->control_type; + break; + case break_control: + print_command_trace ("loop_break"); + /* Return for "continue", and "break" so we can either continue the loop at the top, or break out. */ ret = cmd->control_type; @@ -324,6 +439,11 @@ execute_control_command (struct command_line *cmd) case while_control: { + char *buffer = alloca (strlen (cmd->line) + 7); + + sprintf (buffer, "while %s", cmd->line); + print_command_trace (buffer); + /* Parse the loop control expression for the while statement. */ new_line = insert_args (cmd->line); if (!new_line) @@ -356,7 +476,9 @@ execute_control_command (struct command_line *cmd) current = *cmd->body_list; while (current) { + command_nest_depth++; ret = execute_control_command (current); + command_nest_depth--; /* If we got an error, or a "break" command, then stop looping. */ @@ -385,6 +507,11 @@ execute_control_command (struct command_line *cmd) case if_control: { + char *buffer = alloca (strlen (cmd->line) + 4); + + sprintf (buffer, "if %s", cmd->line); + print_command_trace (buffer); + new_line = insert_args (cmd->line); if (!new_line) break; @@ -400,8 +527,8 @@ execute_control_command (struct command_line *cmd) val_mark = value_mark (); val = evaluate_expression (expr); - /* Choose which arm to take commands from based on the value of the - conditional expression. */ + /* Choose which arm to take commands from based on the value + of the conditional expression. */ if (value_true (val)) current = *cmd->body_list; else if (cmd->body_count == 2) @@ -411,7 +538,9 @@ execute_control_command (struct command_line *cmd) /* Execute commands in the given arm. */ while (current) { + command_nest_depth++; ret = execute_control_command (current); + command_nest_depth--; /* If we got an error, get out. */ if (ret != simple_control) @@ -423,9 +552,26 @@ execute_control_command (struct command_line *cmd) break; } + case commands_control: + { + /* Breakpoint commands list, record the commands in the + breakpoint's command list and return. */ + new_line = insert_args (cmd->line); + if (!new_line) + break; + make_cleanup (free_current_contents, &new_line); + ret = commands_from_control_command (new_line, cmd); + break; + } + case python_control: + { + eval_python_from_control_command (cmd); + ret = simple_control; + break; + } default: - warning (_("Invalid control type in command structure.")); + warning (_("Invalid control type in canned commands structure.")); break; } @@ -434,6 +580,17 @@ execute_control_command (struct command_line *cmd) return ret; } +/* Like execute_control_command, but first set + suppress_next_print_command_trace. */ + +enum command_control_type +execute_control_command_untraced (struct command_line *cmd) +{ + suppress_next_print_command_trace = 1; + return execute_control_command (cmd); +} + + /* "while" command support. Executes a body of statements while the loop condition is nonzero. */ @@ -448,7 +605,7 @@ while_command (char *arg, int from_tty) if (command == NULL) return; - execute_control_command (command); + execute_control_command_untraced (command); free_command_lines (&command); } @@ -466,7 +623,7 @@ if_command (char *arg, int from_tty) if (command == NULL) return; - execute_control_command (command); + execute_control_command_untraced (command); free_command_lines (&command); } @@ -475,11 +632,13 @@ static void arg_cleanup (void *ignore) { struct user_args *oargs = user_args; + if (!user_args) internal_error (__FILE__, __LINE__, _("arg_cleanup called with no user args.\n")); user_args = user_args->next; + xfree (oargs->command); xfree (oargs); } @@ -504,6 +663,8 @@ setup_user_args (char *p) if (p == NULL) return old_chain; + user_args->command = p = xstrdup (p); + while (*p) { char *start_arg; @@ -565,8 +726,8 @@ setup_user_args (char *p) return old_chain; } -/* Given character string P, return a point to the first argument ($arg), - or NULL if P contains no arguments. */ +/* Given character string P, return a point to the first argument + ($arg), or NULL if P contains no arguments. */ static char * locate_arg (char *p) @@ -582,7 +743,8 @@ locate_arg (char *p) } /* Insert the user defined arguments stored in user_arg into the $arg - arguments found in line, with the updated copy being placed into nline. */ + arguments found in line, with the updated copy being placed into + nline. */ static char * insert_args (char *line) @@ -590,7 +752,13 @@ insert_args (char *line) char *p, *save_line, *new_line; unsigned len, i; - /* First we need to know how much memory to allocate for the new line. */ + /* If we are not in a user-defined function, treat $argc, $arg0, et + cetera as normal convenience variables. */ + if (user_args == NULL) + return xstrdup (line); + + /* First we need to know how much memory to allocate for the new + line. */ save_line = line; len = 0; while ((p = locate_arg (line))) @@ -652,10 +820,10 @@ insert_args (char *line) i = p[4] - '0'; len = user_args->a[i].len; if (len) - { - memcpy (new_line, user_args->a[i].arg, len); - new_line += len; - } + { + memcpy (new_line, user_args->a[i].arg, len); + new_line += len; + } } line = p + 5; } @@ -687,19 +855,21 @@ realloc_body_list (struct command_line *command, int new_length) xmalloc (sizeof (struct command_line *) * new_length); memcpy (body_list, command->body_list, sizeof (struct command_line *) * n); + memset (body_list + n, 0, sizeof (struct command_line *) * (new_length - n)); xfree (command->body_list); command->body_list = body_list; command->body_count = new_length; } -/* Read one line from the input stream. If the command is an "else" or - "end", return such an indication to the caller. */ +/* Read next line from stdout. Passed to read_command_line_1 and + recurse_read_control_structure whenever we need to read commands + from stdout. */ -static enum misc_command_type -read_next_line (struct command_line **command) +static char * +read_next_line (void) { - char *p, *p1, *prompt_ptr, control_prompt[256]; + char *prompt_ptr, control_prompt[256]; int i = 0; if (control_level >= 254) @@ -717,96 +887,177 @@ read_next_line (struct command_line **command) else prompt_ptr = NULL; - p = command_line_input (prompt_ptr, instream == stdin, "commands"); + return command_line_input (prompt_ptr, instream == stdin, "commands"); +} + +/* Process one input line. If the command is an "end", return such an + indication to the caller. If PARSE_COMMANDS is true, strip leading + whitespace (trailing whitespace is always stripped) in the line, + attempt to recognize GDB control commands, and also return an + indication if the command is an "else" or a nop. + + Otherwise, only "end" is recognized. */ + +static enum misc_command_type +process_next_line (char *p, struct command_line **command, int parse_commands, + void (*validator)(char *, void *), void *closure) +{ + char *p_end; + char *p_start; + int not_handled = 0; /* Not sure what to do here. */ if (p == NULL) return end_command; - /* Strip leading and trailing whitespace. */ - while (*p == ' ' || *p == '\t') - p++; - - p1 = p + strlen (p); - while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t')) - p1--; + /* Strip trailing whitespace. */ + p_end = p + strlen (p); + while (p_end > p && (p_end[-1] == ' ' || p_end[-1] == '\t')) + p_end--; - /* Blanks and comments don't really do anything, but we need to - distinguish them from else, end and other commands which can be - executed. */ - if (p1 == p || p[0] == '#') - return nop_command; + p_start = p; + /* Strip leading whitespace. */ + while (p_start < p_end && (*p_start == ' ' || *p_start == '\t')) + p_start++; - /* Is this the end of a simple, while, or if control structure? */ - if (p1 - p == 3 && !strncmp (p, "end", 3)) + /* 'end' is always recognized, regardless of parse_commands value. + We also permit whitespace before end and after. */ + if (p_end - p_start == 3 && !strncmp (p_start, "end", 3)) return end_command; + + if (parse_commands) + { + /* If commands are parsed, we skip initial spaces. Otherwise, + which is the case for Python commands and documentation + (see the 'document' command), spaces are preserved. */ + p = p_start; + + /* Blanks and comments don't really do anything, but we need to + distinguish them from else, end and other commands which can + be executed. */ + if (p_end == p || p[0] == '#') + return nop_command; + + /* Is the else clause of an if control structure? */ + if (p_end - p == 4 && !strncmp (p, "else", 4)) + return else_command; + + /* Check for while, if, break, continue, etc and build a new + command line structure for them. */ + if ((p_end - p >= 14 && !strncmp (p, "while-stepping", 14)) + || (p_end - p >= 8 && !strncmp (p, "stepping", 8)) + || (p_end - p >= 2 && !strncmp (p, "ws", 2))) + { + /* Because validate_actionline and encode_action lookup + command's line as command, we need the line to + include 'while-stepping'. + + For 'ws' alias, the command will have 'ws', not expanded + to 'while-stepping'. This is intentional -- we don't + really want frontend to send a command list with 'ws', + and next break-info returning command line with + 'while-stepping'. This should work, but might cause the + breakpoint to be marked as changed while it's actually + not. */ + *command = build_command_line (while_stepping_control, p); + } + else if (p_end - p > 5 && !strncmp (p, "while", 5)) + { + char *first_arg; - /* Is the else clause of an if control structure? */ - if (p1 - p == 4 && !strncmp (p, "else", 4)) - return else_command; + first_arg = p + 5; + while (first_arg < p_end && isspace (*first_arg)) + first_arg++; + *command = build_command_line (while_control, first_arg); + } + else if (p_end - p > 2 && !strncmp (p, "if", 2)) + { + char *first_arg; - /* Check for while, if, break, continue, etc and build a new command - line structure for them. */ - if (p1 - p > 5 && !strncmp (p, "while", 5)) - { - char *first_arg; - first_arg = p + 5; - while (first_arg < p1 && isspace (*first_arg)) - first_arg++; - *command = build_command_line (while_control, first_arg); - } - else if (p1 - p > 2 && !strncmp (p, "if", 2)) - { - char *first_arg; - first_arg = p + 2; - while (first_arg < p1 && isspace (*first_arg)) - first_arg++; - *command = build_command_line (if_control, first_arg); - } - else if (p1 - p == 10 && !strncmp (p, "loop_break", 10)) - { - *command = (struct command_line *) - xmalloc (sizeof (struct command_line)); - (*command)->next = NULL; - (*command)->line = NULL; - (*command)->control_type = break_control; - (*command)->body_count = 0; - (*command)->body_list = NULL; - } - else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13)) - { - *command = (struct command_line *) - xmalloc (sizeof (struct command_line)); - (*command)->next = NULL; - (*command)->line = NULL; - (*command)->control_type = continue_control; - (*command)->body_count = 0; - (*command)->body_list = NULL; + first_arg = p + 2; + while (first_arg < p_end && isspace (*first_arg)) + first_arg++; + *command = build_command_line (if_control, first_arg); + } + else if (p_end - p >= 8 && !strncmp (p, "commands", 8)) + { + char *first_arg; + + first_arg = p + 8; + while (first_arg < p_end && isspace (*first_arg)) + first_arg++; + *command = build_command_line (commands_control, first_arg); + } + else if (p_end - p == 6 && !strncmp (p, "python", 6)) + { + /* Note that we ignore the inline "python command" form + here. */ + *command = build_command_line (python_control, ""); + } + else if (p_end - p == 10 && !strncmp (p, "loop_break", 10)) + { + *command = (struct command_line *) + xmalloc (sizeof (struct command_line)); + (*command)->next = NULL; + (*command)->line = NULL; + (*command)->control_type = break_control; + (*command)->body_count = 0; + (*command)->body_list = NULL; + } + else if (p_end - p == 13 && !strncmp (p, "loop_continue", 13)) + { + *command = (struct command_line *) + xmalloc (sizeof (struct command_line)); + (*command)->next = NULL; + (*command)->line = NULL; + (*command)->control_type = continue_control; + (*command)->body_count = 0; + (*command)->body_list = NULL; + } + else + not_handled = 1; } - else + + if (!parse_commands || not_handled) { /* A normal command. */ *command = (struct command_line *) xmalloc (sizeof (struct command_line)); (*command)->next = NULL; - (*command)->line = savestring (p, p1 - p); + (*command)->line = savestring (p, p_end - p); (*command)->control_type = simple_control; (*command)->body_count = 0; (*command)->body_list = NULL; } + if (validator) + { + volatile struct gdb_exception ex; + + TRY_CATCH (ex, RETURN_MASK_ALL) + { + validator ((*command)->line, closure); + } + if (ex.reason < 0) + { + xfree (*command); + throw_exception (ex); + } + } + /* Nothing special. */ return ok_command; } -/* Recursively read in the control structures and create a command_line - structure from them. - - The parent_control parameter is the control structure in which the - following commands are nested. */ +/* Recursively read in the control structures and create a + command_line structure from them. Use read_next_line_func to + obtain lines of the command. */ static enum command_control_type -recurse_read_control_structure (struct command_line *current_cmd) +recurse_read_control_structure (char * (*read_next_line_func) (void), + struct command_line *current_cmd, + void (*validator)(char *, void *), + void *closure) { int current_body, i; enum misc_command_type val; @@ -829,7 +1080,9 @@ recurse_read_control_structure (struct command_line *current_cmd) dont_repeat (); next = NULL; - val = read_next_line (&next); + val = process_next_line (read_next_line_func (), &next, + current_cmd->control_type != python_control, + validator, closure); /* Just skip blanks and comments. */ if (val == nop_command) @@ -838,9 +1091,12 @@ recurse_read_control_structure (struct command_line *current_cmd) if (val == end_command) { if (current_cmd->control_type == while_control - || current_cmd->control_type == if_control) + || current_cmd->control_type == while_stepping_control + || current_cmd->control_type == if_control + || current_cmd->control_type == python_control + || current_cmd->control_type == commands_control) { - /* Success reading an entire control structure. */ + /* Success reading an entire canned sequence of commands. */ ret = simple_control; break; } @@ -888,10 +1144,14 @@ recurse_read_control_structure (struct command_line *current_cmd) /* If the latest line is another control structure, then recurse on it. */ if (next->control_type == while_control - || next->control_type == if_control) + || next->control_type == while_stepping_control + || next->control_type == if_control + || next->control_type == python_control + || next->control_type == commands_control) { control_level++; - ret = recurse_read_control_structure (next); + ret = recurse_read_control_structure (read_next_line_func, next, + validator, closure); control_level--; if (ret != simple_control) @@ -907,36 +1167,66 @@ recurse_read_control_structure (struct command_line *current_cmd) /* Read lines from the input stream and accumulate them in a chain of struct command_line's, which is then returned. For input from a terminal, the special command "end" is used to mark the end of the - input, and is not included in the returned chain of commands. */ + input, and is not included in the returned chain of commands. + + If PARSE_COMMANDS is true, strip leading whitespace (trailing whitespace + is always stripped) in the line and attempt to recognize GDB control + commands. Otherwise, only "end" is recognized. */ #define END_MESSAGE "End with a line saying just \"end\"." struct command_line * -read_command_lines (char *prompt_arg, int from_tty) +read_command_lines (char *prompt_arg, int from_tty, int parse_commands, + void (*validator)(char *, void *), void *closure) { - struct command_line *head, *tail, *next; - struct cleanup *old_chain; - enum command_control_type ret; - enum misc_command_type val; + struct command_line *head; - control_level = 0; - if (deprecated_readline_begin_hook) + if (from_tty && input_from_terminal_p ()) { - /* Note - intentional to merge messages with no newline */ - (*deprecated_readline_begin_hook) ("%s %s\n", prompt_arg, END_MESSAGE); + if (deprecated_readline_begin_hook) + { + /* Note - intentional to merge messages with no newline. */ + (*deprecated_readline_begin_hook) ("%s %s\n", prompt_arg, + END_MESSAGE); + } + else + { + printf_unfiltered ("%s\n%s\n", prompt_arg, END_MESSAGE); + gdb_flush (gdb_stdout); + } } - else if (from_tty && input_from_terminal_p ()) + + head = read_command_lines_1 (read_next_line, parse_commands, + validator, closure); + + if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ()) { - printf_unfiltered ("%s\n%s\n", prompt_arg, END_MESSAGE); - gdb_flush (gdb_stdout); + (*deprecated_readline_end_hook) (); } + return (head); +} + +/* Act the same way as read_command_lines, except that each new line is + obtained using READ_NEXT_LINE_FUNC. */ + +struct command_line * +read_command_lines_1 (char * (*read_next_line_func) (void), int parse_commands, + void (*validator)(char *, void *), void *closure) +{ + struct command_line *head, *tail, *next; + struct cleanup *old_chain; + enum command_control_type ret; + enum misc_command_type val; + control_level = 0; head = tail = NULL; old_chain = NULL; while (1) { - val = read_next_line (&next); + dont_repeat (); + val = process_next_line (read_next_line_func (), &next, parse_commands, + validator, closure); /* Ignore blank lines or comments. */ if (val == nop_command) @@ -955,10 +1245,14 @@ read_command_lines (char *prompt_arg, int from_tty) } if (next->control_type == while_control - || next->control_type == if_control) + || next->control_type == if_control + || next->control_type == python_control + || next->control_type == commands_control + || next->control_type == while_stepping_control) { control_level++; - ret = recurse_read_control_structure (next); + ret = recurse_read_control_structure (read_next_line_func, next, + validator, closure); control_level--; if (ret == invalid_control) @@ -989,11 +1283,7 @@ read_command_lines (char *prompt_arg, int from_tty) do_cleanups (old_chain); } - if (deprecated_readline_end_hook) - { - (*deprecated_readline_end_hook) (); - } - return (head); + return head; } /* Free a chain of struct command_line's. */ @@ -1064,21 +1354,57 @@ copy_command_lines (struct command_line *cmds) return result; } -static void -validate_comname (char *comname) +/* Validate that *COMNAME is a valid name for a command. Return the + containing command list, in case it starts with a prefix command. + The prefix must already exist. *COMNAME is advanced to point after + any prefix, and a NUL character overwrites the space after the + prefix. */ + +static struct cmd_list_element ** +validate_comname (char **comname) { - char *p; + struct cmd_list_element **list = &cmdlist; + char *p, *last_word; - if (comname == 0) + if (*comname == 0) error_no_arg (_("name of command to define")); - p = comname; + /* Find the last word of the argument. */ + p = *comname + strlen (*comname); + while (p > *comname && isspace (p[-1])) + p--; + while (p > *comname && !isspace (p[-1])) + p--; + last_word = p; + + /* Find the corresponding command list. */ + if (last_word != *comname) + { + struct cmd_list_element *c; + char saved_char, *tem = *comname; + + /* Separate the prefix and the command. */ + saved_char = last_word[-1]; + last_word[-1] = '\0'; + + c = lookup_cmd (&tem, cmdlist, "", 0, 1); + if (c->prefixlist == NULL) + error (_("\"%s\" is not a prefix command."), *comname); + + list = c->prefixlist; + last_word[-1] = saved_char; + *comname = last_word; + } + + p = *comname; while (*p) { if (!isalnum (*p) && *p != '-' && *p != '_') error (_("Junk in argument list: \"%s\""), p); p++; } + + return list; } /* This is just a placeholder in the command data structures. */ @@ -1098,9 +1424,8 @@ define_command (char *comname, int from_tty) CMD_POST_HOOK }; struct command_line *cmds; - struct cmd_list_element *c, *newc, *oldc, *hookc = 0; - char *tem = comname; - char *tem2; + struct cmd_list_element *c, *newc, *hookc = 0, **list; + char *tem, *comfull; char tmpbuf[MAX_TMPBUF]; int hook_type = CMD_NO_HOOK; int hook_name_size = 0; @@ -1110,16 +1435,19 @@ define_command (char *comname, int from_tty) #define HOOK_POST_STRING "hookpost-" #define HOOK_POST_LEN 9 - validate_comname (comname); + comfull = comname; + list = validate_comname (&comname); /* Look it up, and verify that we got an exact match. */ - c = lookup_cmd (&tem, cmdlist, "", -1, 1); + tem = comname; + c = lookup_cmd (&tem, *list, "", -1, 1); if (c && strcmp (comname, c->name) != 0) c = 0; if (c) { int q; + if (c->class == class_user || c->class == class_alias) q = query (_("Redefine command \"%s\"? "), c->name); else @@ -1147,35 +1475,36 @@ define_command (char *comname, int from_tty) { /* Look up cmd it hooks, and verify that we got an exact match. */ tem = comname + hook_name_size; - hookc = lookup_cmd (&tem, cmdlist, "", -1, 0); + hookc = lookup_cmd (&tem, *list, "", -1, 0); if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0) hookc = 0; if (!hookc) { - warning (_("Your new `%s' command does not hook any existing command."), - comname); - if (!query ("Proceed? ")) + warning (_("Your new `%s' command does not " + "hook any existing command."), + comfull); + if (!query (_("Proceed? "))) error (_("Not confirmed.")); } } - comname = savestring (comname, strlen (comname)); + comname = xstrdup (comname); /* If the rest of the commands will be case insensitive, this one - should behave in the same manner. */ + should behave in the same manner. */ for (tem = comname; *tem; tem++) if (isupper (*tem)) *tem = tolower (*tem); - sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname); - cmds = read_command_lines (tmpbuf, from_tty); + sprintf (tmpbuf, "Type commands for definition of \"%s\".", comfull); + cmds = read_command_lines (tmpbuf, from_tty, 1, 0, 0); if (c && c->class == class_user) free_command_lines (&c->user_commands); newc = add_cmd (comname, class_user, user_defined_command, (c && c->class == class_user) - ? c->doc : savestring ("User-defined.", 13), &cmdlist); + ? c->doc : xstrdup ("User-defined."), list); newc->user_commands = cmds; /* If this new command is a hook, then mark both commands as being @@ -1186,14 +1515,15 @@ define_command (char *comname, int from_tty) { case CMD_PRE_HOOK: hookc->hook_pre = newc; /* Target gets hooked. */ - newc->hookee_pre = hookc; /* We are marked as hooking target cmd. */ + newc->hookee_pre = hookc; /* We are marked as hooking target cmd. */ break; case CMD_POST_HOOK: hookc->hook_post = newc; /* Target gets hooked. */ - newc->hookee_post = hookc; /* We are marked as hooking target cmd. */ + newc->hookee_post = hookc; /* We are marked as hooking + target cmd. */ break; default: - /* Should never come here as hookc would be 0. */ + /* Should never come here as hookc would be 0. */ internal_error (__FILE__, __LINE__, _("bad switch")); } } @@ -1203,19 +1533,21 @@ void document_command (char *comname, int from_tty) { struct command_line *doclines; - struct cmd_list_element *c; - char *tem = comname; + struct cmd_list_element *c, **list; + char *tem, *comfull; char tmpbuf[128]; - validate_comname (comname); + comfull = comname; + list = validate_comname (&comname); - c = lookup_cmd (&tem, cmdlist, "", 0, 1); + tem = comname; + c = lookup_cmd (&tem, *list, "", 0, 1); if (c->class != class_user) - error (_("Command \"%s\" is built-in."), comname); + error (_("Command \"%s\" is built-in."), comfull); - sprintf (tmpbuf, "Type documentation for \"%s\".", comname); - doclines = read_command_lines (tmpbuf, from_tty); + sprintf (tmpbuf, "Type documentation for \"%s\".", comfull); + doclines = read_command_lines (tmpbuf, from_tty, 0, 0, 0); if (c->doc) xfree (c->doc); @@ -1244,24 +1576,19 @@ document_command (char *comname, int from_tty) struct source_cleanup_lines_args { int old_line; - char *old_file; + const char *old_file; }; static void source_cleanup_lines (void *args) { struct source_cleanup_lines_args *p = - (struct source_cleanup_lines_args *) args; + (struct source_cleanup_lines_args *) args; + source_line_number = p->old_line; source_file_name = p->old_file; } -static void -do_fclose_cleanup (void *stream) -{ - fclose (stream); -} - struct wrapped_read_command_file_args { FILE *stream; @@ -1271,35 +1598,36 @@ static void wrapped_read_command_file (struct ui_out *uiout, void *data) { struct wrapped_read_command_file_args *args = data; + read_command_file (args->stream); } -/* Used to implement source_command */ +/* Used to implement source_command. */ void -script_from_file (FILE *stream, char *file) +script_from_file (FILE *stream, const char *file) { struct cleanup *old_cleanups; struct source_cleanup_lines_args old_lines; - int needed_length; if (stream == NULL) internal_error (__FILE__, __LINE__, _("called with NULL file pointer!")); - old_cleanups = make_cleanup (do_fclose_cleanup, stream); + old_cleanups = make_cleanup_fclose (stream); old_lines.old_line = source_line_number; old_lines.old_file = source_file_name; make_cleanup (source_cleanup_lines, &old_lines); source_line_number = 0; source_file_name = file; - /* This will get set every time we read a line. So it won't stay "" for - long. */ + /* This will get set every time we read a line. So it won't stay "" + for long. */ error_pre_print = ""; { struct gdb_exception e; struct wrapped_read_command_file_args args; + args.stream = stream; e = catch_exception (uiout, wrapped_read_command_file, &args, RETURN_MASK_ERROR); @@ -1321,17 +1649,30 @@ script_from_file (FILE *stream, char *file) do_cleanups (old_cleanups); } +/* Print the definition of user command C to STREAM. Or, if C is a + prefix command, show the definitions of all user commands under C + (recursively). PREFIX and NAME combined are the name of the + current command. */ void -show_user_1 (struct cmd_list_element *c, struct ui_file *stream) +show_user_1 (struct cmd_list_element *c, char *prefix, char *name, + struct ui_file *stream) { struct command_line *cmdlines; + if (c->prefixlist != NULL) + { + char *prefixname = c->prefixname; + + for (c = *c->prefixlist; c != NULL; c = c->next) + if (c->class == class_user || c->prefixlist != NULL) + show_user_1 (c, prefixname, c->name, gdb_stdout); + return; + } + cmdlines = c->user_commands; if (!cmdlines) return; - fputs_filtered ("User command ", stream); - fputs_filtered (c->name, stream); - fputs_filtered (":\n", stream); + fprintf_filtered (stream, "User command \"%s%s\":\n", prefix, name); print_command_lines (uiout, cmdlines, 1); fputs_filtered ("\n", stream);