OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/gnu-old/gdb-7.1/gdb/cli
    from Rev 834 to Rev 842
    Reverse comparison

Rev 834 → Rev 842

/cli-script.h
0,0 → 1,70
/* Header file for GDB CLI command implementation library.
Copyright (c) 2000, 2002, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
 
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 3 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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, see <http://www.gnu.org/licenses/>. */
 
#if !defined (CLI_SCRIPT_H)
#define CLI_SCRIPT_H 1
 
struct ui_file;
struct command_line;
struct cmd_list_element;
 
/* Exported to cli/cli-cmds.c */
 
extern void script_from_file (FILE *stream, char *file);
 
extern void document_command (char *, int);
 
extern void define_command (char *, int);
 
extern void while_command (char *arg, int from_tty);
 
extern void if_command (char *arg, int from_tty);
 
extern void show_user_1 (struct cmd_list_element *c, char *prefix,
char *name, struct ui_file *stream);
 
/* Exported to gdb/breakpoint.c */
 
extern enum command_control_type
execute_control_command (struct command_line *cmd);
 
extern enum command_control_type
execute_control_command_untraced (struct command_line *cmd);
 
extern struct command_line *get_command_line (enum command_control_type,
char *);
 
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
 
extern struct command_line * copy_command_lines (struct command_line *cmds);
 
struct cleanup *make_cleanup_free_command_lines (struct command_line **arg);
 
/* Exported to gdb/infrun.c */
 
extern void execute_user_command (struct cmd_list_element *c, char *args);
 
/* Exported to top.c */
 
extern void print_command_trace (const char *cmd);
 
/* Exported to event-top.c */
 
extern void reset_command_nest_depth (void);
 
#endif /* !defined (CLI_SCRIPT_H) */
cli-script.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-dump.h =================================================================== --- cli-dump.h (nonexistent) +++ cli-dump.h (revision 842) @@ -0,0 +1,39 @@ +/* Dump-to-file commands, for GDB, the GNU debugger. + + Copyright (c) 2001, 2005, 2007, 2008, 2009, 2010 + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#ifndef CLI_DUMP_H +#define CLI_DUMP_H + +extern void add_dump_command (char *name, + void (*func) (char *args, char *mode), + char *descr); + +/* Utilities for doing the dump. */ +extern char *scan_filename_with_cleanup (char **cmd, const char *defname); + +extern char *scan_expression_with_cleanup (char **cmd, const char *defname); + +extern FILE *fopen_with_cleanup (const char *filename, const char *mode); + +extern char *skip_spaces (char *inp); + +extern struct value *parse_and_eval_with_error (char *exp, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3); + +#endif
cli-dump.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-cmds.h =================================================================== --- cli-cmds.h (nonexistent) +++ cli-cmds.h (revision 842) @@ -0,0 +1,136 @@ +/* Header file for GDB CLI command implementation library. + Copyright (c) 2000,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#if !defined (CLI_CMDS_H) +#define CLI_CMDS_H 1 + +/* Chain containing all defined commands. */ + +extern struct cmd_list_element *cmdlist; + +/* Chain containing all defined info subcommands. */ + +extern struct cmd_list_element *infolist; + +/* Chain containing all defined enable subcommands. */ + +extern struct cmd_list_element *enablelist; + +/* Chain containing all defined disable subcommands. */ + +extern struct cmd_list_element *disablelist; + +/* Chain containing all defined delete subcommands. */ + +extern struct cmd_list_element *deletelist; + +/* Chain containing all defined detach subcommands. */ + +extern struct cmd_list_element *detachlist; + +/* Chain containing all defined kill subcommands. */ + +extern struct cmd_list_element *killlist; + +/* Chain containing all defined toggle subcommands. */ + +extern struct cmd_list_element *togglelist; + +/* Chain containing all defined stop subcommands. */ + +extern struct cmd_list_element *stoplist; + +/* Chain containing all defined "enable breakpoint" subcommands. */ + +extern struct cmd_list_element *enablebreaklist; + +/* Chain containing all defined set subcommands */ + +extern struct cmd_list_element *setlist; + +/* Chain containing all defined unset subcommands */ + +extern struct cmd_list_element *unsetlist; + +/* Chain containing all defined show subcommands. */ + +extern struct cmd_list_element *showlist; + +/* Chain containing all defined \"set history\". */ + +extern struct cmd_list_element *sethistlist; + +/* Chain containing all defined \"show history\". */ + +extern struct cmd_list_element *showhistlist; + +/* Chain containing all defined \"unset history\". */ + +extern struct cmd_list_element *unsethistlist; + +/* Chain containing all defined maintenance subcommands. */ + +extern struct cmd_list_element *maintenancelist; + +/* Chain containing all defined "maintenance info" subcommands. */ + +extern struct cmd_list_element *maintenanceinfolist; + +/* Chain containing all defined "maintenance print" subcommands. */ + +extern struct cmd_list_element *maintenanceprintlist; + +extern struct cmd_list_element *setprintlist; + +extern struct cmd_list_element *showprintlist; + +extern struct cmd_list_element *setdebuglist; + +extern struct cmd_list_element *showdebuglist; + +extern struct cmd_list_element *setchecklist; + +extern struct cmd_list_element *showchecklist; + +/* Exported to gdb/top.c */ + +void init_cmd_lists (void); + +void init_cli_cmds (void); + +int is_complete_command (struct cmd_list_element *cmd); + +/* Exported to gdb/main.c */ + +extern void cd_command (char *, int); + +/* Exported to gdb/top.c and gdb/main.c */ + +extern void quit_command (char *, int); + +extern void source_script (char *, int); + +/* Used everywhere whenever at least one parameter is required and + none is specified. */ + +extern NORETURN void error_no_arg (char *) ATTR_NORETURN; + +/* Command tracing state. */ + +extern int source_verbose; +extern int trace_commands; + +#endif /* !defined (CLI_CMDS_H) */
cli-cmds.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-setshow.c =================================================================== --- cli-setshow.c (nonexistent) +++ cli-setshow.c (revision 842) @@ -0,0 +1,443 @@ +/* Handle set and show GDB commands. + + Copyright (c) 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#include "defs.h" +#include "readline/tilde.h" +#include "value.h" +#include +#include "gdb_string.h" + +#include "ui-out.h" + +#include "cli/cli-decode.h" +#include "cli/cli-cmds.h" +#include "cli/cli-setshow.h" + +/* Prototypes for local functions */ + +static int parse_binary_operation (char *); + + +static enum auto_boolean +parse_auto_binary_operation (const char *arg) +{ + if (arg != NULL && *arg != '\0') + { + int length = strlen (arg); + while (isspace (arg[length - 1]) && length > 0) + length--; + if (strncmp (arg, "on", length) == 0 + || strncmp (arg, "1", length) == 0 + || strncmp (arg, "yes", length) == 0 + || strncmp (arg, "enable", length) == 0) + return AUTO_BOOLEAN_TRUE; + else if (strncmp (arg, "off", length) == 0 + || strncmp (arg, "0", length) == 0 + || strncmp (arg, "no", length) == 0 + || strncmp (arg, "disable", length) == 0) + return AUTO_BOOLEAN_FALSE; + else if (strncmp (arg, "auto", length) == 0 + || (strncmp (arg, "-1", length) == 0 && length > 1)) + return AUTO_BOOLEAN_AUTO; + } + error (_("\"on\", \"off\" or \"auto\" expected.")); + return AUTO_BOOLEAN_AUTO; /* pacify GCC */ +} + +static int +parse_binary_operation (char *arg) +{ + int length; + + if (!arg || !*arg) + return 1; + + length = strlen (arg); + + while (arg[length - 1] == ' ' || arg[length - 1] == '\t') + length--; + + if (strncmp (arg, "on", length) == 0 + || strncmp (arg, "1", length) == 0 + || strncmp (arg, "yes", length) == 0 + || strncmp (arg, "enable", length) == 0) + return 1; + else if (strncmp (arg, "off", length) == 0 + || strncmp (arg, "0", length) == 0 + || strncmp (arg, "no", length) == 0 + || strncmp (arg, "disable", length) == 0) + return 0; + else + { + error (_("\"on\" or \"off\" expected.")); + return 0; + } +} + +void +deprecated_show_value_hack (struct ui_file *ignore_file, + int ignore_from_tty, + struct cmd_list_element *c, + const char *value) +{ + /* If there's no command or value, don't try to print it out. */ + if (c == NULL || value == NULL) + return; + /* Print doc minus "show" at start. */ + print_doc_line (gdb_stdout, c->doc + 5); + switch (c->var_type) + { + case var_string: + case var_string_noescape: + case var_optional_filename: + case var_filename: + case var_enum: + printf_filtered ((" is \"%s\".\n"), value); + break; + default: + printf_filtered ((" is %s.\n"), value); + break; + } +} + +/* Do a "set" or "show" command. ARG is NULL if no argument, or the text + of the argument, and FROM_TTY is nonzero if this command is being entered + directly by the user (i.e. these are just like any other + command). C is the command list element for the command. */ + +void +do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) +{ + if (c->type == set_cmd) + { + switch (c->var_type) + { + case var_string: + { + char *new; + char *p; + char *q; + int ch; + + if (arg == NULL) + arg = ""; + new = (char *) xmalloc (strlen (arg) + 2); + p = arg; + q = new; + while ((ch = *p++) != '\000') + { + if (ch == '\\') + { + /* \ at end of argument is used after spaces + so they won't be lost. */ + /* This is obsolete now that we no longer strip + trailing whitespace and actually, the backslash + didn't get here in my test, readline or + something did something funky with a backslash + right before a newline. */ + if (*p == 0) + break; + ch = parse_escape (&p); + if (ch == 0) + break; /* C loses */ + else if (ch > 0) + *q++ = ch; + } + else + *q++ = ch; + } +#if 0 + if (*(p - 1) != '\\') + *q++ = ' '; +#endif + *q++ = '\0'; + new = (char *) xrealloc (new, q - new); + if (*(char **) c->var != NULL) + xfree (*(char **) c->var); + *(char **) c->var = new; + } + break; + case var_string_noescape: + if (arg == NULL) + arg = ""; + if (*(char **) c->var != NULL) + xfree (*(char **) c->var); + *(char **) c->var = xstrdup (arg); + break; + case var_optional_filename: + if (arg == NULL) + arg = ""; + if (*(char **) c->var != NULL) + xfree (*(char **) c->var); + *(char **) c->var = xstrdup (arg); + break; + case var_filename: + if (arg == NULL) + error_no_arg (_("filename to set it to.")); + if (*(char **) c->var != NULL) + xfree (*(char **) c->var); + { + /* Clear trailing whitespace of filename. */ + char *ptr = arg + strlen (arg) - 1; + while (ptr >= arg && (*ptr == ' ' || *ptr == '\t')) + ptr--; + *(ptr + 1) = '\0'; + } + *(char **) c->var = tilde_expand (arg); + break; + case var_boolean: + *(int *) c->var = parse_binary_operation (arg); + break; + case var_auto_boolean: + *(enum auto_boolean *) c->var = parse_auto_binary_operation (arg); + break; + case var_uinteger: + if (arg == NULL) + error_no_arg (_("integer to set it to.")); + *(unsigned int *) c->var = parse_and_eval_long (arg); + if (*(unsigned int *) c->var == 0) + *(unsigned int *) c->var = UINT_MAX; + break; + case var_integer: + { + unsigned int val; + if (arg == NULL) + error_no_arg (_("integer to set it to.")); + val = parse_and_eval_long (arg); + if (val == 0) + *(int *) c->var = INT_MAX; + else if (val >= INT_MAX) + error (_("integer %u out of range"), val); + else + *(int *) c->var = val; + break; + } + case var_zinteger: + if (arg == NULL) + error_no_arg (_("integer to set it to.")); + *(int *) c->var = parse_and_eval_long (arg); + break; + case var_zuinteger: + if (arg == NULL) + error_no_arg (_("integer to set it to.")); + *(unsigned int *) c->var = parse_and_eval_long (arg); + break; + case var_enum: + { + int i; + int len; + int nmatches; + const char *match = NULL; + char *p; + + /* if no argument was supplied, print an informative error message */ + if (arg == NULL) + { + char *msg; + int msg_len = 0; + for (i = 0; c->enums[i]; i++) + msg_len += strlen (c->enums[i]) + 2; + + msg = xmalloc (msg_len); + *msg = '\0'; + make_cleanup (xfree, msg); + + for (i = 0; c->enums[i]; i++) + { + if (i != 0) + strcat (msg, ", "); + strcat (msg, c->enums[i]); + } + error (_("Requires an argument. Valid arguments are %s."), msg); + } + + p = strchr (arg, ' '); + + if (p) + len = p - arg; + else + len = strlen (arg); + + nmatches = 0; + for (i = 0; c->enums[i]; i++) + if (strncmp (arg, c->enums[i], len) == 0) + { + if (c->enums[i][len] == '\0') + { + match = c->enums[i]; + nmatches = 1; + break; /* exact match. */ + } + else + { + match = c->enums[i]; + nmatches++; + } + } + + if (nmatches <= 0) + error (_("Undefined item: \"%s\"."), arg); + + if (nmatches > 1) + error (_("Ambiguous item \"%s\"."), arg); + + *(const char **) c->var = match; + } + break; + default: + error (_("gdb internal error: bad var_type in do_setshow_command")); + } + } + else if (c->type == show_cmd) + { + struct cleanup *old_chain; + struct ui_stream *stb; + + stb = ui_out_stream_new (uiout); + old_chain = make_cleanup_ui_out_stream_delete (stb); + + /* Possibly call the pre hook. */ + if (c->pre_show_hook) + (c->pre_show_hook) (c); + + switch (c->var_type) + { + case var_string: + if (*(char **) c->var) + fputstr_filtered (*(char **) c->var, '"', stb->stream); + break; + case var_string_noescape: + case var_optional_filename: + case var_filename: + case var_enum: + if (*(char **) c->var) + fputs_filtered (*(char **) c->var, stb->stream); + break; + case var_boolean: + fputs_filtered (*(int *) c->var ? "on" : "off", stb->stream); + break; + case var_auto_boolean: + switch (*(enum auto_boolean*) c->var) + { + case AUTO_BOOLEAN_TRUE: + fputs_filtered ("on", stb->stream); + break; + case AUTO_BOOLEAN_FALSE: + fputs_filtered ("off", stb->stream); + break; + case AUTO_BOOLEAN_AUTO: + fputs_filtered ("auto", stb->stream); + break; + default: + internal_error (__FILE__, __LINE__, + _("do_setshow_command: invalid var_auto_boolean")); + break; + } + break; + case var_uinteger: + if (*(unsigned int *) c->var == UINT_MAX) + { + fputs_filtered ("unlimited", stb->stream); + break; + } + /* else fall through */ + case var_zuinteger: + case var_zinteger: + fprintf_filtered (stb->stream, "%u", *(unsigned int *) c->var); + break; + case var_integer: + if (*(int *) c->var == INT_MAX) + { + fputs_filtered ("unlimited", stb->stream); + } + else + fprintf_filtered (stb->stream, "%d", *(int *) c->var); + break; + + default: + error (_("gdb internal error: bad var_type in do_setshow_command")); + } + + + /* FIXME: cagney/2005-02-10: Need to split this in half: code to + convert the value into a string (esentially the above); and + code to print the value out. For the latter there should be + MI and CLI specific versions. */ + + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_stream (uiout, "value", stb); + else + { + char *value = ui_file_xstrdup (stb->stream, NULL); + make_cleanup (xfree, value); + if (c->show_value_func != NULL) + c->show_value_func (gdb_stdout, from_tty, c, value); + else + deprecated_show_value_hack (gdb_stdout, from_tty, c, value); + } + do_cleanups (old_chain); + } + else + error (_("gdb internal error: bad cmd_type in do_setshow_command")); + c->func (c, NULL, from_tty); + if (c->type == set_cmd && deprecated_set_hook) + deprecated_set_hook (c); +} + +/* Show all the settings in a list of show commands. */ + +void +cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix) +{ + struct cleanup *showlist_chain; + + showlist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "showlist"); + for (; list != NULL; list = list->next) + { + /* If we find a prefix, run its list, prefixing our output by its + prefix (with "show " skipped). */ + if (list->prefixlist && !list->abbrev_flag) + { + struct cleanup *optionlist_chain + = make_cleanup_ui_out_tuple_begin_end (uiout, "optionlist"); + char *new_prefix = strstr (list->prefixname, "show ") + 5; + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string (uiout, "prefix", new_prefix); + cmd_show_list (*list->prefixlist, from_tty, new_prefix); + /* Close the tuple. */ + do_cleanups (optionlist_chain); + } + else + { + struct cleanup *option_chain + = make_cleanup_ui_out_tuple_begin_end (uiout, "option"); + ui_out_text (uiout, prefix); + ui_out_field_string (uiout, "name", list->name); + ui_out_text (uiout, ": "); + if (list->type == show_cmd) + do_setshow_command ((char *) NULL, from_tty, list); + else + cmd_func (list, NULL, from_tty); + /* Close the tuple. */ + do_cleanups (option_chain); + } + } + /* Close the tuple. */ + do_cleanups (showlist_chain); +} +
cli-setshow.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-interp.c =================================================================== --- cli-interp.c (nonexistent) +++ cli-interp.c (revision 842) @@ -0,0 +1,160 @@ +/* CLI Definitions for GDB, the GNU debugger. + + Copyright (c) 2002, 2003, 2007, 2008, 2009, 2010 + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#include "defs.h" +#include "interps.h" +#include "wrapper.h" +#include "event-top.h" +#include "ui-out.h" +#include "cli-out.h" +#include "top.h" /* for "execute_command" */ +#include "gdb_string.h" +#include "exceptions.h" + +struct ui_out *cli_uiout; + +/* These are the ui_out and the interpreter for the console interpreter. */ + +/* Longjmp-safe wrapper for "execute_command". */ +static struct gdb_exception safe_execute_command (struct ui_out *uiout, + char *command, int from_tty); +struct captured_execute_command_args +{ + char *command; + int from_tty; +}; + +/* These implement the cli out interpreter: */ + +static void * +cli_interpreter_init (int top_level) +{ + return NULL; +} + +static int +cli_interpreter_resume (void *data) +{ + struct ui_file *stream; + + /*sync_execution = 1; */ + + /* gdb_setup_readline will change gdb_stdout. If the CLI was previously + writing to gdb_stdout, then set it to the new gdb_stdout afterwards. */ + + stream = cli_out_set_stream (cli_uiout, gdb_stdout); + if (stream != gdb_stdout) + { + cli_out_set_stream (cli_uiout, stream); + stream = NULL; + } + + gdb_setup_readline (); + + if (stream != NULL) + cli_out_set_stream (cli_uiout, gdb_stdout); + + return 1; +} + +static int +cli_interpreter_suspend (void *data) +{ + gdb_disable_readline (); + return 1; +} + +/* Don't display the prompt if we are set quiet. */ +static int +cli_interpreter_display_prompt_p (void *data) +{ + if (interp_quiet_p (NULL)) + return 0; + else + return 1; +} + +static struct gdb_exception +cli_interpreter_exec (void *data, const char *command_str) +{ + struct ui_file *old_stream; + struct gdb_exception result; + + /* FIXME: cagney/2003-02-01: Need to const char *propogate + safe_execute_command. */ + char *str = strcpy (alloca (strlen (command_str) + 1), command_str); + + /* gdb_stdout could change between the time cli_uiout was initialized + and now. Since we're probably using a different interpreter which has + a new ui_file for gdb_stdout, use that one instead of the default. + + It is important that it gets reset everytime, since the user could + set gdb to use a different interpreter. */ + old_stream = cli_out_set_stream (cli_uiout, gdb_stdout); + result = safe_execute_command (cli_uiout, str, 1); + cli_out_set_stream (cli_uiout, old_stream); + return result; +} + +static void +do_captured_execute_command (struct ui_out *uiout, void *data) +{ + struct captured_execute_command_args *args = + (struct captured_execute_command_args *) data; + execute_command (args->command, args->from_tty); +} + +static struct gdb_exception +safe_execute_command (struct ui_out *uiout, char *command, int from_tty) +{ + struct gdb_exception e; + struct captured_execute_command_args args; + args.command = command; + args.from_tty = from_tty; + e = catch_exception (uiout, do_captured_execute_command, &args, + RETURN_MASK_ALL); + /* FIXME: cagney/2005-01-13: This shouldn't be needed. Instead the + caller should print the exception. */ + exception_print (gdb_stderr, e); + return e; +} + + +/* Standard gdb initialization hook. */ +extern initialize_file_ftype _initialize_cli_interp; /* -Wmissing-prototypes */ + +void +_initialize_cli_interp (void) +{ + static const struct interp_procs procs = { + cli_interpreter_init, /* init_proc */ + cli_interpreter_resume, /* resume_proc */ + cli_interpreter_suspend, /* suspend_proc */ + cli_interpreter_exec, /* exec_proc */ + cli_interpreter_display_prompt_p /* prompt_proc_p */ + }; + struct interp *cli_interp; + + /* Create a default uiout builder for the CLI. */ + cli_uiout = cli_out_new (gdb_stdout); + cli_interp = interp_new (INTERP_CONSOLE, NULL, cli_uiout, &procs); + + interp_add (cli_interp); +}
cli-interp.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-setshow.h =================================================================== --- cli-setshow.h (nonexistent) +++ cli-setshow.h (revision 842) @@ -0,0 +1,37 @@ +/* Header file for GDB CLI set and show commands implementation. + Copyright (c) 2000, 2001, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#if !defined (CLI_SETSHOW_H) +#define CLI_SETSHOW_H 1 + +struct cmd_list_element; + +/* Exported to cli/cli-cmds.c and gdb/top.c */ + +/* Do a "set" or "show" command. ARG is NULL if no argument, or the text + of the argument, and FROM_TTY is nonzero if this command is being entered + directly by the user (i.e. these are just like any other + command). C is the command list element for the command. */ +extern void do_setshow_command (char *arg, int from_tty, + struct cmd_list_element *c); + +/* Exported to cli/cli-cmds.c and gdb/top.c, language.c and valprint.c */ + +extern void cmd_show_list (struct cmd_list_element *list, int from_tty, + char *prefix); + +#endif /* !defined (CLI_SETSHOW_H) */
cli-setshow.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-decode.c =================================================================== --- cli-decode.c (nonexistent) +++ cli-decode.c (revision 842) @@ -0,0 +1,1741 @@ +/* Handle lists of commands, their decoding and documentation, for GDB. + + Copyright (c) 1986, 1989, 1990, 1991, 1998, 2000, 2001, 2002, 2004, 2007, + 2008, 2009, 2010 Free Software Foundation, Inc. + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#include "defs.h" +#include "symtab.h" +#include +#include "gdb_regex.h" +#include "gdb_string.h" +#include "completer.h" +#include "ui-out.h" + +#include "cli/cli-cmds.h" +#include "cli/cli-decode.h" + +#ifdef TUI +#include "tui/tui.h" /* For tui_active et.al. */ +#endif + +#include "gdb_assert.h" + +/* Prototypes for local functions */ + +static void undef_cmd_error (char *, char *); + +static struct cmd_list_element *delete_cmd (char *name, + struct cmd_list_element **list, + struct cmd_list_element **prehook, + struct cmd_list_element **prehookee, + struct cmd_list_element **posthook, + struct cmd_list_element **posthookee); + +static struct cmd_list_element *find_cmd (char *command, + int len, + struct cmd_list_element *clist, + int ignore_help_classes, + int *nfound); + +static void help_all (struct ui_file *stream); + +static void +print_help_for_command (struct cmd_list_element *c, char *prefix, int recurse, + struct ui_file *stream); + + +/* Set the callback function for the specified command. For each both + the commands callback and func() are set. The latter set to a + bounce function (unless cfunc / sfunc is NULL that is). */ + +static void +do_cfunc (struct cmd_list_element *c, char *args, int from_tty) +{ + c->function.cfunc (args, from_tty); /* Ok. */ +} + +void +set_cmd_cfunc (struct cmd_list_element *cmd, cmd_cfunc_ftype *cfunc) +{ + if (cfunc == NULL) + cmd->func = NULL; + else + cmd->func = do_cfunc; + cmd->function.cfunc = cfunc; /* Ok. */ +} + +static void +do_sfunc (struct cmd_list_element *c, char *args, int from_tty) +{ + c->function.sfunc (args, from_tty, c); /* Ok. */ +} + +void +set_cmd_sfunc (struct cmd_list_element *cmd, cmd_sfunc_ftype *sfunc) +{ + if (sfunc == NULL) + cmd->func = NULL; + else + cmd->func = do_sfunc; + cmd->function.sfunc = sfunc; /* Ok. */ +} + +int +cmd_cfunc_eq (struct cmd_list_element *cmd, + void (*cfunc) (char *args, int from_tty)) +{ + return cmd->func == do_cfunc && cmd->function.cfunc == cfunc; +} + +void +set_cmd_context (struct cmd_list_element *cmd, void *context) +{ + cmd->context = context; +} + +void * +get_cmd_context (struct cmd_list_element *cmd) +{ + return cmd->context; +} + +enum cmd_types +cmd_type (struct cmd_list_element *cmd) +{ + return cmd->type; +} + +void +set_cmd_completer (struct cmd_list_element *cmd, + char **(*completer) (struct cmd_list_element *self, + char *text, char *word)) +{ + cmd->completer = completer; /* Ok. */ +} + + +/* Add element named NAME. + CLASS is the top level category into which commands are broken down + for "help" purposes. + FUN should be the function to execute the command; + it will get a character string as argument, with leading + and trailing blanks already eliminated. + + DOC is a documentation string for the command. + Its first line should be a complete sentence. + It should start with ? for a command that is an abbreviation + or with * for a command that most users don't need to know about. + + Add this command to command list *LIST. + + Returns a pointer to the added command (not necessarily the head + of *LIST). */ + +struct cmd_list_element * +add_cmd (char *name, enum command_class class, void (*fun) (char *, int), + char *doc, struct cmd_list_element **list) +{ + struct cmd_list_element *c + = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element)); + struct cmd_list_element *p, *iter; + + /* Turn each alias of the old command into an alias of the new + command. */ + c->aliases = delete_cmd (name, list, &c->hook_pre, &c->hookee_pre, + &c->hook_post, &c->hookee_post); + for (iter = c->aliases; iter; iter = iter->alias_chain) + iter->cmd_pointer = c; + if (c->hook_pre) + c->hook_pre->hookee_pre = c; + if (c->hookee_pre) + c->hookee_pre->hook_pre = c; + if (c->hook_post) + c->hook_post->hookee_post = c; + if (c->hookee_post) + c->hookee_post->hook_post = c; + + if (*list == NULL || strcmp ((*list)->name, name) >= 0) + { + c->next = *list; + *list = c; + } + else + { + p = *list; + while (p->next && strcmp (p->next->name, name) <= 0) + { + p = p->next; + } + c->next = p->next; + p->next = c; + } + + c->name = name; + c->class = class; + set_cmd_cfunc (c, fun); + set_cmd_context (c, NULL); + c->doc = doc; + c->flags = 0; + c->replacement = NULL; + c->pre_show_hook = NULL; + c->hook_in = 0; + c->prefixlist = NULL; + c->prefixname = NULL; + c->allow_unknown = 0; + c->abbrev_flag = 0; + set_cmd_completer (c, make_symbol_completion_list_fn); + c->destroyer = NULL; + c->type = not_set_cmd; + c->var = NULL; + c->var_type = var_boolean; + c->enums = NULL; + c->user_commands = NULL; + c->cmd_pointer = NULL; + c->alias_chain = NULL; + + return c; +} + +/* Deprecates a command CMD. + REPLACEMENT is the name of the command which should be used in place + of this command, or NULL if no such command exists. + + This function does not check to see if command REPLACEMENT exists + since gdb may not have gotten around to adding REPLACEMENT when this + function is called. + + Returns a pointer to the deprecated command. */ + +struct cmd_list_element * +deprecate_cmd (struct cmd_list_element *cmd, char *replacement) +{ + cmd->flags |= (CMD_DEPRECATED | DEPRECATED_WARN_USER); + + if (replacement != NULL) + cmd->replacement = replacement; + else + cmd->replacement = NULL; + + return cmd; +} + +struct cmd_list_element * +add_alias_cmd (char *name, char *oldname, enum command_class class, + int abbrev_flag, struct cmd_list_element **list) +{ + /* Must do this since lookup_cmd tries to side-effect its first arg */ + char *copied_name; + struct cmd_list_element *old; + struct cmd_list_element *c; + copied_name = (char *) alloca (strlen (oldname) + 1); + strcpy (copied_name, oldname); + old = lookup_cmd (&copied_name, *list, "", 1, 1); + + if (old == 0) + { + struct cmd_list_element *prehook, *prehookee, *posthook, *posthookee; + struct cmd_list_element *aliases = delete_cmd (name, list, + &prehook, &prehookee, + &posthook, &posthookee); + /* If this happens, it means a programmer error somewhere. */ + gdb_assert (!aliases && !prehook && !prehookee + && !posthook && ! posthookee); + return 0; + } + + c = add_cmd (name, class, NULL, old->doc, list); + /* NOTE: Both FUNC and all the FUNCTIONs need to be copied. */ + c->func = old->func; + c->function = old->function; + c->prefixlist = old->prefixlist; + c->prefixname = old->prefixname; + c->allow_unknown = old->allow_unknown; + c->abbrev_flag = abbrev_flag; + c->cmd_pointer = old; + c->alias_chain = old->aliases; + old->aliases = c; + return c; +} + +/* Like add_cmd but adds an element for a command prefix: + a name that should be followed by a subcommand to be looked up + in another command list. PREFIXLIST should be the address + of the variable containing that list. */ + +struct cmd_list_element * +add_prefix_cmd (char *name, enum command_class class, void (*fun) (char *, int), + char *doc, struct cmd_list_element **prefixlist, + char *prefixname, int allow_unknown, + struct cmd_list_element **list) +{ + struct cmd_list_element *c = add_cmd (name, class, fun, doc, list); + c->prefixlist = prefixlist; + c->prefixname = prefixname; + c->allow_unknown = allow_unknown; + return c; +} + +/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */ + +struct cmd_list_element * +add_abbrev_prefix_cmd (char *name, enum command_class class, + void (*fun) (char *, int), char *doc, + struct cmd_list_element **prefixlist, char *prefixname, + int allow_unknown, struct cmd_list_element **list) +{ + struct cmd_list_element *c = add_cmd (name, class, fun, doc, list); + c->prefixlist = prefixlist; + c->prefixname = prefixname; + c->allow_unknown = allow_unknown; + c->abbrev_flag = 1; + return c; +} + +/* This is an empty "cfunc". */ +void +not_just_help_class_command (char *args, int from_tty) +{ +} + +/* This is an empty "sfunc". */ +static void empty_sfunc (char *, int, struct cmd_list_element *); + +static void +empty_sfunc (char *args, int from_tty, struct cmd_list_element *c) +{ +} + +/* Add element named NAME to command list LIST (the list for set/show + or some sublist thereof). + TYPE is set_cmd or show_cmd. + CLASS is as in add_cmd. + VAR_TYPE is the kind of thing we are setting. + VAR is address of the variable being controlled by this command. + DOC is the documentation string. */ + +static struct cmd_list_element * +add_set_or_show_cmd (char *name, + enum cmd_types type, + enum command_class class, + var_types var_type, + void *var, + char *doc, + struct cmd_list_element **list) +{ + struct cmd_list_element *c = add_cmd (name, class, NULL, doc, list); + gdb_assert (type == set_cmd || type == show_cmd); + c->type = type; + c->var_type = var_type; + c->var = var; + /* This needs to be something besides NULL so that this isn't + treated as a help class. */ + set_cmd_sfunc (c, empty_sfunc); + return c; +} + +/* Add element named NAME to both the command SET_LIST and SHOW_LIST. + CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are + setting. VAR is address of the variable being controlled by this + command. SET_FUNC and SHOW_FUNC are the callback functions (if + non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the documentation + strings. PRINT the format string to print the value. SET_RESULT + and SHOW_RESULT, if not NULL, are set to the resulting command + structures. */ + +static void +add_setshow_cmd_full (char *name, + enum command_class class, + var_types var_type, void *var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list, + struct cmd_list_element **set_result, + struct cmd_list_element **show_result) +{ + struct cmd_list_element *set; + struct cmd_list_element *show; + char *full_set_doc; + char *full_show_doc; + + if (help_doc != NULL) + { + full_set_doc = xstrprintf ("%s\n%s", set_doc, help_doc); + full_show_doc = xstrprintf ("%s\n%s", show_doc, help_doc); + } + else + { + full_set_doc = xstrdup (set_doc); + full_show_doc = xstrdup (show_doc); + } + set = add_set_or_show_cmd (name, set_cmd, class, var_type, var, + full_set_doc, set_list); + if (set_func != NULL) + set_cmd_sfunc (set, set_func); + show = add_set_or_show_cmd (name, show_cmd, class, var_type, var, + full_show_doc, show_list); + show->show_value_func = show_func; + + if (set_result != NULL) + *set_result = set; + if (show_result != NULL) + *show_result = show; +} + +/* Add element named NAME to command list LIST (the list for set or + some sublist thereof). CLASS is as in add_cmd. ENUMLIST is a list + of strings which may follow NAME. VAR is address of the variable + which will contain the matching string (from ENUMLIST). */ + +void +add_setshow_enum_cmd (char *name, + enum command_class class, + const char *enumlist[], + const char **var, + const char *set_doc, + const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + struct cmd_list_element *c; + add_setshow_cmd_full (name, class, var_enum, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + &c, NULL); + c->enums = enumlist; +} + +/* Add an auto-boolean command named NAME to both the set and show + command list lists. CLASS is as in add_cmd. VAR is address of the + variable which will contain the value. DOC is the documentation + string. FUNC is the corresponding callback. */ +void +add_setshow_auto_boolean_cmd (char *name, + enum command_class class, + enum auto_boolean *var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + static const char *auto_boolean_enums[] = { "on", "off", "auto", NULL }; + struct cmd_list_element *c; + add_setshow_cmd_full (name, class, var_auto_boolean, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + &c, NULL); + c->enums = auto_boolean_enums; +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the + value. SET_DOC and SHOW_DOC are the documentation strings. */ +void +add_setshow_boolean_cmd (char *name, enum command_class class, int *var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + static const char *boolean_enums[] = { "on", "off", NULL }; + struct cmd_list_element *c; + add_setshow_cmd_full (name, class, var_boolean, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + &c, NULL); + c->enums = boolean_enums; +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ +void +add_setshow_filename_cmd (char *name, enum command_class class, + char **var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + struct cmd_list_element *set_result; + add_setshow_cmd_full (name, class, var_filename, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + &set_result, NULL); + set_cmd_completer (set_result, filename_completer); +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ +void +add_setshow_string_cmd (char *name, enum command_class class, + char **var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + add_setshow_cmd_full (name, class, var_string, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + NULL, NULL); +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ +void +add_setshow_string_noescape_cmd (char *name, enum command_class class, + char **var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + add_setshow_cmd_full (name, class, var_string_noescape, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + NULL, NULL); +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ +void +add_setshow_optional_filename_cmd (char *name, enum command_class class, + char **var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + struct cmd_list_element *set_result; + + add_setshow_cmd_full (name, class, var_optional_filename, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + &set_result, NULL); + + set_cmd_completer (set_result, filename_completer); + +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the + value. SET_DOC and SHOW_DOC are the documentation strings. */ +void +add_setshow_integer_cmd (char *name, enum command_class class, + int *var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + add_setshow_cmd_full (name, class, var_integer, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + NULL, NULL); +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the + value. SET_DOC and SHOW_DOC are the documentation strings. */ +void +add_setshow_uinteger_cmd (char *name, enum command_class class, + unsigned int *var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + add_setshow_cmd_full (name, class, var_uinteger, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + NULL, NULL); +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the + value. SET_DOC and SHOW_DOC are the documentation strings. */ +void +add_setshow_zinteger_cmd (char *name, enum command_class class, + int *var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + add_setshow_cmd_full (name, class, var_zinteger, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + NULL, NULL); +} + +/* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the + value. SET_DOC and SHOW_DOC are the documentation strings. */ +void +add_setshow_zuinteger_cmd (char *name, enum command_class class, + unsigned int *var, + const char *set_doc, const char *show_doc, + const char *help_doc, + cmd_sfunc_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) +{ + add_setshow_cmd_full (name, class, var_zuinteger, var, + set_doc, show_doc, help_doc, + set_func, show_func, + set_list, show_list, + NULL, NULL); +} + +/* Remove the command named NAME from the command list. Return the + list commands which were aliased to the deleted command. If the + command had no aliases, return NULL. The various *HOOKs are set to + the pre- and post-hook commands for the deleted command. If the + command does not have a hook, the corresponding out parameter is + set to NULL. */ + +static struct cmd_list_element * +delete_cmd (char *name, struct cmd_list_element **list, + struct cmd_list_element **prehook, + struct cmd_list_element **prehookee, + struct cmd_list_element **posthook, + struct cmd_list_element **posthookee) +{ + struct cmd_list_element *iter; + struct cmd_list_element **previous_chain_ptr; + struct cmd_list_element *aliases = NULL; + + *prehook = NULL; + *prehookee = NULL; + *posthook = NULL; + *posthookee = NULL; + previous_chain_ptr = list; + + for (iter = *previous_chain_ptr; iter; iter = *previous_chain_ptr) + { + if (strcmp (iter->name, name) == 0) + { + if (iter->destroyer) + iter->destroyer (iter, iter->context); + if (iter->hookee_pre) + iter->hookee_pre->hook_pre = 0; + *prehook = iter->hook_pre; + *prehookee = iter->hookee_pre; + if (iter->hookee_post) + iter->hookee_post->hook_post = 0; + *posthook = iter->hook_post; + *posthookee = iter->hookee_post; + + /* Update the link. */ + *previous_chain_ptr = iter->next; + + aliases = iter->aliases; + + /* If this command was an alias, remove it from the list of + aliases. */ + if (iter->cmd_pointer) + { + struct cmd_list_element **prevp = &iter->cmd_pointer->aliases; + struct cmd_list_element *a = *prevp; + + while (a != iter) + { + prevp = &a->alias_chain; + a = *prevp; + } + *prevp = iter->alias_chain; + } + + xfree (iter); + + /* We won't see another command with the same name. */ + break; + } + else + previous_chain_ptr = &iter->next; + } + + return aliases; +} + +/* Shorthands to the commands above. */ + +/* Add an element to the list of info subcommands. */ + +struct cmd_list_element * +add_info (char *name, void (*fun) (char *, int), char *doc) +{ + return add_cmd (name, no_class, fun, doc, &infolist); +} + +/* Add an alias to the list of info subcommands. */ + +struct cmd_list_element * +add_info_alias (char *name, char *oldname, int abbrev_flag) +{ + return add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist); +} + +/* Add an element to the list of commands. */ + +struct cmd_list_element * +add_com (char *name, enum command_class class, void (*fun) (char *, int), + char *doc) +{ + return add_cmd (name, class, fun, doc, &cmdlist); +} + +/* Add an alias or abbreviation command to the list of commands. */ + +struct cmd_list_element * +add_com_alias (char *name, char *oldname, enum command_class class, + int abbrev_flag) +{ + return add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist); +} + +/* Recursively walk the commandlist structures, and print out the + documentation of commands that match our regex in either their + name, or their documentation. +*/ +void +apropos_cmd (struct ui_file *stream, struct cmd_list_element *commandlist, + struct re_pattern_buffer *regex, char *prefix) +{ + struct cmd_list_element *c; + int returnvalue; + /* Walk through the commands */ + for (c=commandlist;c;c=c->next) + { + returnvalue = -1; /*Needed to avoid double printing*/ + if (c->name != NULL) + { + /* Try to match against the name*/ + returnvalue=re_search(regex,c->name,strlen(c->name),0,strlen(c->name),NULL); + if (returnvalue >= 0) + { + print_help_for_command (c, prefix, + 0 /* don't recurse */, stream); + } + } + if (c->doc != NULL && returnvalue < 0) + { + /* Try to match against documentation */ + if (re_search(regex,c->doc,strlen(c->doc),0,strlen(c->doc),NULL) >=0) + { + print_help_for_command (c, prefix, + 0 /* don't recurse */, stream); + } + } + /* Check if this command has subcommands and is not an abbreviation. + We skip listing subcommands of abbreviations in order to avoid + duplicates in the output. + */ + if (c->prefixlist != NULL && !c->abbrev_flag) + { + /* Recursively call ourselves on the subcommand list, + passing the right prefix in. + */ + apropos_cmd (stream,*c->prefixlist,regex,c->prefixname); + } + } +} + +/* This command really has to deal with two things: + * 1) I want documentation on *this string* (usually called by + * "help commandname"). + * 2) I want documentation on *this list* (usually called by + * giving a command that requires subcommands. Also called by saying + * just "help".) + * + * I am going to split this into two seperate comamnds, help_cmd and + * help_list. + */ + +void +help_cmd (char *command, struct ui_file *stream) +{ + struct cmd_list_element *c; + extern struct cmd_list_element *cmdlist; + + if (!command) + { + help_list (cmdlist, "", all_classes, stream); + return; + } + + if (strcmp (command, "all") == 0) + { + help_all (stream); + return; + } + + c = lookup_cmd (&command, cmdlist, "", 0, 0); + + if (c == 0) + return; + + /* There are three cases here. + If c->prefixlist is nonzero, we have a prefix command. + Print its documentation, then list its subcommands. + + If c->func is non NULL, we really have a command. Print its + documentation and return. + + If c->func is NULL, we have a class name. Print its + documentation (as if it were a command) and then set class to the + number of this class so that the commands in the class will be + listed. */ + + fputs_filtered (c->doc, stream); + fputs_filtered ("\n", stream); + + if (c->prefixlist == 0 && c->func != NULL) + return; + fprintf_filtered (stream, "\n"); + + /* If this is a prefix command, print it's subcommands */ + if (c->prefixlist) + help_list (*c->prefixlist, c->prefixname, all_commands, stream); + + /* If this is a class name, print all of the commands in the class */ + if (c->func == NULL) + help_list (cmdlist, "", c->class, stream); + + if (c->hook_pre || c->hook_post) + fprintf_filtered (stream, + "\nThis command has a hook (or hooks) defined:\n"); + + if (c->hook_pre) + fprintf_filtered (stream, + "\tThis command is run after : %s (pre hook)\n", + c->hook_pre->name); + if (c->hook_post) + fprintf_filtered (stream, + "\tThis command is run before : %s (post hook)\n", + c->hook_post->name); +} + +/* + * Get a specific kind of help on a command list. + * + * LIST is the list. + * CMDTYPE is the prefix to use in the title string. + * CLASS is the class with which to list the nodes of this list (see + * documentation for help_cmd_list below), As usual, ALL_COMMANDS for + * everything, ALL_CLASSES for just classes, and non-negative for only things + * in a specific class. + * and STREAM is the output stream on which to print things. + * If you call this routine with a class >= 0, it recurses. + */ +void +help_list (struct cmd_list_element *list, char *cmdtype, + enum command_class class, struct ui_file *stream) +{ + int len; + char *cmdtype1, *cmdtype2; + + /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */ + len = strlen (cmdtype); + cmdtype1 = (char *) alloca (len + 1); + cmdtype1[0] = 0; + cmdtype2 = (char *) alloca (len + 4); + cmdtype2[0] = 0; + if (len) + { + cmdtype1[0] = ' '; + strncpy (cmdtype1 + 1, cmdtype, len - 1); + cmdtype1[len] = 0; + strncpy (cmdtype2, cmdtype, len - 1); + strcpy (cmdtype2 + len - 1, " sub"); + } + + if (class == all_classes) + fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2); + else + fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2); + + help_cmd_list (list, class, cmdtype, (int) class >= 0, stream); + + if (class == all_classes) + { + fprintf_filtered (stream, "\n\ +Type \"help%s\" followed by a class name for a list of commands in ", + cmdtype1); + wrap_here (""); + fprintf_filtered (stream, "that class."); + + fprintf_filtered (stream, "\n\ +Type \"help all\" for the list of all commands."); + } + + fprintf_filtered (stream, "\nType \"help%s\" followed by %scommand name ", + cmdtype1, cmdtype2); + wrap_here (""); + fputs_filtered ("for ", stream); + wrap_here (""); + fputs_filtered ("full ", stream); + wrap_here (""); + fputs_filtered ("documentation.\n", stream); + fputs_filtered ("Type \"apropos word\" to search " + "for commands related to \"word\".\n", stream); + fputs_filtered ("Command name abbreviations are allowed if unambiguous.\n", + stream); +} + +static void +help_all (struct ui_file *stream) +{ + struct cmd_list_element *c; + extern struct cmd_list_element *cmdlist; + int seen_unclassified = 0; + + for (c = cmdlist; c; c = c->next) + { + if (c->abbrev_flag) + continue; + /* If this is a class name, print all of the commands in the class */ + + if (c->func == NULL) + { + fprintf_filtered (stream, "\nCommand class: %s\n\n", c->name); + help_cmd_list (cmdlist, c->class, "", 1, stream); + } + } + + /* While it's expected that all commands are in some class, + as a safety measure, we'll print commands outside of any + class at the end. */ + + for (c = cmdlist; c; c = c->next) + { + if (c->abbrev_flag) + continue; + + if (c->class == no_class) + { + if (!seen_unclassified) + { + fprintf_filtered (stream, "\nUnclassified commands\n\n"); + seen_unclassified = 1; + } + print_help_for_command (c, "", 1, stream); + } + } + +} + +/* Print only the first line of STR on STREAM. */ +void +print_doc_line (struct ui_file *stream, char *str) +{ + static char *line_buffer = 0; + static int line_size; + char *p; + + if (!line_buffer) + { + line_size = 80; + line_buffer = (char *) xmalloc (line_size); + } + + p = str; + while (*p && *p != '\n' && *p != '.' && *p != ',') + p++; + if (p - str > line_size - 1) + { + line_size = p - str + 1; + xfree (line_buffer); + line_buffer = (char *) xmalloc (line_size); + } + strncpy (line_buffer, str, p - str); + line_buffer[p - str] = '\0'; + if (islower (line_buffer[0])) + line_buffer[0] = toupper (line_buffer[0]); + ui_out_text (uiout, line_buffer); +} + +/* Print one-line help for command C. + If RECURSE is non-zero, also print one-line descriptions + of all prefixed subcommands. */ +static void +print_help_for_command (struct cmd_list_element *c, char *prefix, int recurse, + struct ui_file *stream) +{ + fprintf_filtered (stream, "%s%s -- ", prefix, c->name); + print_doc_line (stream, c->doc); + fputs_filtered ("\n", stream); + + if (recurse + && c->prefixlist != 0 + && c->abbrev_flag == 0) + /* Subcommands of a prefix command typically have 'all_commands' + as class. If we pass CLASS to recursive invocation, + most often we won't see anything. */ + help_cmd_list (*c->prefixlist, all_commands, c->prefixname, 1, stream); +} + +/* + * Implement a help command on command list LIST. + * RECURSE should be non-zero if this should be done recursively on + * all sublists of LIST. + * PREFIX is the prefix to print before each command name. + * STREAM is the stream upon which the output should be written. + * CLASS should be: + * A non-negative class number to list only commands in that + * class. + * ALL_COMMANDS to list all commands in list. + * ALL_CLASSES to list all classes in list. + * + * Note that RECURSE will be active on *all* sublists, not just the + * ones selected by the criteria above (ie. the selection mechanism + * is at the low level, not the high-level). + */ +void +help_cmd_list (struct cmd_list_element *list, enum command_class class, + char *prefix, int recurse, struct ui_file *stream) +{ + struct cmd_list_element *c; + + for (c = list; c; c = c->next) + { + if (c->abbrev_flag == 0 + && (class == all_commands + || (class == all_classes && c->func == NULL) + || (class == c->class && c->func != NULL))) + { + print_help_for_command (c, prefix, recurse, stream); + } + else if (c->abbrev_flag == 0 && recurse + && class == class_user && c->prefixlist != NULL) + /* User-defined commands may be subcommands. */ + help_cmd_list (*c->prefixlist, class, c->prefixname, recurse, stream); + } +} + + +/* Search the input clist for 'command'. Return the command if + found (or NULL if not), and return the number of commands + found in nfound */ + +static struct cmd_list_element * +find_cmd (char *command, int len, struct cmd_list_element *clist, + int ignore_help_classes, int *nfound) +{ + struct cmd_list_element *found, *c; + + found = (struct cmd_list_element *) NULL; + *nfound = 0; + for (c = clist; c; c = c->next) + if (!strncmp (command, c->name, len) + && (!ignore_help_classes || c->func)) + { + found = c; + (*nfound)++; + if (c->name[len] == '\0') + { + *nfound = 1; + break; + } + } + return found; +} + +static int +find_command_name_length (const char *text) +{ + const char *p = text; + + /* Treating underscores as part of command words is important + so that "set args_foo()" doesn't get interpreted as + "set args _foo()". */ + /* Some characters are only used for TUI specific commands. However, they + are always allowed for the sake of consistency. + The XDB compatibility characters are only allowed when using the right + mode because they clash with other GDB commands - specifically '/' is + used as a suffix for print, examine and display. + Note that this is larger than the character set allowed when creating + user-defined commands. */ + while (isalnum (*p) || *p == '-' || *p == '_' + /* Characters used by TUI specific commands. */ + || *p == '+' || *p == '<' || *p == '>' || *p == '$' + /* Characters used for XDB compatibility. */ + || (xdb_commands && (*p == '!' || *p == '/' || *p == '?'))) + p++; + + return p - text; +} + +/* This routine takes a line of TEXT and a CLIST in which to start the + lookup. When it returns it will have incremented the text pointer past + the section of text it matched, set *RESULT_LIST to point to the list in + which the last word was matched, and will return a pointer to the cmd + list element which the text matches. It will return NULL if no match at + all was possible. It will return -1 (cast appropriately, ick) if ambigous + matches are possible; in this case *RESULT_LIST will be set to point to + the list in which there are ambiguous choices (and *TEXT will be set to + the ambiguous text string). + + If the located command was an abbreviation, this routine returns the base + command of the abbreviation. + + It does no error reporting whatsoever; control will always return + to the superior routine. + + In the case of an ambiguous return (-1), *RESULT_LIST will be set to point + at the prefix_command (ie. the best match) *or* (special case) will be NULL + if no prefix command was ever found. For example, in the case of "info a", + "info" matches without ambiguity, but "a" could be "args" or "address", so + *RESULT_LIST is set to the cmd_list_element for "info". So in this case + RESULT_LIST should not be interpeted as a pointer to the beginning of a + list; it simply points to a specific command. In the case of an ambiguous + return *TEXT is advanced past the last non-ambiguous prefix (e.g. + "info t" can be "info types" or "info target"; upon return *TEXT has been + advanced past "info "). + + If RESULT_LIST is NULL, don't set *RESULT_LIST (but don't otherwise + affect the operation). + + This routine does *not* modify the text pointed to by TEXT. + + If IGNORE_HELP_CLASSES is nonzero, ignore any command list elements which + are actually help classes rather than commands (i.e. the function field of + the struct cmd_list_element is NULL). */ + +struct cmd_list_element * +lookup_cmd_1 (char **text, struct cmd_list_element *clist, + struct cmd_list_element **result_list, int ignore_help_classes) +{ + char *command; + int len, tmp, nfound; + struct cmd_list_element *found, *c; + char *line = *text; + + while (**text == ' ' || **text == '\t') + (*text)++; + + /* Identify the name of the command. */ + len = find_command_name_length (*text); + + /* If nothing but whitespace, return 0. */ + if (len == 0) + return 0; + + /* *text and p now bracket the first command word to lookup (and + it's length is len). We copy this into a local temporary */ + + + command = (char *) alloca (len + 1); + memcpy (command, *text, len); + command[len] = '\0'; + + /* Look it up. */ + found = 0; + nfound = 0; + found = find_cmd (command, len, clist, ignore_help_classes, &nfound); + + /* + ** We didn't find the command in the entered case, so lower case it + ** and search again. + */ + if (!found || nfound == 0) + { + for (tmp = 0; tmp < len; tmp++) + { + char x = command[tmp]; + command[tmp] = isupper (x) ? tolower (x) : x; + } + found = find_cmd (command, len, clist, ignore_help_classes, &nfound); + } + + /* If nothing matches, we have a simple failure. */ + if (nfound == 0) + return 0; + + if (nfound > 1) + { + if (result_list != NULL) + /* Will be modified in calling routine + if we know what the prefix command is. */ + *result_list = 0; + return (struct cmd_list_element *) -1; /* Ambiguous. */ + } + + /* We've matched something on this list. Move text pointer forward. */ + + *text += len; + + if (found->cmd_pointer) + { + /* We drop the alias (abbreviation) in favor of the command it is + pointing to. If the alias is deprecated, though, we need to + warn the user about it before we drop it. Note that while we + are warning about the alias, we may also warn about the command + itself and we will adjust the appropriate DEPRECATED_WARN_USER + flags */ + + if (found->flags & DEPRECATED_WARN_USER) + deprecated_cmd_warning (&line); + found = found->cmd_pointer; + } + /* If we found a prefix command, keep looking. */ + + if (found->prefixlist) + { + c = lookup_cmd_1 (text, *found->prefixlist, result_list, + ignore_help_classes); + if (!c) + { + /* Didn't find anything; this is as far as we got. */ + if (result_list != NULL) + *result_list = clist; + return found; + } + else if (c == (struct cmd_list_element *) -1) + { + /* We've gotten this far properly, but the next step + is ambiguous. We need to set the result list to the best + we've found (if an inferior hasn't already set it). */ + if (result_list != NULL) + if (!*result_list) + /* This used to say *result_list = *found->prefixlist + If that was correct, need to modify the documentation + at the top of this function to clarify what is supposed + to be going on. */ + *result_list = found; + return c; + } + else + { + /* We matched! */ + return c; + } + } + else + { + if (result_list != NULL) + *result_list = clist; + return found; + } +} + +/* All this hair to move the space to the front of cmdtype */ + +static void +undef_cmd_error (char *cmdtype, char *q) +{ + error (_("Undefined %scommand: \"%s\". Try \"help%s%.*s\"."), + cmdtype, + q, + *cmdtype ? " " : "", + (int) strlen (cmdtype) - 1, + cmdtype); +} + +/* Look up the contents of *LINE as a command in the command list LIST. + LIST is a chain of struct cmd_list_element's. + If it is found, return the struct cmd_list_element for that command + and update *LINE to point after the command name, at the first argument. + If not found, call error if ALLOW_UNKNOWN is zero + otherwise (or if error returns) return zero. + Call error if specified command is ambiguous, + unless ALLOW_UNKNOWN is negative. + CMDTYPE precedes the word "command" in the error message. + + If INGNORE_HELP_CLASSES is nonzero, ignore any command list + elements which are actually help classes rather than commands (i.e. + the function field of the struct cmd_list_element is 0). */ + +struct cmd_list_element * +lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype, + int allow_unknown, int ignore_help_classes) +{ + struct cmd_list_element *last_list = 0; + struct cmd_list_element *c; + + /* Note: Do not remove trailing whitespace here because this + would be wrong for complete_command. Jim Kingdon */ + + if (!*line) + error (_("Lack of needed %scommand"), cmdtype); + + c = lookup_cmd_1 (line, list, &last_list, ignore_help_classes); + + if (!c) + { + if (!allow_unknown) + { + char *q; + int len = find_command_name_length (*line); + + q = (char *) alloca (len + 1); + strncpy (q, *line, len); + q[len] = '\0'; + undef_cmd_error (cmdtype, q); + } + else + return 0; + } + else if (c == (struct cmd_list_element *) -1) + { + /* Ambigous. Local values should be off prefixlist or called + values. */ + int local_allow_unknown = (last_list ? last_list->allow_unknown : + allow_unknown); + char *local_cmdtype = last_list ? last_list->prefixname : cmdtype; + struct cmd_list_element *local_list = + (last_list ? *(last_list->prefixlist) : list); + + if (local_allow_unknown < 0) + { + if (last_list) + return last_list; /* Found something. */ + else + return 0; /* Found nothing. */ + } + else + { + /* Report as error. */ + int amb_len; + char ambbuf[100]; + + for (amb_len = 0; + ((*line)[amb_len] && (*line)[amb_len] != ' ' + && (*line)[amb_len] != '\t'); + amb_len++) + ; + + ambbuf[0] = 0; + for (c = local_list; c; c = c->next) + if (!strncmp (*line, c->name, amb_len)) + { + if (strlen (ambbuf) + strlen (c->name) + 6 < (int) sizeof ambbuf) + { + if (strlen (ambbuf)) + strcat (ambbuf, ", "); + strcat (ambbuf, c->name); + } + else + { + strcat (ambbuf, ".."); + break; + } + } + error (_("Ambiguous %scommand \"%s\": %s."), local_cmdtype, + *line, ambbuf); + return 0; /* lint */ + } + } + else + { + /* We've got something. It may still not be what the caller + wants (if this command *needs* a subcommand). */ + while (**line == ' ' || **line == '\t') + (*line)++; + + if (c->prefixlist && **line && !c->allow_unknown) + undef_cmd_error (c->prefixname, *line); + + /* Seems to be what he wants. Return it. */ + return c; + } + return 0; +} + +/* We are here presumably because an alias or command in *TEXT is + deprecated and a warning message should be generated. This function + decodes *TEXT and potentially generates a warning message as outlined + below. + + Example for 'set endian big' which has a fictitious alias 'seb'. + + If alias wasn't used in *TEXT, and the command is deprecated: + "warning: 'set endian big' is deprecated." + + If alias was used, and only the alias is deprecated: + "warning: 'seb' an alias for the command 'set endian big' is deprecated." + + If alias was used and command is deprecated (regardless of whether the + alias itself is deprecated: + + "warning: 'set endian big' (seb) is deprecated." + + After the message has been sent, clear the appropriate flags in the + command and/or the alias so the user is no longer bothered. + +*/ +void +deprecated_cmd_warning (char **text) +{ + struct cmd_list_element *alias = NULL; + struct cmd_list_element *prefix_cmd = NULL; + struct cmd_list_element *cmd = NULL; + struct cmd_list_element *c; + char *type; + + if (!lookup_cmd_composition (*text, &alias, &prefix_cmd, &cmd)) + /* return if text doesn't evaluate to a command */ + return; + + if (!((alias ? (alias->flags & DEPRECATED_WARN_USER) : 0) + || (cmd->flags & DEPRECATED_WARN_USER) ) ) + /* return if nothing is deprecated */ + return; + + printf_filtered ("Warning:"); + + if (alias && !(cmd->flags & CMD_DEPRECATED)) + printf_filtered (" '%s', an alias for the", alias->name); + + printf_filtered (" command '"); + + if (prefix_cmd) + printf_filtered ("%s", prefix_cmd->prefixname); + + printf_filtered ("%s", cmd->name); + + if (alias && (cmd->flags & CMD_DEPRECATED)) + printf_filtered ("' (%s) is deprecated.\n", alias->name); + else + printf_filtered ("' is deprecated.\n"); + + + /* if it is only the alias that is deprecated, we want to indicate the + new alias, otherwise we'll indicate the new command */ + + if (alias && !(cmd->flags & CMD_DEPRECATED)) + { + if (alias->replacement) + printf_filtered ("Use '%s'.\n\n", alias->replacement); + else + printf_filtered ("No alternative known.\n\n"); + } + else + { + if (cmd->replacement) + printf_filtered ("Use '%s'.\n\n", cmd->replacement); + else + printf_filtered ("No alternative known.\n\n"); + } + + /* We've warned you, now we'll keep quiet */ + if (alias) + alias->flags &= ~DEPRECATED_WARN_USER; + + cmd->flags &= ~DEPRECATED_WARN_USER; +} + + + +/* Look up the contents of LINE as a command in the command list 'cmdlist'. + Return 1 on success, 0 on failure. + + If LINE refers to an alias, *alias will point to that alias. + + If LINE is a postfix command (i.e. one that is preceeded by a prefix + command) set *prefix_cmd. + + Set *cmd to point to the command LINE indicates. + + If any of *alias, *prefix_cmd, or *cmd cannot be determined or do not + exist, they are NULL when we return. + +*/ +int +lookup_cmd_composition (char *text, + struct cmd_list_element **alias, + struct cmd_list_element **prefix_cmd, + struct cmd_list_element **cmd) +{ + char *command; + int len, tmp, nfound; + struct cmd_list_element *cur_list; + struct cmd_list_element *prev_cmd; + *alias = NULL; + *prefix_cmd = NULL; + *cmd = NULL; + + cur_list = cmdlist; + + while (1) + { + /* Go through as many command lists as we need to + to find the command TEXT refers to. */ + + prev_cmd = *cmd; + + while (*text == ' ' || *text == '\t') + (text)++; + + /* Identify the name of the command. */ + len = find_command_name_length (text); + + /* If nothing but whitespace, return. */ + if (len == 0) + return 0; + + /* text is the start of the first command word to lookup (and + it's length is len). We copy this into a local temporary */ + + command = (char *) alloca (len + 1); + memcpy (command, text, len); + command[len] = '\0'; + + /* Look it up. */ + *cmd = 0; + nfound = 0; + *cmd = find_cmd (command, len, cur_list, 1, &nfound); + + /* We didn't find the command in the entered case, so lower case it + and search again. + */ + if (!*cmd || nfound == 0) + { + for (tmp = 0; tmp < len; tmp++) + { + char x = command[tmp]; + command[tmp] = isupper (x) ? tolower (x) : x; + } + *cmd = find_cmd (command, len, cur_list, 1, &nfound); + } + + if (*cmd == (struct cmd_list_element *) -1) + { + return 0; /* ambiguous */ + } + + if (*cmd == NULL) + return 0; /* nothing found */ + else + { + if ((*cmd)->cmd_pointer) + { + /* cmd was actually an alias, we note that an alias was used + (by assigning *alais) and we set *cmd. + */ + *alias = *cmd; + *cmd = (*cmd)->cmd_pointer; + } + *prefix_cmd = prev_cmd; + } + if ((*cmd)->prefixlist) + cur_list = *(*cmd)->prefixlist; + else + return 1; + + text += len; + } +} + +/* Helper function for SYMBOL_COMPLETION_FUNCTION. */ + +/* Return a vector of char pointers which point to the different + possible completions in LIST of TEXT. + + WORD points in the same buffer as TEXT, and completions should be + returned relative to this position. For example, suppose TEXT is "foo" + and we want to complete to "foobar". If WORD is "oo", return + "oobar"; if WORD is "baz/foo", return "baz/foobar". */ + +char ** +complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word) +{ + struct cmd_list_element *ptr; + char **matchlist; + int sizeof_matchlist; + int matches; + int textlen = strlen (text); + + sizeof_matchlist = 10; + matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *)); + matches = 0; + + for (ptr = list; ptr; ptr = ptr->next) + if (!strncmp (ptr->name, text, textlen) + && !ptr->abbrev_flag + && (ptr->func + || ptr->prefixlist)) + { + if (matches == sizeof_matchlist) + { + sizeof_matchlist *= 2; + matchlist = (char **) xrealloc ((char *) matchlist, + (sizeof_matchlist + * sizeof (char *))); + } + + matchlist[matches] = (char *) + xmalloc (strlen (word) + strlen (ptr->name) + 1); + if (word == text) + strcpy (matchlist[matches], ptr->name); + else if (word > text) + { + /* Return some portion of ptr->name. */ + strcpy (matchlist[matches], ptr->name + (word - text)); + } + else + { + /* Return some of text plus ptr->name. */ + strncpy (matchlist[matches], word, text - word); + matchlist[matches][text - word] = '\0'; + strcat (matchlist[matches], ptr->name); + } + ++matches; + } + + if (matches == 0) + { + xfree (matchlist); + matchlist = 0; + } + else + { + matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1) + * sizeof (char *))); + matchlist[matches] = (char *) 0; + } + + return matchlist; +} + +/* Helper function for SYMBOL_COMPLETION_FUNCTION. */ + +/* Return a vector of char pointers which point to the different + possible completions in CMD of TEXT. + + WORD points in the same buffer as TEXT, and completions should be + returned relative to this position. For example, suppose TEXT is "foo" + and we want to complete to "foobar". If WORD is "oo", return + "oobar"; if WORD is "baz/foo", return "baz/foobar". */ + +char ** +complete_on_enum (const char *enumlist[], + char *text, + char *word) +{ + char **matchlist; + int sizeof_matchlist; + int matches; + int textlen = strlen (text); + int i; + const char *name; + + sizeof_matchlist = 10; + matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *)); + matches = 0; + + for (i = 0; (name = enumlist[i]) != NULL; i++) + if (strncmp (name, text, textlen) == 0) + { + if (matches == sizeof_matchlist) + { + sizeof_matchlist *= 2; + matchlist = (char **) xrealloc ((char *) matchlist, + (sizeof_matchlist + * sizeof (char *))); + } + + matchlist[matches] = (char *) + xmalloc (strlen (word) + strlen (name) + 1); + if (word == text) + strcpy (matchlist[matches], name); + else if (word > text) + { + /* Return some portion of name. */ + strcpy (matchlist[matches], name + (word - text)); + } + else + { + /* Return some of text plus name. */ + strncpy (matchlist[matches], word, text - word); + matchlist[matches][text - word] = '\0'; + strcat (matchlist[matches], name); + } + ++matches; + } + + if (matches == 0) + { + xfree (matchlist); + matchlist = 0; + } + else + { + matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1) + * sizeof (char *))); + matchlist[matches] = (char *) 0; + } + + return matchlist; +} + + +/* check function pointer */ +int +cmd_func_p (struct cmd_list_element *cmd) +{ + return (cmd->func != NULL); +} + + +/* call the command function */ +void +cmd_func (struct cmd_list_element *cmd, char *args, int from_tty) +{ + if (cmd_func_p (cmd)) + (*cmd->func) (cmd, args, from_tty); + else + error (_("Invalid command")); +}
cli-decode.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-script.c =================================================================== --- cli-script.c (nonexistent) +++ cli-script.c (revision 842) @@ -0,0 +1,1605 @@ +/* GDB CLI command scripting. + + 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 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#include "defs.h" +#include "value.h" +#include "language.h" /* For value_true */ +#include + +#include "ui-out.h" +#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" + +#include "python/python.h" + +/* Prototypes for local functions */ + +static enum command_control_type +recurse_read_control_structure (char * (*read_next_line_func) (), + struct command_line *current_cmd); + +static char *insert_args (char *line); + +static struct cleanup * setup_user_args (char *p); + +static char *read_next_line (); + +/* 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; + int len; + } + a[MAXUSERARGS]; + int count; + } + *user_args; + + +/* Allocate, initialize a new command line structure for one of the + control commands (if/while). */ + +static struct command_line * +build_command_line (enum command_control_type type, char *args) +{ + struct command_line *cmd; + + 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; + cmd->control_type = type; + + cmd->body_count = 1; + cmd->body_list + = (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 = xstrdup (args); + + return cmd; +} + +/* Build and return a new command structure for the control commands + such as "if" and "while". */ + +struct command_line * +get_command_line (enum command_control_type type, char *arg) +{ + struct command_line *cmd; + struct cleanup *old_chain = NULL; + + /* Allocate and build a new command line structure. */ + cmd = build_command_line (type, arg); + + old_chain = make_cleanup_free_command_lines (&cmd); + + /* Read in the body of this command. */ + if (recurse_read_control_structure (read_next_line, cmd) == invalid_control) + { + warning (_("Error reading in canned sequence of commands.")); + do_cleanups (old_chain); + return NULL; + } + + discard_cleanups (old_chain); + return cmd; +} + +/* Recursively print a command (including full control structures). */ + +void +print_command_lines (struct ui_out *uiout, struct command_line *cmd, + unsigned int depth) +{ + struct command_line *list; + + list = cmd; + while (list) + { + + if (depth) + ui_out_spaces (uiout, 2 * depth); + + /* A simple command, print it and continue. */ + if (list->control_type == simple_control) + { + ui_out_field_string (uiout, NULL, list->line); + ui_out_text (uiout, "\n"); + list = list->next; + continue; + } + + /* loop_continue to jump to the start of a while loop, print it + and continue. */ + if (list->control_type == continue_control) + { + ui_out_field_string (uiout, NULL, "loop_continue"); + ui_out_text (uiout, "\n"); + list = list->next; + 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"); + ui_out_text (uiout, "\n"); + list = list->next; + continue; + } + + /* A while command. Recursively print its subcommands and continue. */ + if (list->control_type == while_control) + { + ui_out_field_fmt (uiout, NULL, "while %s", list->line); + 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; + } + + /* 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. */ + print_command_lines (uiout, list->body_list[0], depth + 1); + + /* Show the false arm if it exists. */ + if (list->body_count == 2) + { + if (depth) + ui_out_spaces (uiout, 2 * depth); + ui_out_field_string (uiout, NULL, "else"); + ui_out_text (uiout, "\n"); + print_command_lines (uiout, list->body_list[1], 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; + } + + /* 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) */ +} + +/* Handle pre-post hooks. */ + +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 */ +} + +void +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 */ + execute_user_command (c->hook_pre, (char *) 0); + do_cleanups (cleanups); + } +} + +void +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 */ + execute_user_command (c->hook_post, (char *) 0); + do_cleanups (cleanups); + } +} + +/* Execute the command in CMD. */ +static void +do_restore_user_call_depth (void * call_depth) +{ + int * depth = call_depth; + (*depth)--; + if ((*depth) == 0) + in_user_command = 0; +} + + +void +execute_user_command (struct cmd_list_element *c, char *args) +{ + struct command_line *cmdlines; + struct cleanup *old_chain; + enum command_control_type ret; + static int user_call_depth = 0; + extern int max_user_call_depth; + + old_chain = setup_user_args (args); + + cmdlines = c->user_commands; + if (cmdlines == 0) + /* Null command */ + return; + + if (++user_call_depth > max_user_call_depth) + error (_("Max user call depth exceeded -- command aborted.")); + + make_cleanup (do_restore_user_call_depth, &user_call_depth); + + /* Set the instream to 0, indicating execution of a + user-defined function. */ + 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 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 to 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; + + for (i=0; i < command_nest_depth; i++) + printf_filtered ("+"); + + printf_filtered ("%s\n", cmd); +} + +enum command_control_type +execute_control_command (struct command_line *cmd) +{ + struct expression *expr; + struct command_line *current; + struct cleanup *old_chain = make_cleanup (null_cleanup, 0); + struct value *val; + struct value *val_mark; + int loop; + enum command_control_type ret; + char *new_line; + + /* Start by assuming failure, if a problem is detected, the code + below will simply "break" out of the switch. */ + ret = invalid_control; + + switch (cmd->control_type) + { + case simple_control: + /* A simple command, execute it and return. */ + new_line = insert_args (cmd->line); + if (!new_line) + break; + make_cleanup (free_current_contents, &new_line); + execute_command (new_line, 0); + ret = cmd->control_type; + 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; + break; + + 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) + break; + make_cleanup (free_current_contents, &new_line); + expr = parse_expression (new_line); + make_cleanup (free_current_contents, &expr); + + ret = simple_control; + loop = 1; + + /* Keep iterating so long as the expression is true. */ + while (loop == 1) + { + int cond_result; + + QUIT; + + /* Evaluate the expression. */ + val_mark = value_mark (); + val = evaluate_expression (expr); + cond_result = value_true (val); + value_free_to_mark (val_mark); + + /* If the value is false, then break out of the loop. */ + if (!cond_result) + break; + + /* Execute the body of the while statement. */ + 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. */ + if (ret == invalid_control || ret == break_control) + { + loop = 0; + break; + } + + /* If we got a "continue" command, then restart the loop + at this point. */ + if (ret == continue_control) + break; + + /* Get the next statement. */ + current = current->next; + } + } + + /* Reset RET so that we don't recurse the break all the way down. */ + if (ret == break_control) + ret = simple_control; + + break; + } + + 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; + make_cleanup (free_current_contents, &new_line); + /* Parse the conditional for the if statement. */ + expr = parse_expression (new_line); + make_cleanup (free_current_contents, &expr); + + current = NULL; + ret = simple_control; + + /* Evaluate the conditional. */ + val_mark = value_mark (); + val = evaluate_expression (expr); + + /* 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) + current = *(cmd->body_list + 1); + value_free_to_mark (val_mark); + + /* 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) + break; + + /* Get the next statement in the body. */ + current = current->next; + } + + 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 canned commands structure.")); + break; + } + + do_cleanups (old_chain); + + 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. */ + +void +while_command (char *arg, int from_tty) +{ + struct command_line *command = NULL; + + control_level = 1; + command = get_command_line (while_control, arg); + + if (command == NULL) + return; + + execute_control_command_untraced (command); + free_command_lines (&command); +} + +/* "if" command support. Execute either the true or false arm depending + on the value of the if conditional. */ + +void +if_command (char *arg, int from_tty) +{ + struct command_line *command = NULL; + + control_level = 1; + command = get_command_line (if_control, arg); + + if (command == NULL) + return; + + execute_control_command_untraced (command); + free_command_lines (&command); +} + +/* Cleanup */ +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); +} + +/* Bind the incomming arguments for a user defined command to + $arg0, $arg1 ... $argMAXUSERARGS. */ + +static struct cleanup * +setup_user_args (char *p) +{ + struct user_args *args; + struct cleanup *old_chain; + unsigned int arg_count = 0; + + args = (struct user_args *) xmalloc (sizeof (struct user_args)); + memset (args, 0, sizeof (struct user_args)); + + args->next = user_args; + user_args = args; + + old_chain = make_cleanup (arg_cleanup, 0/*ignored*/); + + if (p == NULL) + return old_chain; + + user_args->command = p = xstrdup (p); + + while (*p) + { + char *start_arg; + int squote = 0; + int dquote = 0; + int bsquote = 0; + + if (arg_count >= MAXUSERARGS) + { + error (_("user defined function may only have %d arguments."), + MAXUSERARGS); + return old_chain; + } + + /* Strip whitespace. */ + while (*p == ' ' || *p == '\t') + p++; + + /* P now points to an argument. */ + start_arg = p; + user_args->a[arg_count].arg = p; + + /* Get to the end of this argument. */ + while (*p) + { + if (((*p == ' ' || *p == '\t')) && !squote && !dquote && !bsquote) + break; + else + { + if (bsquote) + bsquote = 0; + else if (*p == '\\') + bsquote = 1; + else if (squote) + { + if (*p == '\'') + squote = 0; + } + else if (dquote) + { + if (*p == '"') + dquote = 0; + } + else + { + if (*p == '\'') + squote = 1; + else if (*p == '"') + dquote = 1; + } + p++; + } + } + + user_args->a[arg_count].len = p - start_arg; + arg_count++; + user_args->count++; + } + return old_chain; +} + +/* 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) +{ + while ((p = strchr (p, '$'))) + { + if (strncmp (p, "$arg", 4) == 0 + && (isdigit (p[4]) || p[4] == 'c')) + return p; + p++; + } + return NULL; +} + +/* Insert the user defined arguments stored in user_arg into the $arg + arguments found in line, with the updated copy being placed into nline. */ + +static char * +insert_args (char *line) +{ + char *p, *save_line, *new_line; + unsigned len, i; + + /* 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))) + { + len += p - line; + i = p[4] - '0'; + + if (p[4] == 'c') + { + /* $argc. Number will be <=10. */ + len += user_args->count == 10 ? 2 : 1; + } + else if (i >= user_args->count) + { + error (_("Missing argument %d in user function."), i); + return NULL; + } + else + { + len += user_args->a[i].len; + } + line = p + 5; + } + + /* Don't forget the tail. */ + len += strlen (line); + + /* Allocate space for the new line and fill it in. */ + new_line = (char *) xmalloc (len + 1); + if (new_line == NULL) + return NULL; + + /* Restore pointer to beginning of old line. */ + line = save_line; + + /* Save pointer to beginning of new line. */ + save_line = new_line; + + while ((p = locate_arg (line))) + { + int i, len; + + memcpy (new_line, line, p - line); + new_line += p - line; + + if (p[4] == 'c') + { + gdb_assert (user_args->count >= 0 && user_args->count <= 10); + if (user_args->count == 10) + { + *(new_line++) = '1'; + *(new_line++) = '0'; + } + else + *(new_line++) = user_args->count + '0'; + } + else + { + i = p[4] - '0'; + len = user_args->a[i].len; + if (len) + { + memcpy (new_line, user_args->a[i].arg, len); + new_line += len; + } + } + line = p + 5; + } + /* Don't forget the tail. */ + strcpy (new_line, line); + + /* Return a pointer to the beginning of the new line. */ + return save_line; +} + + +/* Expand the body_list of COMMAND so that it can hold NEW_LENGTH + code bodies. This is typically used when we encounter an "else" + clause for an "if" command. */ + +static void +realloc_body_list (struct command_line *command, int new_length) +{ + int n; + struct command_line **body_list; + + n = command->body_count; + + /* Nothing to do? */ + if (new_length <= n) + return; + + body_list = (struct command_line **) + 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 next line from stdout. Passed to read_command_line_1 and + recurse_read_control_structure whenever we need to read commands + from stdout. */ + +static char * +read_next_line () +{ + char *prompt_ptr, control_prompt[256]; + int i = 0; + + if (control_level >= 254) + error (_("Control nesting too deep!")); + + /* Set a prompt based on the nesting of the control commands. */ + if (instream == stdin || (instream == 0 && deprecated_readline_hook != NULL)) + { + for (i = 0; i < control_level; i++) + control_prompt[i] = ' '; + control_prompt[i] = '>'; + control_prompt[i + 1] = '\0'; + prompt_ptr = (char *) &control_prompt[0]; + } + else + prompt_ptr = NULL; + + 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) +{ + char *p_end; + char *p_start; + int not_handled = 0; + + /* Not sure what to do here. */ + if (p == NULL) + return end_command; + + /* Strip trailing whitespace. */ + p_end = p + strlen (p); + while (p_end > p && (p_end[-1] == ' ' || p_end[-1] == '\t')) + p_end--; + + p_start = p; + /* Strip leading whitespace. */ + while (p_start < p_end && (*p_start == ' ' || *p_start == '\t')) + p_start++; + + /* '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 > 5 && !strncmp (p, "while", 5)) + { + char *first_arg; + 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; + 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; + } + + if (!parse_commands || not_handled) + { + /* A normal command. */ + *command = (struct command_line *) + xmalloc (sizeof (struct command_line)); + (*command)->next = NULL; + (*command)->line = savestring (p, p_end - p); + (*command)->control_type = simple_control; + (*command)->body_count = 0; + (*command)->body_list = NULL; + } + + /* Nothing special. */ + return ok_command; +} + +/* 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 (char * (*read_next_line_func) (), + struct command_line *current_cmd) +{ + int current_body, i; + enum misc_command_type val; + enum command_control_type ret; + struct command_line **body_ptr, *child_tail, *next; + char *p; + + child_tail = NULL; + current_body = 1; + + /* Sanity checks. */ + if (current_cmd->control_type == simple_control) + error (_("Recursed on a simple control type.")); + + if (current_body > current_cmd->body_count) + error (_("Allocated body is smaller than this command type needs.")); + + /* Read lines from the input stream and build control structures. */ + while (1) + { + dont_repeat (); + + next = NULL; + val = process_next_line (read_next_line_func (), &next, + current_cmd->control_type != python_control); + + /* Just skip blanks and comments. */ + if (val == nop_command) + continue; + + if (val == end_command) + { + if (current_cmd->control_type == while_control + || current_cmd->control_type == if_control + || current_cmd->control_type == python_control + || current_cmd->control_type == commands_control) + { + /* Success reading an entire canned sequence of commands. */ + ret = simple_control; + break; + } + else + { + ret = invalid_control; + break; + } + } + + /* Not the end of a control structure. */ + if (val == else_command) + { + if (current_cmd->control_type == if_control + && current_body == 1) + { + realloc_body_list (current_cmd, 2); + current_body = 2; + child_tail = NULL; + continue; + } + else + { + ret = invalid_control; + break; + } + } + + if (child_tail) + { + child_tail->next = next; + } + else + { + body_ptr = current_cmd->body_list; + for (i = 1; i < current_body; i++) + body_ptr++; + + *body_ptr = next; + + } + + child_tail = next; + + /* 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 == python_control + || next->control_type == commands_control) + { + control_level++; + ret = recurse_read_control_structure (read_next_line_func, next); + control_level--; + + if (ret != simple_control) + break; + } + } + + dont_repeat (); + + return ret; +} + +/* 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. + + 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, int parse_commands) +{ + struct command_line *head; + + if (from_tty && input_from_terminal_p ()) + { + 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); + } + } + + head = read_command_lines_1 (read_next_line, parse_commands); + + if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ()) + { + (*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) (), int parse_commands) +{ + 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) + { + dont_repeat (); + val = process_next_line (read_next_line_func (), &next, parse_commands); + + /* Ignore blank lines or comments. */ + if (val == nop_command) + continue; + + if (val == end_command) + { + ret = simple_control; + break; + } + + if (val != ok_command) + { + ret = invalid_control; + break; + } + + if (next->control_type == while_control + || next->control_type == if_control + || next->control_type == python_control + || next->control_type == commands_control) + { + control_level++; + ret = recurse_read_control_structure (read_next_line_func, next); + control_level--; + + if (ret == invalid_control) + break; + } + + if (tail) + { + tail->next = next; + } + else + { + head = next; + old_chain = make_cleanup_free_command_lines (&head); + } + tail = next; + } + + dont_repeat (); + + if (head) + { + if (ret != invalid_control) + { + discard_cleanups (old_chain); + } + else + do_cleanups (old_chain); + } + + return head; +} + +/* Free a chain of struct command_line's. */ + +void +free_command_lines (struct command_line **lptr) +{ + struct command_line *l = *lptr; + struct command_line *next; + struct command_line **blist; + int i; + + while (l) + { + if (l->body_count > 0) + { + blist = l->body_list; + for (i = 0; i < l->body_count; i++, blist++) + free_command_lines (blist); + } + next = l->next; + xfree (l->line); + xfree (l); + l = next; + } + *lptr = NULL; +} + +static void +do_free_command_lines_cleanup (void *arg) +{ + free_command_lines (arg); +} + +struct cleanup * +make_cleanup_free_command_lines (struct command_line **arg) +{ + return make_cleanup (do_free_command_lines_cleanup, arg); +} + +struct command_line * +copy_command_lines (struct command_line *cmds) +{ + struct command_line *result = NULL; + + if (cmds) + { + result = (struct command_line *) xmalloc (sizeof (struct command_line)); + + result->next = copy_command_lines (cmds->next); + result->line = xstrdup (cmds->line); + result->control_type = cmds->control_type; + result->body_count = cmds->body_count; + if (cmds->body_count > 0) + { + int i; + + result->body_list = (struct command_line **) + xmalloc (sizeof (struct command_line *) * cmds->body_count); + + for (i = 0; i < cmds->body_count; i++) + result->body_list[i] = copy_command_lines (cmds->body_list[i]); + } + else + result->body_list = NULL; + } + + return result; +} + +/* 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) +{ + struct cmd_list_element **list = &cmdlist; + char *p, *last_word; + + if (*comname == 0) + error_no_arg (_("name of command to define")); + + /* 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. */ +static void +user_defined_command (char *ignore, int from_tty) +{ +} + +void +define_command (char *comname, int from_tty) +{ +#define MAX_TMPBUF 128 + enum cmd_hook_type + { + CMD_NO_HOOK = 0, + CMD_PRE_HOOK, + CMD_POST_HOOK + }; + struct command_line *cmds; + struct cmd_list_element *c, *newc, *oldc, *hookc = 0, **list; + char *tem, *tem2, *comfull; + char tmpbuf[MAX_TMPBUF]; + int hook_type = CMD_NO_HOOK; + int hook_name_size = 0; + +#define HOOK_STRING "hook-" +#define HOOK_LEN 5 +#define HOOK_POST_STRING "hookpost-" +#define HOOK_POST_LEN 9 + + comfull = comname; + list = validate_comname (&comname); + + /* Look it up, and verify that we got an exact match. */ + 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 + q = query (_("Really redefine built-in command \"%s\"? "), c->name); + if (!q) + error (_("Command \"%s\" not redefined."), c->name); + } + + /* If this new command is a hook, then mark the command which it + is hooking. Note that we allow hooking `help' commands, so that + we can hook the `stop' pseudo-command. */ + + if (!strncmp (comname, HOOK_STRING, HOOK_LEN)) + { + hook_type = CMD_PRE_HOOK; + hook_name_size = HOOK_LEN; + } + else if (!strncmp (comname, HOOK_POST_STRING, HOOK_POST_LEN)) + { + hook_type = CMD_POST_HOOK; + hook_name_size = HOOK_POST_LEN; + } + + if (hook_type != CMD_NO_HOOK) + { + /* Look up cmd it hooks, and verify that we got an exact match. */ + tem = comname + hook_name_size; + 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."), + comfull); + if (!query (_("Proceed? "))) + error (_("Not confirmed.")); + } + } + + comname = xstrdup (comname); + + /* If the rest of the commands will be case insensitive, this one + 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\".", comfull); + cmds = read_command_lines (tmpbuf, from_tty, 1); + + 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 : xstrdup ("User-defined."), list); + newc->user_commands = cmds; + + /* If this new command is a hook, then mark both commands as being + tied. */ + if (hookc) + { + switch (hook_type) + { + case CMD_PRE_HOOK: + hookc->hook_pre = newc; /* Target gets hooked. */ + 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. */ + break; + default: + /* Should never come here as hookc would be 0. */ + internal_error (__FILE__, __LINE__, _("bad switch")); + } + } +} + +void +document_command (char *comname, int from_tty) +{ + struct command_line *doclines; + struct cmd_list_element *c, **list; + char *tem, *comfull; + char tmpbuf[128]; + + comfull = comname; + list = validate_comname (&comname); + + tem = comname; + c = lookup_cmd (&tem, *list, "", 0, 1); + + if (c->class != class_user) + error (_("Command \"%s\" is built-in."), comfull); + + sprintf (tmpbuf, "Type documentation for \"%s\".", comfull); + doclines = read_command_lines (tmpbuf, from_tty, 0); + + if (c->doc) + xfree (c->doc); + + { + struct command_line *cl1; + int len = 0; + + for (cl1 = doclines; cl1; cl1 = cl1->next) + len += strlen (cl1->line) + 1; + + c->doc = (char *) xmalloc (len + 1); + *c->doc = 0; + + for (cl1 = doclines; cl1; cl1 = cl1->next) + { + strcat (c->doc, cl1->line); + if (cl1->next) + strcat (c->doc, "\n"); + } + } + + free_command_lines (&doclines); +} + +struct source_cleanup_lines_args +{ + int old_line; + char *old_file; +}; + +static void +source_cleanup_lines (void *args) +{ + struct source_cleanup_lines_args *p = + (struct source_cleanup_lines_args *) args; + source_line_number = p->old_line; + source_file_name = p->old_file; +} + +struct wrapped_read_command_file_args +{ + FILE *stream; +}; + +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 */ + +void +script_from_file (FILE *stream, 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_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. */ + 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); + switch (e.reason) + { + case 0: + break; + case RETURN_ERROR: + /* Re-throw the error, but with the file name information + prepended. */ + throw_error (e.error, + _("%s:%d: Error in sourced command file:\n%s"), + source_file_name, source_line_number, e.message); + default: + internal_error (__FILE__, __LINE__, _("bad reason")); + } + } + + 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, 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; + fprintf_filtered (stream, "User command \"%s%s\":\n", prefix, name); + + print_command_lines (uiout, cmdlines, 1); + fputs_filtered ("\n", stream); +} +
cli-script.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-dump.c =================================================================== --- cli-dump.c (nonexistent) +++ cli-dump.c (revision 842) @@ -0,0 +1,788 @@ +/* Dump-to-file commands, for GDB, the GNU debugger. + + Copyright (c) 2002, 2005, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + + Contributed by Red Hat. + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#include "defs.h" +#include "gdb_string.h" +#include "cli/cli-decode.h" +#include "cli/cli-cmds.h" +#include "value.h" +#include "completer.h" +#include "cli/cli-dump.h" +#include "gdb_assert.h" +#include +#include "target.h" +#include "readline/readline.h" +#include "gdbcore.h" + +#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) + + +char * +skip_spaces (char *chp) +{ + if (chp == NULL) + return NULL; + while (isspace (*chp)) + chp++; + return chp; +} + +char * +scan_expression_with_cleanup (char **cmd, const char *def) +{ + if ((*cmd) == NULL || (**cmd) == '\0') + { + char *exp = xstrdup (def); + make_cleanup (xfree, exp); + return exp; + } + else + { + char *exp; + char *end; + + end = (*cmd) + strcspn (*cmd, " \t"); + exp = savestring ((*cmd), end - (*cmd)); + make_cleanup (xfree, exp); + (*cmd) = skip_spaces (end); + return exp; + } +} + + +char * +scan_filename_with_cleanup (char **cmd, const char *defname) +{ + char *filename; + char *fullname; + + /* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */ + + /* File. */ + if ((*cmd) == NULL) + { + if (defname == NULL) + error (_("Missing filename.")); + filename = xstrdup (defname); + make_cleanup (xfree, filename); + } + else + { + /* FIXME: should parse a possibly quoted string. */ + char *end; + + (*cmd) = skip_spaces (*cmd); + end = *cmd + strcspn (*cmd, " \t"); + filename = savestring ((*cmd), end - (*cmd)); + make_cleanup (xfree, filename); + (*cmd) = skip_spaces (end); + } + gdb_assert (filename != NULL); + + fullname = tilde_expand (filename); + make_cleanup (xfree, fullname); + + return fullname; +} + +FILE * +fopen_with_cleanup (const char *filename, const char *mode) +{ + FILE *file = fopen (filename, mode); + if (file == NULL) + perror_with_name (filename); + make_cleanup_fclose (file); + return file; +} + +static bfd * +bfd_openr_with_cleanup (const char *filename, const char *target) +{ + bfd *ibfd; + + ibfd = bfd_openr (filename, target); + if (ibfd == NULL) + error (_("Failed to open %s: %s."), filename, + bfd_errmsg (bfd_get_error ())); + + make_cleanup_bfd_close (ibfd); + if (!bfd_check_format (ibfd, bfd_object)) + error (_("'%s' is not a recognized file format."), filename); + + return ibfd; +} + +static bfd * +bfd_openw_with_cleanup (const char *filename, const char *target, + const char *mode) +{ + bfd *obfd; + + if (*mode == 'w') /* Write: create new file */ + { + obfd = bfd_openw (filename, target); + if (obfd == NULL) + error (_("Failed to open %s: %s."), filename, + bfd_errmsg (bfd_get_error ())); + make_cleanup_bfd_close (obfd); + if (!bfd_set_format (obfd, bfd_object)) + error (_("bfd_openw_with_cleanup: %s."), bfd_errmsg (bfd_get_error ())); + } + else if (*mode == 'a') /* Append to existing file */ + { /* FIXME -- doesn't work... */ + error (_("bfd_openw does not work with append.")); + } + else + error (_("bfd_openw_with_cleanup: unknown mode %s."), mode); + + return obfd; +} + +struct cmd_list_element *dump_cmdlist; +struct cmd_list_element *append_cmdlist; +struct cmd_list_element *srec_cmdlist; +struct cmd_list_element *ihex_cmdlist; +struct cmd_list_element *tekhex_cmdlist; +struct cmd_list_element *binary_dump_cmdlist; +struct cmd_list_element *binary_append_cmdlist; + +static void +dump_command (char *cmd, int from_tty) +{ + printf_unfiltered (_("\"dump\" must be followed by a subcommand.\n\n")); + help_list (dump_cmdlist, "dump ", -1, gdb_stdout); +} + +static void +append_command (char *cmd, int from_tty) +{ + printf_unfiltered (_("\"append\" must be followed by a subcommand.\n\n")); + help_list (dump_cmdlist, "append ", -1, gdb_stdout); +} + +static void +dump_binary_file (const char *filename, const char *mode, + const bfd_byte *buf, int len) +{ + FILE *file; + int status; + + file = fopen_with_cleanup (filename, mode); + status = fwrite (buf, len, 1, file); + if (status != 1) + perror_with_name (filename); +} + +static void +dump_bfd_file (const char *filename, const char *mode, + const char *target, CORE_ADDR vaddr, + const bfd_byte *buf, int len) +{ + bfd *obfd; + asection *osection; + + obfd = bfd_openw_with_cleanup (filename, target, mode); + osection = bfd_make_section_anyway (obfd, ".newsec"); + bfd_set_section_size (obfd, osection, len); + bfd_set_section_vma (obfd, osection, vaddr); + bfd_set_section_alignment (obfd, osection, 0); + bfd_set_section_flags (obfd, osection, (SEC_HAS_CONTENTS + | SEC_ALLOC + | SEC_LOAD)); + osection->entsize = 0; + bfd_set_section_contents (obfd, osection, buf, 0, len); +} + +static void +dump_memory_to_file (char *cmd, char *mode, char *file_format) +{ + struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL); + CORE_ADDR lo; + CORE_ADDR hi; + ULONGEST count; + char *filename; + void *buf; + char *lo_exp; + char *hi_exp; + int len; + + /* Open the file. */ + filename = scan_filename_with_cleanup (&cmd, NULL); + + /* Find the low address. */ + if (cmd == NULL || *cmd == '\0') + error (_("Missing start address.")); + lo_exp = scan_expression_with_cleanup (&cmd, NULL); + + /* Find the second address - rest of line. */ + if (cmd == NULL || *cmd == '\0') + error (_("Missing stop address.")); + hi_exp = cmd; + + lo = parse_and_eval_address (lo_exp); + hi = parse_and_eval_address (hi_exp); + if (hi <= lo) + error (_("Invalid memory address range (start >= end).")); + count = hi - lo; + + /* FIXME: Should use read_memory_partial() and a magic blocking + value. */ + buf = xmalloc (count); + make_cleanup (xfree, buf); + read_memory (lo, buf, count); + + /* Have everything. Open/write the data. */ + if (file_format == NULL || strcmp (file_format, "binary") == 0) + { + dump_binary_file (filename, mode, buf, count); + } + else + { + dump_bfd_file (filename, mode, file_format, lo, buf, count); + } + + do_cleanups (old_cleanups); +} + +static void +dump_memory_command (char *cmd, char *mode) +{ + dump_memory_to_file (cmd, mode, "binary"); +} + +static void +dump_value_to_file (char *cmd, char *mode, char *file_format) +{ + struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL); + struct value *val; + char *filename; + + /* Open the file. */ + filename = scan_filename_with_cleanup (&cmd, NULL); + + /* Find the value. */ + if (cmd == NULL || *cmd == '\0') + error (_("No value to %s."), *mode == 'a' ? "append" : "dump"); + val = parse_and_eval (cmd); + if (val == NULL) + error (_("Invalid expression.")); + + /* Have everything. Open/write the data. */ + if (file_format == NULL || strcmp (file_format, "binary") == 0) + { + dump_binary_file (filename, mode, value_contents (val), + TYPE_LENGTH (value_type (val))); + } + else + { + CORE_ADDR vaddr; + + if (VALUE_LVAL (val)) + { + vaddr = value_address (val); + } + else + { + vaddr = 0; + warning (_("value is not an lval: address assumed to be zero")); + } + + dump_bfd_file (filename, mode, file_format, vaddr, + value_contents (val), + TYPE_LENGTH (value_type (val))); + } + + do_cleanups (old_cleanups); +} + +static void +dump_value_command (char *cmd, char *mode) +{ + dump_value_to_file (cmd, mode, "binary"); +} + +static void +dump_srec_memory (char *args, int from_tty) +{ + dump_memory_to_file (args, FOPEN_WB, "srec"); +} + +static void +dump_srec_value (char *args, int from_tty) +{ + dump_value_to_file (args, FOPEN_WB, "srec"); +} + +static void +dump_ihex_memory (char *args, int from_tty) +{ + dump_memory_to_file (args, FOPEN_WB, "ihex"); +} + +static void +dump_ihex_value (char *args, int from_tty) +{ + dump_value_to_file (args, FOPEN_WB, "ihex"); +} + +static void +dump_tekhex_memory (char *args, int from_tty) +{ + dump_memory_to_file (args, FOPEN_WB, "tekhex"); +} + +static void +dump_tekhex_value (char *args, int from_tty) +{ + dump_value_to_file (args, FOPEN_WB, "tekhex"); +} + +static void +dump_binary_memory (char *args, int from_tty) +{ + dump_memory_to_file (args, FOPEN_WB, "binary"); +} + +static void +dump_binary_value (char *args, int from_tty) +{ + dump_value_to_file (args, FOPEN_WB, "binary"); +} + +static void +append_binary_memory (char *args, int from_tty) +{ + dump_memory_to_file (args, FOPEN_AB, "binary"); +} + +static void +append_binary_value (char *args, int from_tty) +{ + dump_value_to_file (args, FOPEN_AB, "binary"); +} + +struct dump_context +{ + void (*func) (char *cmd, char *mode); + char *mode; +}; + +static void +call_dump_func (struct cmd_list_element *c, char *args, int from_tty) +{ + struct dump_context *d = get_cmd_context (c); + d->func (args, d->mode); +} + +void +add_dump_command (char *name, void (*func) (char *args, char *mode), + char *descr) + +{ + struct cmd_list_element *c; + struct dump_context *d; + + c = add_cmd (name, all_commands, NULL, descr, &dump_cmdlist); + c->completer = filename_completer; + d = XMALLOC (struct dump_context); + d->func = func; + d->mode = FOPEN_WB; + set_cmd_context (c, d); + c->func = call_dump_func; + + c = add_cmd (name, all_commands, NULL, descr, &append_cmdlist); + c->completer = filename_completer; + d = XMALLOC (struct dump_context); + d->func = func; + d->mode = FOPEN_AB; + set_cmd_context (c, d); + c->func = call_dump_func; + + /* Replace "Dump " at start of docstring with "Append " (borrowed + from [deleted] deprecated_add_show_from_set). */ + if ( c->doc[0] == 'W' + && c->doc[1] == 'r' + && c->doc[2] == 'i' + && c->doc[3] == 't' + && c->doc[4] == 'e' + && c->doc[5] == ' ') + c->doc = concat ("Append ", c->doc + 6, (char *)NULL); +} + +/* Opaque data for restore_section_callback. */ +struct callback_data { + CORE_ADDR load_offset; + CORE_ADDR load_start; + CORE_ADDR load_end; +}; + +/* Function: restore_section_callback. + + Callback function for bfd_map_over_sections. + Selectively loads the sections into memory. */ + +static void +restore_section_callback (bfd *ibfd, asection *isec, void *args) +{ + struct callback_data *data = args; + bfd_vma sec_start = bfd_section_vma (ibfd, isec); + bfd_size_type size = bfd_section_size (ibfd, isec); + bfd_vma sec_end = sec_start + size; + bfd_size_type sec_offset = 0; + bfd_size_type sec_load_count = size; + struct cleanup *old_chain; + gdb_byte *buf; + int ret; + + /* Ignore non-loadable sections, eg. from elf files. */ + if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD)) + return; + + /* Does the section overlap with the desired restore range? */ + if (sec_end <= data->load_start + || (data->load_end > 0 && sec_start >= data->load_end)) + { + /* No, no useable data in this section. */ + printf_filtered (_("skipping section %s...\n"), + bfd_section_name (ibfd, isec)); + return; + } + + /* Compare section address range with user-requested + address range (if any). Compute where the actual + transfer should start and end. */ + if (sec_start < data->load_start) + sec_offset = data->load_start - sec_start; + /* Size of a partial transfer: */ + sec_load_count -= sec_offset; + if (data->load_end > 0 && sec_end > data->load_end) + sec_load_count -= sec_end - data->load_end; + + /* Get the data. */ + buf = xmalloc (size); + old_chain = make_cleanup (xfree, buf); + if (!bfd_get_section_contents (ibfd, isec, buf, 0, size)) + error (_("Failed to read bfd file %s: '%s'."), bfd_get_filename (ibfd), + bfd_errmsg (bfd_get_error ())); + + printf_filtered ("Restoring section %s (0x%lx to 0x%lx)", + bfd_section_name (ibfd, isec), + (unsigned long) sec_start, + (unsigned long) sec_end); + + if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0) + printf_filtered (" into memory (%s to %s)\n", + paddress (target_gdbarch, + (unsigned long) sec_start + + sec_offset + data->load_offset), + paddress (target_gdbarch, + (unsigned long) sec_start + sec_offset + + data->load_offset + sec_load_count)); + else + puts_filtered ("\n"); + + /* Write the data. */ + ret = target_write_memory (sec_start + sec_offset + data->load_offset, + buf + sec_offset, sec_load_count); + if (ret != 0) + warning (_("restore: memory write failed (%s)."), safe_strerror (ret)); + do_cleanups (old_chain); + return; +} + +static void +restore_binary_file (char *filename, struct callback_data *data) +{ + FILE *file = fopen_with_cleanup (filename, FOPEN_RB); + int status; + gdb_byte *buf; + long len; + + /* Get the file size for reading. */ + if (fseek (file, 0, SEEK_END) == 0) + len = ftell (file); + else + perror_with_name (filename); + + if (len <= data->load_start) + error (_("Start address is greater than length of binary file %s."), + filename); + + /* Chop off "len" if it exceeds the requested load_end addr. */ + if (data->load_end != 0 && data->load_end < len) + len = data->load_end; + /* Chop off "len" if the requested load_start addr skips some bytes. */ + if (data->load_start > 0) + len -= data->load_start; + + printf_filtered + ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n", + filename, + (unsigned long) (data->load_start + data->load_offset), + (unsigned long) (data->load_start + data->load_offset + len)); + + /* Now set the file pos to the requested load start pos. */ + if (fseek (file, data->load_start, SEEK_SET) != 0) + perror_with_name (filename); + + /* Now allocate a buffer and read the file contents. */ + buf = xmalloc (len); + make_cleanup (xfree, buf); + if (fread (buf, 1, len, file) != len) + perror_with_name (filename); + + /* Now write the buffer into target memory. */ + len = target_write_memory (data->load_start + data->load_offset, buf, len); + if (len != 0) + warning (_("restore: memory write failed (%s)."), safe_strerror (len)); + return; +} + +static void +restore_command (char *args, int from_tty) +{ + char *filename; + struct callback_data data; + bfd *ibfd; + int binary_flag = 0; + + if (!target_has_execution) + noprocess (); + + data.load_offset = 0; + data.load_start = 0; + data.load_end = 0; + + /* Parse the input arguments. First is filename (required). */ + filename = scan_filename_with_cleanup (&args, NULL); + if (args != NULL && *args != '\0') + { + char *binary_string = "binary"; + + /* Look for optional "binary" flag. */ + if (strncmp (args, binary_string, strlen (binary_string)) == 0) + { + binary_flag = 1; + args += strlen (binary_string); + args = skip_spaces (args); + } + /* Parse offset (optional). */ + if (args != NULL && *args != '\0') + data.load_offset = + parse_and_eval_address (scan_expression_with_cleanup (&args, NULL)); + if (args != NULL && *args != '\0') + { + /* Parse start address (optional). */ + data.load_start = + parse_and_eval_long (scan_expression_with_cleanup (&args, NULL)); + if (args != NULL && *args != '\0') + { + /* Parse end address (optional). */ + data.load_end = parse_and_eval_long (args); + if (data.load_end <= data.load_start) + error (_("Start must be less than end.")); + } + } + } + + if (info_verbose) + printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n", + filename, (unsigned long) data.load_offset, + (unsigned long) data.load_start, + (unsigned long) data.load_end); + + if (binary_flag) + { + restore_binary_file (filename, &data); + } + else + { + /* Open the file for loading. */ + ibfd = bfd_openr_with_cleanup (filename, NULL); + + /* Process the sections. */ + bfd_map_over_sections (ibfd, restore_section_callback, &data); + } + return; +} + +static void +srec_dump_command (char *cmd, int from_tty) +{ + printf_unfiltered ("\"dump srec\" must be followed by a subcommand.\n"); + help_list (srec_cmdlist, "dump srec ", -1, gdb_stdout); +} + +static void +ihex_dump_command (char *cmd, int from_tty) +{ + printf_unfiltered ("\"dump ihex\" must be followed by a subcommand.\n"); + help_list (ihex_cmdlist, "dump ihex ", -1, gdb_stdout); +} + +static void +tekhex_dump_command (char *cmd, int from_tty) +{ + printf_unfiltered ("\"dump tekhex\" must be followed by a subcommand.\n"); + help_list (tekhex_cmdlist, "dump tekhex ", -1, gdb_stdout); +} + +static void +binary_dump_command (char *cmd, int from_tty) +{ + printf_unfiltered ("\"dump binary\" must be followed by a subcommand.\n"); + help_list (binary_dump_cmdlist, "dump binary ", -1, gdb_stdout); +} + +static void +binary_append_command (char *cmd, int from_tty) +{ + printf_unfiltered ("\"append binary\" must be followed by a subcommand.\n"); + help_list (binary_append_cmdlist, "append binary ", -1, gdb_stdout); +} + +extern initialize_file_ftype _initialize_cli_dump; /* -Wmissing-prototypes */ + +void +_initialize_cli_dump (void) +{ + struct cmd_list_element *c; + add_prefix_cmd ("dump", class_vars, dump_command, _("\ +Dump target code/data to a local file."), + &dump_cmdlist, "dump ", + 0/*allow-unknown*/, + &cmdlist); + add_prefix_cmd ("append", class_vars, append_command, _("\ +Append target code/data to a local file."), + &append_cmdlist, "append ", + 0/*allow-unknown*/, + &cmdlist); + + add_dump_command ("memory", dump_memory_command, "\ +Write contents of memory to a raw binary file.\n\ +Arguments are FILE START STOP. Writes the contents of memory within the\n\ +range [START .. STOP) to the specifed FILE in raw target ordered bytes."); + + add_dump_command ("value", dump_value_command, "\ +Write the value of an expression to a raw binary file.\n\ +Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\ +the specified FILE in raw target ordered bytes."); + + add_prefix_cmd ("srec", all_commands, srec_dump_command, _("\ +Write target code/data to an srec file."), + &srec_cmdlist, "dump srec ", + 0 /*allow-unknown*/, + &dump_cmdlist); + + add_prefix_cmd ("ihex", all_commands, ihex_dump_command, _("\ +Write target code/data to an intel hex file."), + &ihex_cmdlist, "dump ihex ", + 0 /*allow-unknown*/, + &dump_cmdlist); + + add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command, _("\ +Write target code/data to a tekhex file."), + &tekhex_cmdlist, "dump tekhex ", + 0 /*allow-unknown*/, + &dump_cmdlist); + + add_prefix_cmd ("binary", all_commands, binary_dump_command, _("\ +Write target code/data to a raw binary file."), + &binary_dump_cmdlist, "dump binary ", + 0 /*allow-unknown*/, + &dump_cmdlist); + + add_prefix_cmd ("binary", all_commands, binary_append_command, _("\ +Append target code/data to a raw binary file."), + &binary_append_cmdlist, "append binary ", + 0 /*allow-unknown*/, + &append_cmdlist); + + add_cmd ("memory", all_commands, dump_srec_memory, _("\ +Write contents of memory to an srec file.\n\ +Arguments are FILE START STOP. Writes the contents of memory\n\ +within the range [START .. STOP) to the specifed FILE in srec format."), + &srec_cmdlist); + + add_cmd ("value", all_commands, dump_srec_value, _("\ +Write the value of an expression to an srec file.\n\ +Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ +to the specified FILE in srec format."), + &srec_cmdlist); + + add_cmd ("memory", all_commands, dump_ihex_memory, _("\ +Write contents of memory to an ihex file.\n\ +Arguments are FILE START STOP. Writes the contents of memory within\n\ +the range [START .. STOP) to the specifed FILE in intel hex format."), + &ihex_cmdlist); + + add_cmd ("value", all_commands, dump_ihex_value, _("\ +Write the value of an expression to an ihex file.\n\ +Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ +to the specified FILE in intel hex format."), + &ihex_cmdlist); + + add_cmd ("memory", all_commands, dump_tekhex_memory, _("\ +Write contents of memory to a tekhex file.\n\ +Arguments are FILE START STOP. Writes the contents of memory\n\ +within the range [START .. STOP) to the specifed FILE in tekhex format."), + &tekhex_cmdlist); + + add_cmd ("value", all_commands, dump_tekhex_value, _("\ +Write the value of an expression to a tekhex file.\n\ +Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ +to the specified FILE in tekhex format."), + &tekhex_cmdlist); + + add_cmd ("memory", all_commands, dump_binary_memory, _("\ +Write contents of memory to a raw binary file.\n\ +Arguments are FILE START STOP. Writes the contents of memory\n\ +within the range [START .. STOP) to the specifed FILE in binary format."), + &binary_dump_cmdlist); + + add_cmd ("value", all_commands, dump_binary_value, _("\ +Write the value of an expression to a raw binary file.\n\ +Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ +to the specified FILE in raw target ordered bytes."), + &binary_dump_cmdlist); + + add_cmd ("memory", all_commands, append_binary_memory, _("\ +Append contents of memory to a raw binary file.\n\ +Arguments are FILE START STOP. Writes the contents of memory within the\n\ +range [START .. STOP) to the specifed FILE in raw target ordered bytes."), + &binary_append_cmdlist); + + add_cmd ("value", all_commands, append_binary_value, _("\ +Append the value of an expression to a raw binary file.\n\ +Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\ +to the specified FILE in raw target ordered bytes."), + &binary_append_cmdlist); + + c = add_com ("restore", class_vars, restore_command, _("\ +Restore the contents of FILE to target memory.\n\ +Arguments are FILE OFFSET START END where all except FILE are optional.\n\ +OFFSET will be added to the base address of the file (default zero).\n\ +If START and END are given, only the file contents within that range\n\ +(file relative) will be restored to target memory.")); + c->completer = filename_completer; + /* FIXME: completers for other commands. */ +}
cli-dump.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-cmds.c =================================================================== --- cli-cmds.c (nonexistent) +++ cli-cmds.c (revision 842) @@ -0,0 +1,1588 @@ +/* GDB CLI commands. + + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#include "defs.h" +#include "exceptions.h" +#include "arch-utils.h" +#include "readline/readline.h" +#include "readline/tilde.h" +#include "completer.h" +#include "target.h" /* For baud_rate, remote_debug and remote_timeout */ +#include "gdb_wait.h" /* For shell escape implementation */ +#include "gdb_regex.h" /* Used by apropos_command */ +#include "gdb_string.h" +#include "gdb_vfork.h" +#include "linespec.h" +#include "expression.h" +#include "frame.h" +#include "value.h" +#include "language.h" +#include "filenames.h" /* for DOSish file names */ +#include "objfiles.h" +#include "source.h" +#include "disasm.h" +extern void disconnect_or_stop_tracing (int from_tty); + +#include "ui-out.h" + +#include "top.h" +#include "cli/cli-decode.h" +#include "cli/cli-script.h" +#include "cli/cli-setshow.h" +#include "cli/cli-cmds.h" + +#include "python/python.h" + +#ifdef TUI +#include "tui/tui.h" /* For tui_active et.al. */ +#endif + +#include + +/* Prototypes for local command functions */ + +static void complete_command (char *, int); + +static void echo_command (char *, int); + +static void pwd_command (char *, int); + +static void show_version (char *, int); + +static void help_command (char *, int); + +static void show_command (char *, int); + +static void info_command (char *, int); + +static void show_debug (char *, int); + +static void set_debug (char *, int); + +static void show_user (char *, int); + +static void make_command (char *, int); + +static void shell_escape (char *, int); + +static void edit_command (char *, int); + +static void list_command (char *, int); + +void apropos_command (char *, int); + +/* Prototypes for local utility functions */ + +static void ambiguous_line_spec (struct symtabs_and_lines *); + +/* Limit the call depth of user-defined commands */ +int max_user_call_depth; + +/* Define all cmd_list_elements. */ + +/* Chain containing all defined commands. */ + +struct cmd_list_element *cmdlist; + +/* Chain containing all defined info subcommands. */ + +struct cmd_list_element *infolist; + +/* Chain containing all defined enable subcommands. */ + +struct cmd_list_element *enablelist; + +/* Chain containing all defined disable subcommands. */ + +struct cmd_list_element *disablelist; + +/* Chain containing all defined toggle subcommands. */ + +struct cmd_list_element *togglelist; + +/* Chain containing all defined stop subcommands. */ + +struct cmd_list_element *stoplist; + +/* Chain containing all defined delete subcommands. */ + +struct cmd_list_element *deletelist; + +/* Chain containing all defined detach subcommands. */ + +struct cmd_list_element *detachlist; + +/* Chain containing all defined kill subcommands. */ + +struct cmd_list_element *killlist; + +/* Chain containing all defined "enable breakpoint" subcommands. */ + +struct cmd_list_element *enablebreaklist; + +/* Chain containing all defined set subcommands */ + +struct cmd_list_element *setlist; + +/* Chain containing all defined unset subcommands */ + +struct cmd_list_element *unsetlist; + +/* Chain containing all defined show subcommands. */ + +struct cmd_list_element *showlist; + +/* Chain containing all defined \"set history\". */ + +struct cmd_list_element *sethistlist; + +/* Chain containing all defined \"show history\". */ + +struct cmd_list_element *showhistlist; + +/* Chain containing all defined \"unset history\". */ + +struct cmd_list_element *unsethistlist; + +/* Chain containing all defined maintenance subcommands. */ + +struct cmd_list_element *maintenancelist; + +/* Chain containing all defined "maintenance info" subcommands. */ + +struct cmd_list_element *maintenanceinfolist; + +/* Chain containing all defined "maintenance print" subcommands. */ + +struct cmd_list_element *maintenanceprintlist; + +struct cmd_list_element *setprintlist; + +struct cmd_list_element *showprintlist; + +struct cmd_list_element *setdebuglist; + +struct cmd_list_element *showdebuglist; + +struct cmd_list_element *setchecklist; + +struct cmd_list_element *showchecklist; + +/* Command tracing state. */ + +int source_verbose = 0; +int trace_commands = 0; + +/* 'script-extension' option support. */ + +static const char script_ext_off[] = "off"; +static const char script_ext_soft[] = "soft"; +static const char script_ext_strict[] = "strict"; + +static const char *script_ext_enums[] = { + script_ext_off, + script_ext_soft, + script_ext_strict, + NULL +}; + +static const char *script_ext_mode = script_ext_soft; + +/* Utility used everywhere when at least one argument is needed and + none is supplied. */ + +void +error_no_arg (char *why) +{ + error (_("Argument required (%s)."), why); +} + +/* The "info" command is defined as a prefix, with allow_unknown = 0. + Therefore, its own definition is called only for "info" with no args. */ + +static void +info_command (char *arg, int from_tty) +{ + printf_unfiltered (_("\"info\" must be followed by the name of an info command.\n")); + help_list (infolist, "info ", -1, gdb_stdout); +} + +/* The "show" command with no arguments shows all the settings. */ + +static void +show_command (char *arg, int from_tty) +{ + cmd_show_list (showlist, from_tty, ""); +} + +/* Provide documentation on command or list given by COMMAND. FROM_TTY + is ignored. */ + +static void +help_command (char *command, int from_tty) +{ + help_cmd (command, gdb_stdout); +} + +/* String compare function for qsort. */ +static int +compare_strings (const void *arg1, const void *arg2) +{ + const char **s1 = (const char **) arg1; + const char **s2 = (const char **) arg2; + return strcmp (*s1, *s2); +} + +/* The "complete" command is used by Emacs to implement completion. */ + +static void +complete_command (char *arg, int from_tty) +{ + int i; + int argpoint; + char **completions, *point, *arg_prefix; + + dont_repeat (); + + if (arg == NULL) + arg = ""; + argpoint = strlen (arg); + + /* complete_line assumes that its first argument is somewhere within, + and except for filenames at the beginning of, the word to be completed. + The following crude imitation of readline's word-breaking tries to + accomodate this. */ + point = arg + argpoint; + while (point > arg) + { + if (strchr (rl_completer_word_break_characters, point[-1]) != 0) + break; + point--; + } + + arg_prefix = alloca (point - arg + 1); + memcpy (arg_prefix, arg, point - arg); + arg_prefix[point - arg] = 0; + + completions = complete_line (point, arg, argpoint); + + if (completions) + { + int item, size; + + for (size = 0; completions[size]; ++size) + ; + qsort (completions, size, sizeof (char *), compare_strings); + + /* We do extra processing here since we only want to print each + unique item once. */ + item = 0; + while (item < size) + { + int next_item; + printf_unfiltered ("%s%s\n", arg_prefix, completions[item]); + next_item = item + 1; + while (next_item < size + && ! strcmp (completions[item], completions[next_item])) + { + xfree (completions[next_item]); + ++next_item; + } + + xfree (completions[item]); + item = next_item; + } + + xfree (completions); + } +} + +int +is_complete_command (struct cmd_list_element *c) +{ + return cmd_cfunc_eq (c, complete_command); +} + +static void +show_version (char *args, int from_tty) +{ + immediate_quit++; + print_gdb_version (gdb_stdout); + printf_filtered ("\n"); + immediate_quit--; +} + +/* Handle the quit command. */ + +void +quit_command (char *args, int from_tty) +{ + if (!quit_confirm ()) + error (_("Not confirmed.")); + + disconnect_or_stop_tracing (from_tty); + + quit_force (args, from_tty); +} + +static void +pwd_command (char *args, int from_tty) +{ + if (args) + error (_("The \"pwd\" command does not take an argument: %s"), args); + if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf))) + error (_("Error finding name of working directory: %s"), + safe_strerror (errno)); + + if (strcmp (gdb_dirbuf, current_directory) != 0) + printf_unfiltered (_("Working directory %s\n (canonically %s).\n"), + current_directory, gdb_dirbuf); + else + printf_unfiltered (_("Working directory %s.\n"), current_directory); +} + +void +cd_command (char *dir, int from_tty) +{ + int len; + /* Found something other than leading repetitions of "/..". */ + int found_real_path; + char *p; + + /* If the new directory is absolute, repeat is a no-op; if relative, + repeat might be useful but is more likely to be a mistake. */ + dont_repeat (); + + if (dir == 0) + error_no_arg (_("new working directory")); + + dir = tilde_expand (dir); + make_cleanup (xfree, dir); + + if (chdir (dir) < 0) + perror_with_name (dir); + +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + /* There's too much mess with DOSish names like "d:", "d:.", + "d:./foo" etc. Instead of having lots of special #ifdef'ed code, + simply get the canonicalized name of the current directory. */ + dir = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); +#endif + + len = strlen (dir); + if (IS_DIR_SEPARATOR (dir[len - 1])) + { + /* Remove the trailing slash unless this is a root directory + (including a drive letter on non-Unix systems). */ + if (!(len == 1) /* "/" */ +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + && !(len == 3 && dir[1] == ':') /* "d:/" */ +#endif + ) + len--; + } + + dir = savestring (dir, len); + if (IS_ABSOLUTE_PATH (dir)) + current_directory = dir; + else + { + if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])) + current_directory = concat (current_directory, dir, (char *)NULL); + else + current_directory = concat (current_directory, SLASH_STRING, + dir, (char *)NULL); + xfree (dir); + } + + /* Now simplify any occurrences of `.' and `..' in the pathname. */ + + found_real_path = 0; + for (p = current_directory; *p;) + { + if (IS_DIR_SEPARATOR (p[0]) && p[1] == '.' + && (p[2] == 0 || IS_DIR_SEPARATOR (p[2]))) + strcpy (p, p + 2); + else if (IS_DIR_SEPARATOR (p[0]) && p[1] == '.' && p[2] == '.' + && (p[3] == 0 || IS_DIR_SEPARATOR (p[3]))) + { + if (found_real_path) + { + /* Search backwards for the directory just before the "/.." + and obliterate it and the "/..". */ + char *q = p; + while (q != current_directory && !IS_DIR_SEPARATOR (q[-1])) + --q; + + if (q == current_directory) + /* current_directory is + a relative pathname ("can't happen"--leave it alone). */ + ++p; + else + { + strcpy (q - 1, p + 3); + p = q - 1; + } + } + else + /* We are dealing with leading repetitions of "/..", for example + "/../..", which is the Mach super-root. */ + p += 3; + } + else + { + found_real_path = 1; + ++p; + } + } + + forget_cached_source_info (); + + if (from_tty) + pwd_command ((char *) 0, 1); +} + +/* Show the current value of the 'script-extension' option. */ + +static void +show_script_ext_mode (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Script filename extension recognition is \"%s\".\n"), + value); +} + +static int +find_and_open_script (int from_tty, char **filep, FILE **streamp, + struct cleanup **cleanupp) +{ + char *file = *filep; + char *full_pathname = NULL; + int fd; + struct cleanup *old_cleanups; + + file = tilde_expand (file); + old_cleanups = make_cleanup (xfree, file); + + /* Search for and open 'file' on the search path used for source + files. Put the full location in 'full_pathname'. */ + fd = openp (source_path, OPF_TRY_CWD_FIRST, + file, O_RDONLY, &full_pathname); + make_cleanup (xfree, full_pathname); + + /* Use the full path name, if it is found. */ + if (full_pathname != NULL && fd != -1) + { + file = full_pathname; + } + + if (fd == -1) + { + if (from_tty) + perror_with_name (file); + else + { + do_cleanups (old_cleanups); + return 0; + } + } + + *streamp = fdopen (fd, FOPEN_RT); + *filep = file; + *cleanupp = old_cleanups; + + return 1; +} + +void +source_script (char *file, int from_tty) +{ + FILE *stream; + struct cleanup *old_cleanups; + + if (file == NULL || *file == 0) + { + error (_("source command requires file name of file to source.")); + } + + if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups)) + return; + + if (script_ext_mode != script_ext_off + && strlen (file) > 3 && !strcmp (&file[strlen (file) - 3], ".py")) + { + volatile struct gdb_exception e; + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + source_python_script (stream, file); + } + if (e.reason < 0) + { + /* Should we fallback to ye olde GDB script mode? */ + if (script_ext_mode == script_ext_soft + && e.reason == RETURN_ERROR && e.error == UNSUPPORTED_ERROR) + { + if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups)) + return; + + script_from_file (stream, file); + } + else + /* Nope, just punt. */ + throw_exception (e); + } + } + else + script_from_file (stream, file); + + do_cleanups (old_cleanups); +} + +/* Return the source_verbose global variable to its previous state + on exit from the source command, by whatever means. */ +static void +source_verbose_cleanup (void *old_value) +{ + source_verbose = *(int *)old_value; + xfree (old_value); +} + +static void +source_command (char *args, int from_tty) +{ + struct cleanup *old_cleanups; + char *file = args; + int *old_source_verbose = xmalloc (sizeof(int)); + + *old_source_verbose = source_verbose; + old_cleanups = make_cleanup (source_verbose_cleanup, old_source_verbose); + + /* -v causes the source command to run in verbose mode. + We still have to be able to handle filenames with spaces in a + backward compatible way, so buildargv is not appropriate. */ + + if (args) + { + /* Make sure leading white space does not break the comparisons. */ + while (isspace(args[0])) + args++; + + /* Is -v the first thing in the string? */ + if (args[0] == '-' && args[1] == 'v' && isspace (args[2])) + { + source_verbose = 1; + + /* Trim -v and whitespace from the filename. */ + file = &args[3]; + while (isspace (file[0])) + file++; + } + } + + source_script (file, from_tty); +} + + +static void +echo_command (char *text, int from_tty) +{ + char *p = text; + int c; + + if (text) + while ((c = *p++) != '\0') + { + if (c == '\\') + { + /* \ at end of argument is used after spaces + so they won't be lost. */ + if (*p == 0) + return; + + c = parse_escape (&p); + if (c >= 0) + printf_filtered ("%c", c); + } + else + printf_filtered ("%c", c); + } + + /* Force this output to appear now. */ + wrap_here (""); + gdb_flush (gdb_stdout); +} + +static void +shell_escape (char *arg, int from_tty) +{ +#if defined(CANT_FORK) || \ + (!defined(HAVE_WORKING_VFORK) && !defined(HAVE_WORKING_FORK)) + /* If ARG is NULL, they want an inferior shell, but `system' just + reports if the shell is available when passed a NULL arg. */ + int rc = system (arg ? arg : ""); + + if (!arg) + arg = "inferior shell"; + + if (rc == -1) + { + fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", arg, + safe_strerror (errno)); + gdb_flush (gdb_stderr); + } + else if (rc) + { + fprintf_unfiltered (gdb_stderr, "%s exited with status %d\n", arg, rc); + gdb_flush (gdb_stderr); + } +#ifdef GLOBAL_CURDIR + /* Make sure to return to the directory GDB thinks it is, in case the + shell command we just ran changed it. */ + chdir (current_directory); +#endif +#else /* Can fork. */ + int rc, status, pid; + + if ((pid = vfork ()) == 0) + { + char *p, *user_shell; + + if ((user_shell = (char *) getenv ("SHELL")) == NULL) + user_shell = "/bin/sh"; + + /* Get the name of the shell for arg0 */ + if ((p = strrchr (user_shell, '/')) == NULL) + p = user_shell; + else + p++; /* Get past '/' */ + + if (!arg) + execl (user_shell, p, (char *) 0); + else + execl (user_shell, p, "-c", arg, (char *) 0); + + fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell, + safe_strerror (errno)); + gdb_flush (gdb_stderr); + _exit (0177); + } + + if (pid != -1) + while ((rc = wait (&status)) != pid && rc != -1) + ; + else + error (_("Fork failed")); +#endif /* Can fork. */ +} + +static void +edit_command (char *arg, int from_tty) +{ + struct symtabs_and_lines sals; + struct symtab_and_line sal; + struct symbol *sym; + char *arg1; + char *editor; + char *p, *fn; + + /* Pull in the current default source line if necessary. */ + if (arg == 0) + { + set_default_source_symtab_and_line (); + sal = get_current_source_symtab_and_line (); + } + + /* bare "edit" edits file with present line. */ + + if (arg == 0) + { + if (sal.symtab == 0) + error (_("No default source file yet.")); + sal.line += get_lines_to_list () / 2; + } + else + { + + /* Now should only be one argument -- decode it in SAL. */ + + arg1 = arg; + sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0); + + if (! sals.nelts) + { + /* C++ */ + return; + } + if (sals.nelts > 1) + { + ambiguous_line_spec (&sals); + xfree (sals.sals); + return; + } + + sal = sals.sals[0]; + xfree (sals.sals); + + if (*arg1) + error (_("Junk at end of line specification.")); + + /* If line was specified by address, + first print exactly which line, and which file. + In this case, sal.symtab == 0 means address is outside + of all known source files, not that user failed to give a filename. */ + if (*arg == '*') + { + struct gdbarch *gdbarch; + if (sal.symtab == 0) + /* FIXME-32x64--assumes sal.pc fits in long. */ + error (_("No source file for address %s."), + hex_string ((unsigned long) sal.pc)); + + gdbarch = get_objfile_arch (sal.symtab->objfile); + sym = find_pc_function (sal.pc); + if (sym) + printf_filtered ("%s is in %s (%s:%d).\n", + paddress (gdbarch, sal.pc), + SYMBOL_PRINT_NAME (sym), + sal.symtab->filename, sal.line); + else + printf_filtered ("%s is at %s:%d.\n", + paddress (gdbarch, sal.pc), + sal.symtab->filename, sal.line); + } + + /* If what was given does not imply a symtab, it must be an undebuggable + symbol which means no source code. */ + + if (sal.symtab == 0) + error (_("No line number known for %s."), arg); + } + + if ((editor = (char *) getenv ("EDITOR")) == NULL) + editor = "/bin/ex"; + + /* If we don't already know the full absolute file name of the + source file, find it now. */ + if (!sal.symtab->fullname) + { + fn = symtab_to_fullname (sal.symtab); + if (!fn) + fn = "unknown"; + } + else + fn = sal.symtab->fullname; + + /* Quote the file name, in case it has whitespace or other special + characters. */ + p = xstrprintf ("%s +%d \"%s\"", editor, sal.line, fn); + shell_escape (p, from_tty); + xfree (p); +} + +static void +list_command (char *arg, int from_tty) +{ + struct symtabs_and_lines sals, sals_end; + struct symtab_and_line sal = { 0 }; + struct symtab_and_line sal_end = { 0 }; + struct symtab_and_line cursal = { 0 }; + struct symbol *sym; + char *arg1; + int no_end = 1; + int dummy_end = 0; + int dummy_beg = 0; + int linenum_beg = 0; + char *p; + + /* Pull in the current default source line if necessary */ + if (arg == 0 || arg[0] == '+' || arg[0] == '-') + { + set_default_source_symtab_and_line (); + cursal = get_current_source_symtab_and_line (); + } + + /* "l" or "l +" lists next ten lines. */ + + if (arg == 0 || strcmp (arg, "+") == 0) + { + print_source_lines (cursal.symtab, cursal.line, + cursal.line + get_lines_to_list (), 0); + return; + } + + /* "l -" lists previous ten lines, the ones before the ten just listed. */ + if (strcmp (arg, "-") == 0) + { + print_source_lines (cursal.symtab, + max (get_first_line_listed () - get_lines_to_list (), 1), + get_first_line_listed (), 0); + return; + } + + /* Now if there is only one argument, decode it in SAL + and set NO_END. + If there are two arguments, decode them in SAL and SAL_END + and clear NO_END; however, if one of the arguments is blank, + set DUMMY_BEG or DUMMY_END to record that fact. */ + + if (!have_full_symbols () && !have_partial_symbols ()) + error (_("No symbol table is loaded. Use the \"file\" command.")); + + arg1 = arg; + if (*arg1 == ',') + dummy_beg = 1; + else + { + sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0); + + if (!sals.nelts) + return; /* C++ */ + if (sals.nelts > 1) + { + ambiguous_line_spec (&sals); + xfree (sals.sals); + return; + } + + sal = sals.sals[0]; + xfree (sals.sals); + } + + /* Record whether the BEG arg is all digits. */ + + for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++); + linenum_beg = (p == arg1); + + while (*arg1 == ' ' || *arg1 == '\t') + arg1++; + if (*arg1 == ',') + { + no_end = 0; + arg1++; + while (*arg1 == ' ' || *arg1 == '\t') + arg1++; + if (*arg1 == 0) + dummy_end = 1; + else + { + if (dummy_beg) + sals_end = decode_line_1 (&arg1, 0, 0, 0, 0, 0); + else + sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0, 0); + if (sals_end.nelts == 0) + return; + if (sals_end.nelts > 1) + { + ambiguous_line_spec (&sals_end); + xfree (sals_end.sals); + return; + } + sal_end = sals_end.sals[0]; + xfree (sals_end.sals); + } + } + + if (*arg1) + error (_("Junk at end of line specification.")); + + if (!no_end && !dummy_beg && !dummy_end + && sal.symtab != sal_end.symtab) + error (_("Specified start and end are in different files.")); + if (dummy_beg && dummy_end) + error (_("Two empty args do not say what lines to list.")); + + /* if line was specified by address, + first print exactly which line, and which file. + In this case, sal.symtab == 0 means address is outside + of all known source files, not that user failed to give a filename. */ + if (*arg == '*') + { + struct gdbarch *gdbarch; + if (sal.symtab == 0) + /* FIXME-32x64--assumes sal.pc fits in long. */ + error (_("No source file for address %s."), + hex_string ((unsigned long) sal.pc)); + + gdbarch = get_objfile_arch (sal.symtab->objfile); + sym = find_pc_function (sal.pc); + if (sym) + printf_filtered ("%s is in %s (%s:%d).\n", + paddress (gdbarch, sal.pc), + SYMBOL_PRINT_NAME (sym), + sal.symtab->filename, sal.line); + else + printf_filtered ("%s is at %s:%d.\n", + paddress (gdbarch, sal.pc), + sal.symtab->filename, sal.line); + } + + /* If line was not specified by just a line number, + and it does not imply a symtab, it must be an undebuggable symbol + which means no source code. */ + + if (!linenum_beg && sal.symtab == 0) + error (_("No line number known for %s."), arg); + + /* If this command is repeated with RET, + turn it into the no-arg variant. */ + + if (from_tty) + *arg = 0; + + if (dummy_beg && sal_end.symtab == 0) + error (_("No default source file yet. Do \"help list\".")); + if (dummy_beg) + print_source_lines (sal_end.symtab, + max (sal_end.line - (get_lines_to_list () - 1), 1), + sal_end.line + 1, 0); + else if (sal.symtab == 0) + error (_("No default source file yet. Do \"help list\".")); + else if (no_end) + { + int first_line = sal.line - get_lines_to_list () / 2; + + if (first_line < 1) first_line = 1; + + print_source_lines (sal.symtab, + first_line, + first_line + get_lines_to_list (), + 0); + } + else + print_source_lines (sal.symtab, sal.line, + (dummy_end + ? sal.line + get_lines_to_list () + : sal_end.line + 1), + 0); +} + +/* Subroutine of disassemble_command to simplify it. + Perform the disassembly. + NAME is the name of the function if known, or NULL. + [LOW,HIGH) are the range of addresses to disassemble. + MIXED is non-zero to print source with the assembler. */ + +static void +print_disassembly (struct gdbarch *gdbarch, const char *name, + CORE_ADDR low, CORE_ADDR high, int flags) +{ +#if defined(TUI) + if (!tui_is_window_visible (DISASSEM_WIN)) +#endif + { + printf_filtered ("Dump of assembler code "); + if (name != NULL) + printf_filtered ("for function %s:\n", name); + else + printf_filtered ("from %s to %s:\n", + paddress (gdbarch, low), paddress (gdbarch, high)); + + /* Dump the specified range. */ + gdb_disassembly (gdbarch, uiout, 0, flags, -1, low, high); + + printf_filtered ("End of assembler dump.\n"); + gdb_flush (gdb_stdout); + } +#if defined(TUI) + else + { + tui_show_assembly (gdbarch, low); + } +#endif +} + +/* Subroutine of disassemble_command to simplify it. + Print a disassembly of the current function according to FLAGS. */ + +static void +disassemble_current_function (int flags) +{ + struct frame_info *frame; + struct gdbarch *gdbarch; + CORE_ADDR low, high, pc; + char *name; + + frame = get_selected_frame (_("No frame selected.")); + gdbarch = get_frame_arch (frame); + pc = get_frame_pc (frame); + if (find_pc_partial_function (pc, &name, &low, &high) == 0) + error (_("No function contains program counter for selected frame.")); +#if defined(TUI) + /* NOTE: cagney/2003-02-13 The `tui_active' was previously + `tui_version'. */ + if (tui_active) + /* FIXME: cagney/2004-02-07: This should be an observer. */ + low = tui_get_low_disassembly_address (gdbarch, low, pc); +#endif + low += gdbarch_deprecated_function_start_offset (gdbarch); + + print_disassembly (gdbarch, name, low, high, flags); +} + +/* Dump a specified section of assembly code. + + Usage: + disassemble [/mr] + - dump the assembly code for the function of the current pc + disassemble [/mr] addr + - dump the assembly code for the function at ADDR + disassemble [/mr] low high + - dump the assembly code in the range [LOW,HIGH) + + A /m modifier will include source code with the assembly. + A /r modifier will include raw instructions in hex with the assembly. */ + +static void +disassemble_command (char *arg, int from_tty) +{ + struct gdbarch *gdbarch = get_current_arch (); + CORE_ADDR low, high; + char *name; + CORE_ADDR pc, pc_masked; + int flags; + + name = NULL; + flags = 0; + + if (arg && *arg == '/') + { + ++arg; + + if (*arg == '\0') + error (_("Missing modifier.")); + + while (*arg && ! isspace (*arg)) + { + switch (*arg++) + { + case 'm': + flags |= DISASSEMBLY_SOURCE; + break; + case 'r': + flags |= DISASSEMBLY_RAW_INSN; + break; + default: + error (_("Invalid disassembly modifier.")); + } + } + + while (isspace (*arg)) + ++arg; + } + + if (! arg || ! *arg) + { + flags |= DISASSEMBLY_OMIT_FNAME; + disassemble_current_function (flags); + return; + } + + pc = value_as_address (parse_to_comma_and_eval (&arg)); + if (arg[0] == ',') + ++arg; + if (arg[0] == '\0') + { + /* One argument. */ + if (find_pc_partial_function (pc, &name, &low, &high) == 0) + error (_("No function contains specified address.")); +#if defined(TUI) + /* NOTE: cagney/2003-02-13 The `tui_active' was previously + `tui_version'. */ + if (tui_active) + /* FIXME: cagney/2004-02-07: This should be an observer. */ + low = tui_get_low_disassembly_address (gdbarch, low, pc); +#endif + low += gdbarch_deprecated_function_start_offset (gdbarch); + flags |= DISASSEMBLY_OMIT_FNAME; + } + else + { + /* Two arguments. */ + low = pc; + high = parse_and_eval_address (arg); + } + + print_disassembly (gdbarch, name, low, high, flags); +} + +static void +make_command (char *arg, int from_tty) +{ + char *p; + + if (arg == 0) + p = "make"; + else + { + p = xmalloc (sizeof ("make ") + strlen (arg)); + strcpy (p, "make "); + strcpy (p + sizeof ("make ") - 1, arg); + } + + shell_escape (p, from_tty); +} + +static void +show_user (char *args, int from_tty) +{ + struct cmd_list_element *c; + extern struct cmd_list_element *cmdlist; + + if (args) + { + char *comname = args; + c = lookup_cmd (&comname, cmdlist, "", 0, 1); + if (c->class != class_user) + error (_("Not a user command.")); + show_user_1 (c, "", args, gdb_stdout); + } + else + { + for (c = cmdlist; c; c = c->next) + { + if (c->class == class_user || c->prefixlist != NULL) + show_user_1 (c, "", c->name, gdb_stdout); + } + } +} + +/* Search through names of commands and documentations for a certain + regular expression. +*/ +void +apropos_command (char *searchstr, int from_tty) +{ + extern struct cmd_list_element *cmdlist; /*This is the main command list*/ + regex_t pattern; + char *pattern_fastmap; + char errorbuffer[512]; + pattern_fastmap = xcalloc (256, sizeof (char)); + if (searchstr == NULL) + error (_("REGEXP string is empty")); + + if (regcomp(&pattern,searchstr,REG_ICASE) == 0) + { + pattern.fastmap=pattern_fastmap; + re_compile_fastmap(&pattern); + apropos_cmd (gdb_stdout,cmdlist,&pattern,""); + } + else + { + regerror(regcomp(&pattern,searchstr,REG_ICASE),NULL,errorbuffer,512); + error (_("Error in regular expression:%s"),errorbuffer); + } + xfree (pattern_fastmap); +} + +/* Print a list of files and line numbers which a user may choose from + in order to list a function which was specified ambiguously (as with + `list classname::overloadedfuncname', for example). The vector in + SALS provides the filenames and line numbers. */ + +static void +ambiguous_line_spec (struct symtabs_and_lines *sals) +{ + int i; + + for (i = 0; i < sals->nelts; ++i) + printf_filtered (_("file: \"%s\", line number: %d\n"), + sals->sals[i].symtab->filename, sals->sals[i].line); +} + +static void +set_debug (char *arg, int from_tty) +{ + printf_unfiltered (_("\"set debug\" must be followed by the name of a debug subcommand.\n")); + help_list (setdebuglist, "set debug ", -1, gdb_stdout); +} + +static void +show_debug (char *args, int from_tty) +{ + cmd_show_list (showdebuglist, from_tty, ""); +} + +void +init_cmd_lists (void) +{ + max_user_call_depth = 1024; + + cmdlist = NULL; + infolist = NULL; + enablelist = NULL; + disablelist = NULL; + togglelist = NULL; + stoplist = NULL; + deletelist = NULL; + detachlist = NULL; + enablebreaklist = NULL; + setlist = NULL; + unsetlist = NULL; + showlist = NULL; + sethistlist = NULL; + showhistlist = NULL; + unsethistlist = NULL; + maintenancelist = NULL; + maintenanceinfolist = NULL; + maintenanceprintlist = NULL; + setprintlist = NULL; + showprintlist = NULL; + setchecklist = NULL; + showchecklist = NULL; +} + +static void +show_info_verbose (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + if (info_verbose) + fprintf_filtered (file, _("\ +Verbose printing of informational messages is %s.\n"), value); + else + fprintf_filtered (file, _("Verbosity is %s.\n"), value); +} + +static void +show_history_expansion_p (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("History expansion on command input is %s.\n"), + value); +} + +static void +show_baud_rate (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Baud rate for remote serial I/O is %s.\n"), + value); +} + +static void +show_remote_debug (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Debugging of remote protocol is %s.\n"), + value); +} + +static void +show_remote_timeout (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Timeout limit to wait for target to respond is %s.\n"), + value); +} + +static void +show_max_user_call_depth (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +The max call depth for user-defined commands is %s.\n"), + value); +} + + +void +init_cli_cmds (void) +{ + struct cmd_list_element *c; + char *source_help_text; + + /* Define the classes of commands. + They will appear in the help list in the reverse of this order. */ + + add_cmd ("internals", class_maintenance, NULL, _("\ +Maintenance commands.\n\ +Some gdb commands are provided just for use by gdb maintainers.\n\ +These commands are subject to frequent change, and may not be as\n\ +well documented as user commands."), + &cmdlist); + add_cmd ("obscure", class_obscure, NULL, _("Obscure features."), &cmdlist); + add_cmd ("aliases", class_alias, NULL, _("Aliases of other commands."), &cmdlist); + add_cmd ("user-defined", class_user, NULL, _("\ +User-defined commands.\n\ +The commands in this class are those defined by the user.\n\ +Use the \"define\" command to define a command."), &cmdlist); + add_cmd ("support", class_support, NULL, _("Support facilities."), &cmdlist); + if (!dbx_commands) + add_cmd ("status", class_info, NULL, _("Status inquiries."), &cmdlist); + add_cmd ("files", class_files, NULL, _("Specifying and examining files."), + &cmdlist); + add_cmd ("breakpoints", class_breakpoint, NULL, + _("Making program stop at certain points."), &cmdlist); + add_cmd ("data", class_vars, NULL, _("Examining data."), &cmdlist); + add_cmd ("stack", class_stack, NULL, _("\ +Examining the stack.\n\ +The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\ +counting from zero for the innermost (currently executing) frame.\n\n\ +At any time gdb identifies one frame as the \"selected\" frame.\n\ +Variable lookups are done with respect to the selected frame.\n\ +When the program being debugged stops, gdb selects the innermost frame.\n\ +The commands below can be used to select other frames by number or address."), + &cmdlist); + add_cmd ("running", class_run, NULL, _("Running the program."), &cmdlist); + + /* Define general commands. */ + + add_com ("pwd", class_files, pwd_command, _("\ +Print working directory. This is used for your program as well.")); + + c = add_cmd ("cd", class_files, cd_command, _("\ +Set working directory to DIR for debugger and program being debugged.\n\ +The change does not take effect for the program being debugged\n\ +until the next time it is started."), &cmdlist); + set_cmd_completer (c, filename_completer); + + add_com ("echo", class_support, echo_command, _("\ +Print a constant string. Give string as argument.\n\ +C escape sequences may be used in the argument.\n\ +No newline is added at the end of the argument;\n\ +use \"\\n\" if you want a newline to be printed.\n\ +Since leading and trailing whitespace are ignored in command arguments,\n\ +if you want to print some you must use \"\\\" before leading whitespace\n\ +to be printed or after trailing whitespace.")); + add_com ("document", class_support, document_command, _("\ +Document a user-defined command.\n\ +Give command name as argument. Give documentation on following lines.\n\ +End with a line of just \"end\".")); + add_com ("define", class_support, define_command, _("\ +Define a new command name. Command name is argument.\n\ +Definition appears on following lines, one command per line.\n\ +End with a line of just \"end\".\n\ +Use the \"document\" command to give documentation for the new command.\n\ +Commands defined in this way may have up to ten arguments.")); + + source_help_text = xstrprintf (_("\ +Read commands from a file named FILE.\n\ +Optional -v switch (before the filename) causes each command in\n\ +FILE to be echoed as it is executed.\n\ +Note that the file \"%s\" is read automatically in this way\n\ +when GDB is started."), gdbinit); + c = add_cmd ("source", class_support, source_command, + source_help_text, &cmdlist); + set_cmd_completer (c, filename_completer); + + add_setshow_enum_cmd ("script-extension", class_support, + script_ext_enums, &script_ext_mode, _("\ +Set mode for script filename extension recognition."), _("\ +Show mode for script filename extension recognition."), _("\ +off == no filename extension recognition (all sourced files are GDB scripts)\n\ +soft == evaluate script according to filename extension, fallback to GDB script" + "\n\ +strict == evaluate script according to filename extension, error if not supported" + ), + NULL, + show_script_ext_mode, + &setlist, &showlist); + + add_com ("quit", class_support, quit_command, _("Exit gdb.")); + c = add_com ("help", class_support, help_command, + _("Print list of commands.")); + set_cmd_completer (c, command_completer); + add_com_alias ("q", "quit", class_support, 1); + add_com_alias ("h", "help", class_support, 1); + + add_setshow_boolean_cmd ("verbose", class_support, &info_verbose, _("\ +Set verbosity."), _("\ +Show verbosity."), NULL, + set_verbose, + show_info_verbose, + &setlist, &showlist); + + add_prefix_cmd ("history", class_support, set_history, + _("Generic command for setting command history parameters."), + &sethistlist, "set history ", 0, &setlist); + add_prefix_cmd ("history", class_support, show_history, + _("Generic command for showing command history parameters."), + &showhistlist, "show history ", 0, &showlist); + + add_setshow_boolean_cmd ("expansion", no_class, &history_expansion_p, _("\ +Set history expansion on command input."), _("\ +Show history expansion on command input."), _("\ +Without an argument, history expansion is enabled."), + NULL, + show_history_expansion_p, + &sethistlist, &showhistlist); + + add_prefix_cmd ("info", class_info, info_command, _("\ +Generic command for showing things about the program being debugged."), + &infolist, "info ", 0, &cmdlist); + add_com_alias ("i", "info", class_info, 1); + add_com_alias ("inf", "info", class_info, 1); + + add_com ("complete", class_obscure, complete_command, + _("List the completions for the rest of the line as a command.")); + + add_prefix_cmd ("show", class_info, show_command, _("\ +Generic command for showing things about the debugger."), + &showlist, "show ", 0, &cmdlist); + /* Another way to get at the same thing. */ + add_info ("set", show_command, _("Show all GDB settings.")); + + add_cmd ("commands", no_class, show_commands, _("\ +Show the history of commands you typed.\n\ +You can supply a command number to start with, or a `+' to start after\n\ +the previous command number shown."), + &showlist); + + add_cmd ("version", no_class, show_version, + _("Show what version of GDB this is."), &showlist); + + add_com ("while", class_support, while_command, _("\ +Execute nested commands WHILE the conditional expression is non zero.\n\ +The conditional expression must follow the word `while' and must in turn be\n\ +followed by a new line. The nested commands must be entered one per line,\n\ +and should be terminated by the word `end'.")); + + add_com ("if", class_support, if_command, _("\ +Execute nested commands once IF the conditional expression is non zero.\n\ +The conditional expression must follow the word `if' and must in turn be\n\ +followed by a new line. The nested commands must be entered one per line,\n\ +and should be terminated by the word 'else' or `end'. If an else clause\n\ +is used, the same rules apply to its nested commands as to the first ones.")); + + /* If target is open when baud changes, it doesn't take effect until the + next open (I think, not sure). */ + add_setshow_zinteger_cmd ("remotebaud", no_class, &baud_rate, _("\ +Set baud rate for remote serial I/O."), _("\ +Show baud rate for remote serial I/O."), _("\ +This value is used to set the speed of the serial port when debugging\n\ +using remote targets."), + NULL, + show_baud_rate, + &setlist, &showlist); + + add_setshow_zinteger_cmd ("remote", no_class, &remote_debug, _("\ +Set debugging of remote protocol."), _("\ +Show debugging of remote protocol."), _("\ +When enabled, each packet sent or received with the remote target\n\ +is displayed."), + NULL, + show_remote_debug, + &setdebuglist, &showdebuglist); + + add_setshow_integer_cmd ("remotetimeout", no_class, &remote_timeout, _("\ +Set timeout limit to wait for target to respond."), _("\ +Show timeout limit to wait for target to respond."), _("\ +This value is used to set the time limit for gdb to wait for a response\n\ +from the target."), + NULL, + show_remote_timeout, + &setlist, &showlist); + + add_prefix_cmd ("debug", no_class, set_debug, + _("Generic command for setting gdb debugging flags"), + &setdebuglist, "set debug ", 0, &setlist); + + add_prefix_cmd ("debug", no_class, show_debug, + _("Generic command for showing gdb debugging flags"), + &showdebuglist, "show debug ", 0, &showlist); + + c = add_com ("shell", class_support, shell_escape, _("\ +Execute the rest of the line as a shell command.\n\ +With no arguments, run an inferior shell.")); + set_cmd_completer (c, filename_completer); + + c = add_com ("edit", class_files, edit_command, _("\ +Edit specified file or function.\n\ +With no argument, edits file containing most recent line listed.\n\ +Editing targets can be specified in these ways:\n\ + FILE:LINENUM, to edit at that line in that file,\n\ + FUNCTION, to edit at the beginning of that function,\n\ + FILE:FUNCTION, to distinguish among like-named static functions.\n\ + *ADDRESS, to edit at the line containing that address.\n\ +Uses EDITOR environment variable contents as editor (or ex as default).")); + + c->completer = location_completer; + + add_com ("list", class_files, list_command, _("\ +List specified function or line.\n\ +With no argument, lists ten more lines after or around previous listing.\n\ +\"list -\" lists the ten lines before a previous ten-line listing.\n\ +One argument specifies a line, and ten lines are listed around that line.\n\ +Two arguments with comma between specify starting and ending lines to list.\n\ +Lines can be specified in these ways:\n\ + LINENUM, to list around that line in current file,\n\ + FILE:LINENUM, to list around that line in that file,\n\ + FUNCTION, to list around beginning of that function,\n\ + FILE:FUNCTION, to distinguish among like-named static functions.\n\ + *ADDRESS, to list around the line containing that address.\n\ +With two args if one is empty it stands for ten lines away from the other arg.")); + + if (!xdb_commands) + add_com_alias ("l", "list", class_files, 1); + else + add_com_alias ("v", "list", class_files, 1); + + if (dbx_commands) + add_com_alias ("file", "list", class_files, 1); + + c = add_com ("disassemble", class_vars, disassemble_command, _("\ +Disassemble a specified section of memory.\n\ +Default is the function surrounding the pc of the selected frame.\n\ +With a /m modifier, source lines are included (if available).\n\ +With a /r modifier, raw instructions in hex are included.\n\ +With a single argument, the function surrounding that address is dumped.\n\ +Two arguments (separated by a comma) are taken as a range of memory to dump.")); + set_cmd_completer (c, location_completer); + if (xdb_commands) + add_com_alias ("va", "disassemble", class_xdb, 0); + + /* NOTE: cagney/2000-03-20: Being able to enter ``(gdb) !ls'' would + be a really useful feature. Unfortunately, the below wont do + this. Instead it adds support for the form ``(gdb) ! ls'' + (i.e. the space is required). If the ``!'' command below is + added the complains about no ``!'' command would be replaced by + complains about how the ``!'' command is broken :-) */ + if (xdb_commands) + add_com_alias ("!", "shell", class_support, 0); + + c = add_com ("make", class_support, make_command, _("\ +Run the ``make'' program using the rest of the line as arguments.")); + set_cmd_completer (c, filename_completer); + add_cmd ("user", no_class, show_user, _("\ +Show definitions of user defined commands.\n\ +Argument is the name of the user defined command.\n\ +With no argument, show definitions of all user defined commands."), &showlist); + add_com ("apropos", class_support, apropos_command, + _("Search for commands matching a REGEXP")); + + add_setshow_integer_cmd ("max-user-call-depth", no_class, + &max_user_call_depth, _("\ +Set the max call depth for user-defined commands."), _("\ +Show the max call depth for user-defined commands."), NULL, + NULL, + show_max_user_call_depth, + &setlist, &showlist); + + add_setshow_boolean_cmd ("trace-commands", no_class, &trace_commands, _("\ +Set tracing of GDB CLI commands."), _("\ +Show state of GDB CLI command tracing."), _("\ +When 'on', each command is displayed as it is executed."), + NULL, + NULL, + &setlist, &showlist); +}
cli-cmds.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-logging.c =================================================================== --- cli-logging.c (nonexistent) +++ cli-logging.c (revision 842) @@ -0,0 +1,238 @@ +/* Command-line output logging for GDB, the GNU debugger. + + Copyright (c) 2003, 2004, 2007, 2008, 2009, 2010 + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#include "defs.h" +#include "gdbcmd.h" +#include "ui-out.h" + +#include "gdb_string.h" + +/* These hold the pushed copies of the gdb output files. + If NULL then nothing has yet been pushed. */ +struct saved_output_files +{ + struct ui_file *out; + struct ui_file *err; + struct ui_file *log; + struct ui_file *targ; +}; +static struct saved_output_files saved_output; +static char *saved_filename; + +static char *logging_filename; +static void +show_logging_filename (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("The current logfile is \"%s\".\n"), + value); +} + +int logging_overwrite; +static void +show_logging_overwrite (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Whether logging overwrites or appends to the log file is %s.\n"), + value); +} + +int logging_redirect; +static void +show_logging_redirect (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("The logging output mode is %s.\n"), value); +} + +/* If we've pushed output files, close them and pop them. */ +static void +pop_output_files (void) +{ + /* Only delete one of the files -- they are all set to the same + value. */ + ui_file_delete (gdb_stdout); + gdb_stdout = saved_output.out; + gdb_stderr = saved_output.err; + gdb_stdlog = saved_output.log; + gdb_stdtarg = saved_output.targ; + saved_output.out = NULL; + saved_output.err = NULL; + saved_output.log = NULL; + saved_output.targ = NULL; + + ui_out_redirect (uiout, NULL); +} + +/* This is a helper for the `set logging' command. */ +static void +handle_redirections (int from_tty) +{ + struct cleanup *cleanups; + struct ui_file *output; + + if (saved_filename != NULL) + { + fprintf_unfiltered (gdb_stdout, "Already logging to %s.\n", + saved_filename); + return; + } + + output = gdb_fopen (logging_filename, logging_overwrite ? "w" : "a"); + if (output == NULL) + perror_with_name (_("set logging")); + cleanups = make_cleanup_ui_file_delete (output); + + /* Redirects everything to gdb_stdout while this is running. */ + if (!logging_redirect) + { + output = tee_file_new (gdb_stdout, 0, output, 1); + if (output == NULL) + perror_with_name (_("set logging")); + discard_cleanups (cleanups); + cleanups = make_cleanup_ui_file_delete (output); + if (from_tty) + fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n", + logging_filename); + } + else if (from_tty) + fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n", + logging_filename); + + discard_cleanups (cleanups); + + saved_filename = xstrdup (logging_filename); + saved_output.out = gdb_stdout; + saved_output.err = gdb_stderr; + saved_output.log = gdb_stdlog; + saved_output.targ = gdb_stdtarg; + + gdb_stdout = output; + gdb_stderr = output; + gdb_stdlog = output; + gdb_stdtarg = output; + + if (ui_out_redirect (uiout, gdb_stdout) < 0) + warning (_("Current output protocol does not support redirection")); +} + +static void +set_logging_on (char *args, int from_tty) +{ + char *rest = args; + if (rest && *rest) + { + xfree (logging_filename); + logging_filename = xstrdup (rest); + } + handle_redirections (from_tty); +} + +static void +set_logging_off (char *args, int from_tty) +{ + if (saved_filename == NULL) + return; + + pop_output_files (); + if (from_tty) + fprintf_unfiltered (gdb_stdout, "Done logging to %s.\n", saved_filename); + xfree (saved_filename); + saved_filename = NULL; +} + +static void +set_logging_command (char *args, int from_tty) +{ + printf_unfiltered (_("\ +\"set logging\" lets you log output to a file.\n\ +Usage: set logging on [FILENAME]\n\ + set logging off\n\ + set logging file FILENAME\n\ + set logging overwrite [on|off]\n\ + set logging redirect [on|off]\n")); +} + +static void +show_logging_command (char *args, int from_tty) +{ + if (saved_filename) + printf_unfiltered (_("Currently logging to \"%s\".\n"), saved_filename); + if (saved_filename == NULL + || strcmp (logging_filename, saved_filename) != 0) + printf_unfiltered (_("Future logs will be written to %s.\n"), + logging_filename); + + if (logging_overwrite) + printf_unfiltered (_("Logs will overwrite the log file.\n")); + else + printf_unfiltered (_("Logs will be appended to the log file.\n")); + + if (logging_redirect) + printf_unfiltered (_("Output will be sent only to the log file.\n")); + else + printf_unfiltered (_("Output will be logged and displayed.\n")); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_cli_logging; + +void +_initialize_cli_logging (void) +{ + static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist; + + + add_prefix_cmd ("logging", class_support, set_logging_command, + _("Set logging options"), &set_logging_cmdlist, + "set logging ", 0, &setlist); + add_prefix_cmd ("logging", class_support, show_logging_command, + _("Show logging options"), &show_logging_cmdlist, + "show logging ", 0, &showlist); + add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite, _("\ +Set whether logging overwrites or appends to the log file."), _("\ +Show whether logging overwrites or appends to the log file."), _("\ +If set, logging overrides the log file."), + NULL, + show_logging_overwrite, + &set_logging_cmdlist, &show_logging_cmdlist); + add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect, _("\ +Set the logging output mode."), _("\ +Show the logging output mode."), _("\ +If redirect is off, output will go to both the screen and the log file.\n\ +If redirect is on, output will go only to the log file."), + NULL, + show_logging_redirect, + &set_logging_cmdlist, &show_logging_cmdlist); + add_setshow_filename_cmd ("file", class_support, &logging_filename, _("\ +Set the current logfile."), _("\ +Show the current logfile."), _("\ +The logfile is used when directing GDB's output."), + NULL, + show_logging_filename, + &set_logging_cmdlist, &show_logging_cmdlist); + add_cmd ("on", class_support, set_logging_on, + _("Enable logging."), &set_logging_cmdlist); + add_cmd ("off", class_support, set_logging_off, + _("Disable logging."), &set_logging_cmdlist); + + logging_filename = xstrdup ("gdb.txt"); +}
cli-logging.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: cli-decode.h =================================================================== --- cli-decode.h (nonexistent) +++ cli-decode.h (revision 842) @@ -0,0 +1,319 @@ +/* Header file for GDB command decoding library. + + Copyright (c) 2000, 2003, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . */ + +#if !defined (CLI_DECODE_H) +#define CLI_DECODE_H 1 + +#include "command.h" + +struct re_pattern_buffer; + +#if 0 +/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum + cmd_types'' can be moved from "command.h" to "cli-decode.h". */ +/* Not a set/show command. Note that some commands which begin with + "set" or "show" might be in this category, if their syntax does + not fall into one of the following categories. */ +typedef enum cmd_types + { + not_set_cmd, + set_cmd, + show_cmd + } +cmd_types; +#endif + +/* This structure records one command'd definition. */ + + +/* This flag is used by the code executing commands to warn the user + the first time a deprecated command is used, see the 'flags' field in + the following struct. +*/ +#define CMD_DEPRECATED 0x1 +#define DEPRECATED_WARN_USER 0x2 +#define MALLOCED_REPLACEMENT 0x4 + +struct cmd_list_element + { + /* Points to next command in this list. */ + struct cmd_list_element *next; + + /* Name of this command. */ + char *name; + + /* Command class; class values are chosen by application program. */ + enum command_class class; + + /* Function definition of this command. NULL for command class + names and for help topics that are not really commands. NOTE: + cagney/2002-02-02: This function signature is evolving. For + the moment suggest sticking with either set_cmd_cfunc() or + set_cmd_sfunc(). */ + void (*func) (struct cmd_list_element *c, char *args, int from_tty); + /* The command's real callback. At present func() bounces through + to one of the below. */ + union + { + /* If type is not_set_cmd, call it like this: */ + cmd_cfunc_ftype *cfunc; + /* If type is set_cmd or show_cmd, first set the variables, + and then call this: */ + cmd_sfunc_ftype *sfunc; + } + function; + + /* Local state (context) for this command. This can be anything. */ + void *context; + + /* Documentation of this command (or help topic). + First line is brief documentation; remaining lines form, with it, + the full documentation. First line should end with a period. + Entire string should also end with a period, not a newline. */ + char *doc; + + /* For set/show commands. A method for printing the output to the + specified stream. */ + show_value_ftype *show_value_func; + + /* flags : a bitfield + + bit 0: (LSB) CMD_DEPRECATED, when 1 indicated that this command + is deprecated. It may be removed from gdb's command set in the + future. + + bit 1: DEPRECATED_WARN_USER, the user needs to be warned that + this is a deprecated command. The user should only be warned + the first time a command is used. + + bit 2: MALLOCED_REPLACEMENT, when functions are deprecated at + compile time (this is the way it should, in general, be done) + the memory containing the replacement string is statically + allocated. In some cases it makes sense to deprecate commands + at runtime (the testsuite is one example). In this case the + memory for replacement is malloc'ed. When a command is + undeprecated or re-deprecated at runtime we don't want to risk + calling free on statically allocated memory, so we check this + flag. + */ + int flags; + + /* If this command is deprecated, this is the replacement name. */ + char *replacement; + + /* If this command represents a show command, then this function + is called before the variable's value is examined. */ + void (*pre_show_hook) (struct cmd_list_element *c); + + /* Hook for another command to be executed before this command. */ + struct cmd_list_element *hook_pre; + + /* Hook for another command to be executed after this command. */ + struct cmd_list_element *hook_post; + + /* Flag that specifies if this command is already running its hook. */ + /* Prevents the possibility of hook recursion. */ + int hook_in; + + /* Nonzero identifies a prefix command. For them, the address + of the variable containing the list of subcommands. */ + struct cmd_list_element **prefixlist; + + /* For prefix commands only: + String containing prefix commands to get here: this one + plus any others needed to get to it. Should end in a space. + It is used before the word "command" in describing the + commands reached through this prefix. */ + char *prefixname; + + /* For prefix commands only: + nonzero means do not get an error if subcommand is not + recognized; call the prefix's own function in that case. */ + char allow_unknown; + + /* Nonzero says this is an abbreviation, and should not + be mentioned in lists of commands. + This allows "br" to complete to "break", which it + otherwise wouldn't. */ + char abbrev_flag; + + /* Completion routine for this command. TEXT is the text beyond + what was matched for the command itself (leading whitespace is + skipped). It stops where we are supposed to stop completing + (rl_point) and is '\0' terminated. + + Return value is a malloc'd vector of pointers to possible completions + terminated with NULL. If there are no completions, returning a pointer + to a NULL would work but returning NULL itself is also valid. + WORD points in the same buffer as TEXT, and completions should be + returned relative to this position. For example, suppose TEXT is "foo" + and we want to complete to "foobar". If WORD is "oo", return + "oobar"; if WORD is "baz/foo", return "baz/foobar". */ + char **(*completer) (struct cmd_list_element *cmd, char *text, char *word); + + /* Destruction routine for this command. If non-NULL, this is + called when this command instance is destroyed. This may be + used to finalize the CONTEXT field, if needed. */ + void (*destroyer) (struct cmd_list_element *self, void *context); + + /* Type of "set" or "show" command (or SET_NOT_SET if not "set" + or "show"). */ + cmd_types type; + + /* Pointer to variable affected by "set" and "show". Doesn't matter + if type is not_set. */ + void *var; + + /* What kind of variable is *VAR? */ + var_types var_type; + + /* Pointer to NULL terminated list of enumerated values (like argv). */ + const char **enums; + + /* Pointer to command strings of user-defined commands */ + struct command_line *user_commands; + + /* Pointer to command that is hooked by this one, (by hook_pre) + so the hook can be removed when this one is deleted. */ + struct cmd_list_element *hookee_pre; + + /* Pointer to command that is hooked by this one, (by hook_post) + so the hook can be removed when this one is deleted. */ + struct cmd_list_element *hookee_post; + + /* Pointer to command that is aliased by this one, so the + aliased command can be located in case it has been hooked. */ + struct cmd_list_element *cmd_pointer; + + /* Start of a linked list of all aliases of this command. */ + struct cmd_list_element *aliases; + + /* Link pointer for aliases on an alias list. */ + struct cmd_list_element *alias_chain; + }; + +/* API to the manipulation of command lists. */ + +extern struct cmd_list_element *add_cmd (char *, enum command_class, + void (*fun) (char *, int), char *, + struct cmd_list_element **); + +extern struct cmd_list_element *add_alias_cmd (char *, char *, + enum command_class, int, + struct cmd_list_element **); + +extern struct cmd_list_element *add_prefix_cmd (char *, enum command_class, + void (*fun) (char *, int), + char *, + struct cmd_list_element **, + char *, int, + struct cmd_list_element **); + +extern struct cmd_list_element *add_abbrev_prefix_cmd (char *, + enum command_class, + void (*fun) (char *, + int), + char *, + struct cmd_list_element + **, char *, int, + struct cmd_list_element + **); + +/* Set the commands corresponding callback. */ + +extern void set_cmd_cfunc (struct cmd_list_element *cmd, + void (*cfunc) (char *args, int from_tty)); + +extern void set_cmd_sfunc (struct cmd_list_element *cmd, + void (*sfunc) (char *args, int from_tty, + struct cmd_list_element * c)); + +extern void set_cmd_completer (struct cmd_list_element *cmd, + char **(*completer) (struct cmd_list_element *self, + char *text, char *word)); + +/* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs + around in cmd objects to test the value of the commands sfunc(). */ +extern int cmd_cfunc_eq (struct cmd_list_element *cmd, + void (*cfunc) (char *args, int from_tty)); + +/* Access to the command's local context. */ +extern void set_cmd_context (struct cmd_list_element *cmd, void *context); +extern void *get_cmd_context (struct cmd_list_element *cmd); + +extern struct cmd_list_element *lookup_cmd (char **, + struct cmd_list_element *, char *, + int, int); + +extern struct cmd_list_element *lookup_cmd_1 (char **, + struct cmd_list_element *, + struct cmd_list_element **, + int); + +extern struct cmd_list_element * + deprecate_cmd (struct cmd_list_element *, char * ); + +extern void + deprecated_cmd_warning (char **); + +extern int + lookup_cmd_composition (char *text, + struct cmd_list_element **alias, + struct cmd_list_element **prefix_cmd, + struct cmd_list_element **cmd); + +extern struct cmd_list_element *add_com (char *, enum command_class, + void (*fun) (char *, int), char *); + +extern struct cmd_list_element *add_com_alias (char *, char *, + enum command_class, int); + +extern struct cmd_list_element *add_info (char *, void (*fun) (char *, int), + char *); + +extern struct cmd_list_element *add_info_alias (char *, char *, int); + +extern char **complete_on_cmdlist (struct cmd_list_element *, char *, char *); + +extern char **complete_on_enum (const char *enumlist[], char *, char *); + +extern void help_cmd_list (struct cmd_list_element *, enum command_class, + char *, int, struct ui_file *); + +/* Functions that implement commands about CLI commands. */ + +extern void help_cmd (char *, struct ui_file *); + +extern void help_list (struct cmd_list_element *, char *, + enum command_class, struct ui_file *); + +extern void apropos_cmd (struct ui_file *, struct cmd_list_element *, + struct re_pattern_buffer *, char *); + +/* Used to mark commands that don't do anything. If we just leave the + function field NULL, the command is interpreted as a help topic, or + as a class of commands. */ + +extern void not_just_help_class_command (char *arg, int from_tty); + +/* Exported to cli/cli-setshow.c */ + +extern void print_doc_line (struct ui_file *, char *); + + +#endif /* !defined (CLI_DECODE_H) */
cli-decode.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.