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-6.8/gdb/cli
- from Rev 827 to Rev 840
- ↔ Reverse comparison
Rev 827 → Rev 840
/cli-cmds.c
0,0 → 1,1431
/* GDB CLI commands. |
|
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 |
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 <http://www.gnu.org/licenses/>. */ |
|
#include "defs.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" |
|
#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" |
|
#ifdef TUI |
#include "tui/tui.h" /* For tui_active et.al. */ |
#endif |
|
#include <fcntl.h> |
|
/* 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 "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; |
|
/* 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.")); |
quit_force (args, from_tty); |
} |
|
|
/* JPB: Some picky Ubuntu GCC compilers don't like the result of getcwd being |
ignored (even if you cast it to void). So capture the value and ignore |
THAT. */ |
static void |
pwd_command (char *args, int from_tty) |
{ |
char *res; /* For getcwd result */ |
if (args) |
error (_("The \"pwd\" command does not take an argument: %s"), args); |
res = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); |
|
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); |
} |
|
void |
source_script (char *file, int from_tty) |
{ |
FILE *stream; |
struct cleanup *old_cleanups; |
char *full_pathname = NULL; |
int fd; |
|
if (file == NULL || *file == 0) |
{ |
error (_("source command requires file name of file to source.")); |
} |
|
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, 0, &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 |
return; |
} |
|
stream = fdopen (fd, FOPEN_RT); |
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; |
int cmdlen, log10; |
unsigned m; |
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) return; /* C++ */ |
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 == '*') |
{ |
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)); |
sym = find_pc_function (sal.pc); |
if (sym) |
{ |
deprecated_print_address_numeric (sal.pc, 1, gdb_stdout); |
printf_filtered (" is in "); |
fputs_filtered (SYMBOL_PRINT_NAME (sym), gdb_stdout); |
printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line); |
} |
else |
{ |
deprecated_print_address_numeric (sal.pc, 1, gdb_stdout); |
printf_filtered (" is at %s:%d.\n", |
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"; |
|
/* Approximate base-10 log of line to 1 unit for digit count */ |
for(log10=32, m=0x80000000; !(sal.line & m) && log10>0; log10--, m=m>>1); |
log10 = 1 + (int)((log10 + (0 == ((m-1) & sal.line)))/3.32192809); |
|
/* 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 == '*') |
{ |
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)); |
sym = find_pc_function (sal.pc); |
if (sym) |
{ |
deprecated_print_address_numeric (sal.pc, 1, gdb_stdout); |
printf_filtered (" is in "); |
fputs_filtered (SYMBOL_PRINT_NAME (sym), gdb_stdout); |
printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line); |
} |
else |
{ |
deprecated_print_address_numeric (sal.pc, 1, gdb_stdout); |
printf_filtered (" is at %s:%d.\n", |
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); |
} |
|
/* Dump a specified section of assembly code. With no command line |
arguments, this command will dump the assembly code for the |
function surrounding the pc value in the selected frame. With one |
argument, it will dump the assembly code surrounding that pc value. |
Two arguments are interpeted as bounds within which to dump |
assembly. */ |
|
static void |
disassemble_command (char *arg, int from_tty) |
{ |
CORE_ADDR low, high; |
char *name; |
CORE_ADDR pc, pc_masked; |
char *space_index; |
#if 0 |
asection *section; |
#endif |
|
name = NULL; |
if (!arg) |
{ |
pc = get_frame_pc (get_selected_frame (_("No frame selected."))); |
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 (low, pc); |
#endif |
low += gdbarch_deprecated_function_start_offset (current_gdbarch); |
} |
else if (!(space_index = (char *) strchr (arg, ' '))) |
{ |
/* One argument. */ |
pc = parse_and_eval_address (arg); |
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 (low, pc); |
#endif |
low += gdbarch_deprecated_function_start_offset (current_gdbarch); |
} |
else |
{ |
/* Two arguments. */ |
*space_index = '\0'; |
low = parse_and_eval_address (arg); |
high = parse_and_eval_address (space_index + 1); |
} |
|
#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 "); |
deprecated_print_address_numeric (low, 1, gdb_stdout); |
printf_filtered (" to "); |
deprecated_print_address_numeric (high, 1, gdb_stdout); |
printf_filtered (":\n"); |
} |
|
/* Dump the specified range. */ |
gdb_disassembly (uiout, 0, 0, 0, -1, low, high); |
|
printf_filtered ("End of assembler dump.\n"); |
gdb_flush (gdb_stdout); |
} |
#if defined(TUI) |
else |
{ |
tui_show_assembly (low); |
} |
#endif |
} |
|
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) |
{ |
c = lookup_cmd (&args, cmdlist, "", 0, 1); |
if (c->class != class_user) |
error (_("Not a user command.")); |
show_user_1 (c, gdb_stdout); |
} |
else |
{ |
for (c = cmdlist; c; c = c->next) |
{ |
if (c->class == class_user) |
show_user_1 (c, 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 print 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_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 ("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 single argument, the function surrounding that address is dumped.\n\ |
Two arguments 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-script.h
===================================================================
--- cli-script.h (nonexistent)
+++ cli-script.h (revision 840)
@@ -0,0 +1,62 @@
+/* Header file for GDB CLI command implementation library.
+ Copyright (c) 2000, 2002, 2007, 2008 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_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, struct ui_file *stream);
+
+/* Exported to gdb/breakpoint.c */
+
+extern enum command_control_type
+ execute_control_command (struct command_line *cmd);
+
+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 840)
@@ -0,0 +1,38 @@
+/* Dump-to-file commands, for GDB, the GNU debugger.
+
+ Copyright (c) 2001, 2005, 2007, 2008 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 840)
@@ -0,0 +1,132 @@
+/* Header file for GDB CLI command implementation library.
+ Copyright (c) 2000,2006,2007,2008 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 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 840)
@@ -0,0 +1,438 @@
+/* Handle set and show GDB commands.
+
+ Copyright (c) 2000, 2001, 2002, 2003, 2007, 2008
+ 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 = savestring (arg, strlen (arg));
+ break;
+ case var_optional_filename:
+ if (arg == NULL)
+ arg = "";
+ if (*(char **) c->var != NULL)
+ xfree (*(char **) c->var);
+ *(char **) c->var = savestring (arg, strlen (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_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_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
+ {
+ long length;
+ char *value = ui_file_xstrdup (stb->stream, &length);
+ 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-utils.c
===================================================================
--- cli-utils.c (nonexistent)
+++ cli-utils.c (revision 840)
@@ -0,0 +1,19 @@
+/* GDB CLI utility library.
+ Copyright (c) 2001, 2007, 2008 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 "cli/cli-utils.h"
+
cli-utils.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 840)
@@ -0,0 +1,159 @@
+/* CLI Definitions for GDB, the GNU debugger.
+
+ Copyright (c) 2002, 2003, 2007, 2008 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 (void)
+{
+ 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 840)
@@ -0,0 +1,36 @@
+/* Header file for GDB CLI set and show commands implementation.
+ Copyright (c) 2000, 2001, 2007, 2008 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 840)
@@ -0,0 +1,1668 @@
+/* Handle lists of commands, their decoding and documentation, for GDB.
+
+ Copyright (c) 1986, 1989, 1990, 1991, 1998, 2000, 2001, 2002, 2004, 2007,
+ 2008 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 *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) (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;
+
+ delete_cmd (name, list);
+
+ 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_pre = NULL;
+ c->hook_post = 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);
+ c->type = not_set_cmd;
+ c->var = NULL;
+ c->var_type = var_boolean;
+ c->enums = NULL;
+ c->user_commands = NULL;
+ c->hookee_pre = NULL;
+ c->hookee_post = NULL;
+ c->cmd_pointer = 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)
+ {
+ delete_cmd (name, list);
+ 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;
+ 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;
+}
+
+struct cmd_list_element *
+deprecated_add_set_cmd (char *name,
+ enum command_class class,
+ var_types var_type,
+ void *var,
+ char *doc,
+ struct cmd_list_element **list)
+{
+ return add_set_or_show_cmd (name, set_cmd, class, var_type, var, doc, list);
+}
+
+/* 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)
+{
+ add_setshow_cmd_full (name, class, var_optional_filename, 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_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);
+}
+
+/* Remove the command named NAME from the command list. */
+
+void
+delete_cmd (char *name, struct cmd_list_element **list)
+{
+ struct cmd_list_element *c;
+ struct cmd_list_element *p;
+
+ while (*list && strcmp ((*list)->name, name) == 0)
+ {
+ if ((*list)->hookee_pre)
+ (*list)->hookee_pre->hook_pre = 0; /* Hook slips out of its mouth */
+ if ((*list)->hookee_post)
+ (*list)->hookee_post->hook_post = 0; /* Hook slips out of its bottom */
+ p = (*list)->next;
+ xfree (* list);
+ *list = p;
+ }
+
+ if (*list)
+ for (c = *list; c->next;)
+ {
+ if (strcmp (c->next->name, name) == 0)
+ {
+ if (c->next->hookee_pre)
+ c->next->hookee_pre->hook_pre = 0; /* hooked cmd gets away. */
+ if (c->next->hookee_post)
+ c->next->hookee_post->hook_post = 0; /* remove post hook */
+ /* :( no fishing metaphore */
+ p = c->next->next;
+ xfree (c->next);
+ c->next = p;
+ }
+ else
+ c = c->next;
+ }
+}
+
+/* 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=1; /*Needed to avoid double printing*/
+ /* Walk through the commands */
+ for (c=commandlist;c;c=c->next)
+ {
+ 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 */
+ if (c->prefixlist != NULL)
+ {
+ /* 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);
+ }
+ }
+}
+
+
+/* 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);
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = (*text)[tmp];
+ command[tmp] = x;
+ }
+ 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);
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = text[tmp];
+ command[tmp] = x;
+ }
+ 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 840)
@@ -0,0 +1,1470 @@
+/* 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
+ 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"
+
+/* Prototypes for local functions */
+
+static enum command_control_type
+ recurse_read_control_structure (struct command_line *current_cmd);
+
+static char *insert_args (char *line);
+
+static struct cleanup * setup_user_args (char *p);
+
+static void validate_comname (char *);
+
+/* 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 = savestring (args, strlen (args));
+
+ return cmd;
+}
+
+/* Build and return a new command structure for the control commands
+ such as "if" and "while". */
+
+static 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 (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;
+ }
+
+ /* 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;
+ }
+
+ default:
+ warning (_("Invalid control type in canned commands structure."));
+ break;
+ }
+
+ do_cleanups (old_chain);
+
+ return ret;
+}
+
+/* "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;
+
+ suppress_next_print_command_trace = 1;
+ execute_control_command (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;
+
+ suppress_next_print_command_trace = 1;
+ execute_control_command (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 one line from the input stream. If the command is an "else" or
+ "end", return such an indication to the caller. */
+
+static enum misc_command_type
+read_next_line (struct command_line **command)
+{
+ char *p, *p1, *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;
+
+ p = command_line_input (prompt_ptr, instream == stdin, "commands");
+
+ /* Not sure what to do here. */
+ if (p == NULL)
+ return end_command;
+
+ /* Strip leading and trailing whitespace. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ p1 = p + strlen (p);
+ while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t'))
+ p1--;
+
+ /* Blanks and comments don't really do anything, but we need to
+ distinguish them from else, end and other commands which can be
+ executed. */
+ if (p1 == p || p[0] == '#')
+ return nop_command;
+
+ /* Is this the end of a simple, while, or if control structure? */
+ if (p1 - p == 3 && !strncmp (p, "end", 3))
+ return end_command;
+
+ /* Is the else clause of an if control structure? */
+ if (p1 - 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 (p1 - p > 5 && !strncmp (p, "while", 5))
+ {
+ char *first_arg;
+ first_arg = p + 5;
+ while (first_arg < p1 && isspace (*first_arg))
+ first_arg++;
+ *command = build_command_line (while_control, first_arg);
+ }
+ else if (p1 - p > 2 && !strncmp (p, "if", 2))
+ {
+ char *first_arg;
+ first_arg = p + 2;
+ while (first_arg < p1 && isspace (*first_arg))
+ first_arg++;
+ *command = build_command_line (if_control, first_arg);
+ }
+ else if (p1 - p >= 8 && !strncmp (p, "commands", 8))
+ {
+ char *first_arg;
+ first_arg = p + 8;
+ while (first_arg < p1 && isspace (*first_arg))
+ first_arg++;
+ *command = build_command_line (commands_control, first_arg);
+ }
+ else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = break_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = continue_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else
+ {
+ /* A normal command. */
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = savestring (p, p1 - 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.
+
+ The parent_control parameter is the control structure in which the
+ following commands are nested. */
+
+static enum command_control_type
+recurse_read_control_structure (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;
+
+ 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 = read_next_line (&next);
+
+ /* 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 == 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 == commands_control)
+ {
+ control_level++;
+ ret = recurse_read_control_structure (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. */
+
+#define END_MESSAGE "End with a line saying just \"end\"."
+
+struct command_line *
+read_command_lines (char *prompt_arg, int from_tty)
+{
+ struct command_line *head, *tail, *next;
+ struct cleanup *old_chain;
+ enum command_control_type ret;
+ enum misc_command_type val;
+
+ control_level = 0;
+
+ 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 = tail = NULL;
+ old_chain = NULL;
+
+ while (1)
+ {
+ dont_repeat ();
+ val = read_next_line (&next);
+
+ /* 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 == commands_control)
+ {
+ control_level++;
+ ret = recurse_read_control_structure (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);
+ }
+
+ if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ())
+ {
+ (*deprecated_readline_end_hook) ();
+ }
+ 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;
+}
+
+static void
+validate_comname (char *comname)
+{
+ char *p;
+
+ if (comname == 0)
+ error_no_arg (_("name of command to define"));
+
+ p = comname;
+ while (*p)
+ {
+ if (!isalnum (*p) && *p != '-' && *p != '_')
+ error (_("Junk in argument list: \"%s\""), p);
+ p++;
+ }
+}
+
+/* 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;
+ char *tem = comname;
+ char *tem2;
+ 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
+
+ validate_comname (comname);
+
+ /* Look it up, and verify that we got an exact match. */
+ c = lookup_cmd (&tem, cmdlist, "", -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, cmdlist, "", -1, 0);
+ if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0)
+ hookc = 0;
+ if (!hookc)
+ {
+ warning (_("Your new `%s' command does not hook any existing command."),
+ comname);
+ if (!query ("Proceed? "))
+ error (_("Not confirmed."));
+ }
+ }
+
+ comname = savestring (comname, strlen (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\".", comname);
+ cmds = read_command_lines (tmpbuf, from_tty);
+
+ if (c && c->class == class_user)
+ free_command_lines (&c->user_commands);
+
+ newc = add_cmd (comname, class_user, user_defined_command,
+ (c && c->class == class_user)
+ ? c->doc : savestring ("User-defined.", 13), &cmdlist);
+ 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;
+ char *tem = comname;
+ char tmpbuf[128];
+
+ validate_comname (comname);
+
+ c = lookup_cmd (&tem, cmdlist, "", 0, 1);
+
+ if (c->class != class_user)
+ error (_("Command \"%s\" is built-in."), comname);
+
+ sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
+ doclines = read_command_lines (tmpbuf, from_tty);
+
+ 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;
+}
+
+static void
+do_fclose_cleanup (void *stream)
+{
+ fclose (stream);
+}
+
+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 (do_fclose_cleanup, 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);
+}
+
+void
+show_user_1 (struct cmd_list_element *c, struct ui_file *stream)
+{
+ struct command_line *cmdlines;
+
+ cmdlines = c->user_commands;
+ if (!cmdlines)
+ return;
+ fputs_filtered ("User command ", stream);
+ fputs_filtered (c->name, stream);
+ fputs_filtered (":\n", stream);
+
+ 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 840)
@@ -0,0 +1,797 @@
+/* Dump-to-file commands, for GDB, the GNU debugger.
+
+ Copyright (c) 2002, 2005, 2007, 2008 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"
+
+#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;
+ }
+}
+
+
+static void
+do_fclose_cleanup (void *arg)
+{
+ FILE *file = arg;
+ fclose (arg);
+}
+
+static struct cleanup *
+make_cleanup_fclose (FILE *file)
+{
+ return make_cleanup (do_fclose_cleanup, file);
+}
+
+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);
+ target_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 {
+ long 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 (0x%s to 0x%s)\n",
+ paddr_nz ((unsigned long) sec_start
+ + sec_offset + data->load_offset),
+ paddr_nz ((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_long (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-utils.h
===================================================================
--- cli-utils.h (nonexistent)
+++ cli-utils.h (revision 840)
@@ -0,0 +1,20 @@
+/* Header file for GDB CLI utility library.
+ Copyright (c) 2001, 2007, 2008 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_UTILS_H)
+# define CLI_UTILS_H 1
+
+#endif /* !defined (CLI_UTILS_H) */
cli-utils.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-logging.c
===================================================================
--- cli-logging.c (nonexistent)
+++ cli-logging.c (revision 840)
@@ -0,0 +1,228 @@
+/* Command-line output logging for GDB, the GNU debugger.
+
+ Copyright (c) 2003, 2004, 2007, 2008 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 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"));
+
+ /* 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"));
+ 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);
+
+ 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"));
+}
+
+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"));
+}
+
+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 840)
@@ -0,0 +1,308 @@
+/* Header file for GDB command decoding library.
+
+ Copyright (c) 2000, 2003, 2007, 2008 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 it's 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) (char *text, char *word);
+
+ /* 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;
+ };
+
+/* 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) (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 delete_cmd (char *, struct cmd_list_element **);
+
+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