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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/gnu-old/gdb-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

powered by: WebSVN 2.1.0

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