{
const char **s1 = (const char **) arg1;
const char **s2 = (const char **) arg2;
+
return strcmp (*s1, *s2);
}
static void
complete_command (char *arg, int from_tty)
{
- int i;
int argpoint;
char **completions, *point, *arg_prefix;
while (item < size)
{
int next_item;
+
printf_unfiltered ("%s%s\n", arg_prefix, completions[item]);
next_item = item + 1;
while (next_item < size
/* 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;
value);
}
-static int
-find_and_open_script (int from_tty, char **filep, FILE **streamp,
- struct cleanup **cleanupp)
+/* Try to open SCRIPT_FILE.
+ If successful, the full path name is stored in *FULL_PATHP,
+ the stream is stored in *STREAMP, and return 1.
+ The caller is responsible for freeing *FULL_PATHP.
+ If not successful, return 0; errno is set for the last file
+ we tried to open.
+
+ If SEARCH_PATH is non-zero, and the file isn't found in cwd,
+ search for it in the source search path.
+
+ NOTE: This calls openp which uses xfullpath to compute the full path
+ instead of gdb_realpath. Symbolic links are not resolved. */
+
+int
+find_and_open_script (const char *script_file, int search_path,
+ FILE **streamp, char **full_pathp)
{
- char *file = *filep;
- char *full_pathname = NULL;
+ char *file;
int fd;
struct cleanup *old_cleanups;
+ int search_flags = OPF_TRY_CWD_FIRST;
- file = tilde_expand (file);
+ file = tilde_expand (script_file);
old_cleanups = make_cleanup (xfree, file);
- /* Search for and open 'file' on the search path used for source
- files. Put the full location in 'full_pathname'. */
- fd = openp (source_path, OPF_TRY_CWD_FIRST,
- file, O_RDONLY, &full_pathname);
- make_cleanup (xfree, full_pathname);
+ if (search_path)
+ search_flags |= OPF_SEARCH_IN_PATH;
- /* Use the full path name, if it is found. */
- if (full_pathname != NULL && fd != -1)
- {
- file = full_pathname;
- }
+ /* Search for and open 'file' on the search path used for source
+ files. Put the full location in *FULL_PATHP. */
+ fd = openp (source_path, search_flags,
+ file, O_RDONLY, full_pathp);
if (fd == -1)
{
- if (from_tty)
- perror_with_name (file);
- else
- {
- do_cleanups (old_cleanups);
- return 0;
- }
+ int save_errno = errno;
+ do_cleanups (old_cleanups);
+ errno = save_errno;
+ return 0;
}
- *streamp = fdopen (fd, FOPEN_RT);
- *filep = file;
- *cleanupp = old_cleanups;
+ do_cleanups (old_cleanups);
+ *streamp = fdopen (fd, FOPEN_RT);
return 1;
}
-void
-source_script (char *file, int from_tty)
-{
- FILE *stream;
- struct cleanup *old_cleanups;
-
- if (file == NULL || *file == 0)
- {
- error (_("source command requires file name of file to source."));
- }
-
- if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups))
- return;
+/* Load script FILE, which has already been opened as STREAM.
+ STREAM is closed before we return. */
+static void
+source_script_from_stream (FILE *stream, const char *file)
+{
if (script_ext_mode != script_ext_off
&& strlen (file) > 3 && !strcmp (&file[strlen (file) - 3], ".py"))
{
if (script_ext_mode == script_ext_soft
&& e.reason == RETURN_ERROR && e.error == UNSUPPORTED_ERROR)
{
- if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups))
- return;
-
- script_from_file (stream, file);
+ fseek (stream, 0, SEEK_SET);
+ script_from_file (stream, (char*) file);
}
else
- /* Nope, just punt. */
- throw_exception (e);
+ {
+ /* Nope, just punt. */
+ fclose (stream);
+ throw_exception (e);
+ }
}
+ else
+ fclose (stream);
}
else
script_from_file (stream, file);
+}
+
+/* Worker to perform the "source" command.
+ Load script FILE.
+ If SEARCH_PATH is non-zero, and the file isn't found in cwd,
+ search for it in the source search path. */
+static void
+source_script_with_search (const char *file, int from_tty, int search_path)
+{
+ FILE *stream;
+ char *full_path;
+ struct cleanup *old_cleanups;
+
+ if (file == NULL || *file == 0)
+ error (_("source command requires file name of file to source."));
+
+ if (!find_and_open_script (file, search_path, &stream, &full_path))
+ {
+ /* The script wasn't found, or was otherwise inaccessible.
+ If the source command was invoked interactively, throw an error.
+ Otherwise (e.g. if it was invoked by a script), silently ignore
+ the error. */
+ if (from_tty)
+ perror_with_name (file);
+ else
+ return;
+ }
+
+ old_cleanups = make_cleanup (xfree, full_path);
+ source_script_from_stream (stream, file);
do_cleanups (old_cleanups);
}
+/* Wrapper around source_script_with_search to export it to main.c
+ for use in loading .gdbinit scripts. */
+
+void
+source_script (char *file, int from_tty)
+{
+ source_script_with_search (file, from_tty, 0);
+}
+
/* Return the source_verbose global variable to its previous state
on exit from the source command, by whatever means. */
static void
struct cleanup *old_cleanups;
char *file = args;
int *old_source_verbose = xmalloc (sizeof(int));
+ int search_path = 0;
*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.
+ -s causes the file to be searched in the source search path,
+ even if the file name contains a '/'.
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]))
+ while (args[0] != '\0')
{
- source_verbose = 1;
+ /* Make sure leading white space does not break the comparisons. */
+ while (isspace(args[0]))
+ args++;
+
+ if (args[0] != '-')
+ break;
+
+ if (args[1] == 'v' && isspace (args[2]))
+ {
+ source_verbose = 1;
+
+ /* Skip passed -v. */
+ args = &args[3];
+ }
+ else if (args[1] == 's' && isspace (args[2]))
+ {
+ search_path = 1;
- /* Trim -v and whitespace from the filename. */
- file = &args[3];
- while (isspace (file[0]))
- file++;
+ /* Skip passed -s. */
+ args = &args[3];
+ }
+ else
+ break;
}
+
+ while (isspace (args[0]))
+ args++;
+ file = args;
}
- source_script (file, from_tty);
+ source_script_with_search (file, from_tty, search_path);
do_cleanups (old_cleanups);
}
}
else
{
-
/* Now should only be one argument -- decode it in SAL. */
arg1 = arg;
if (*arg == '*')
{
struct gdbarch *gdbarch;
+
if (sal.symtab == 0)
/* FIXME-32x64--assumes sal.pc fits in long. */
error (_("No source file for address %s."),
if (*arg == '*')
{
struct gdbarch *gdbarch;
+
if (sal.symtab == 0)
/* FIXME-32x64--assumes sal.pc fits in long. */
error (_("No source file for address %s."),
- dump the assembly code for the function of the current pc
disassemble [/mr] addr
- dump the assembly code for the function at ADDR
- disassemble [/mr] low high
- - dump the assembly code in the range [LOW,HIGH)
+ disassemble [/mr] low,high
+ disassemble [/mr] low,+length
+ - dump the assembly code in the range [LOW,HIGH), or [LOW,LOW+length)
A /m modifier will include source code with the assembly.
A /r modifier will include raw instructions in hex with the assembly. */
struct gdbarch *gdbarch = get_current_arch ();
CORE_ADDR low, high;
char *name;
- CORE_ADDR pc, pc_masked;
+ CORE_ADDR pc;
int flags;
name = NULL;
else
{
/* Two arguments. */
+ int incl_flag = 0;
low = pc;
+ while (isspace (*arg))
+ arg++;
+ if (arg[0] == '+')
+ {
+ ++arg;
+ incl_flag = 1;
+ }
high = parse_and_eval_address (arg);
+ if (incl_flag)
+ high += low;
}
print_disassembly (gdbarch, name, low, high, flags);
if (args)
{
char *comname = args;
+
c = lookup_cmd (&comname, cmdlist, "", 0, 1);
if (c->class != class_user)
error (_("Not a user command."));
regex_t pattern;
char *pattern_fastmap;
char errorbuffer[512];
+
pattern_fastmap = xcalloc (256, sizeof (char));
if (searchstr == NULL)
error (_("REGEXP string is empty"));
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\
+\n\
+Usage: source [-s] [-v] FILE\n\
+-s: search for the script in the source search path,\n\
+ even if FILE contains directories.\n\
+-v: each command in FILE is echoed as it is executed.\n\
+\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,
With a /m modifier, source lines are included (if available).\n\
With a /r modifier, raw instructions in hex are included.\n\
With a single argument, the function surrounding that address is dumped.\n\
-Two arguments (separated by a comma) are taken as a range of memory to dump."));
+Two arguments (separated by a comma) are taken as a range of memory to dump,\n\
+ in the form of \"start,end\", or \"start,+length\"."));
set_cmd_completer (c, location_completer);
if (xdb_commands)
add_com_alias ("va", "disassemble", class_xdb, 0);