/* Top level stuff for GDB, the GNU debugger.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdbcmd.h"
#undef savestring
#include <sys/types.h>
-#ifdef USG
-/* What is this for? X_OK? */
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#include <string.h>
+#include "gdb_string.h"
#ifndef NO_SYS_FILE
#include <sys/file.h>
#endif
#include <sys/param.h>
-#include <sys/stat.h>
+#include "gdb_stat.h"
#include <ctype.h>
+extern void initialize_targets PARAMS ((void));
+
+extern void initialize_utils PARAMS ((void));
+
/* Prototypes for local functions */
static char * line_completion_function PARAMS ((char *, int, char *, int));
#define GDBINIT_FILENAME ".gdbinit"
#endif
char gdbinit[] = GDBINIT_FILENAME;
+
int inhibit_gdbinit = 0;
-/* Disable windows if non-zero */
+/* If nonzero, and GDB has been configured to be able to use windows,
+ attempt to open them upon startup. */
-int use_windows = 1; /* Defaults to on for now */
+int use_windows = 1;
/* Version number of GDB, as a string. */
int caution = 1; /* Default is yes, sigh. */
-/*
- * Define all cmd_list_element's
- */
+/* Define all cmd_list_elements. */
/* Chain containing all defined commands. */
/* stdio stream that command input is being read from. Set to stdin normally.
Set by source_command to the file we are sourcing. Set to NULL if we are
- executing a user-defined command. */
+ executing a user-defined command or interacting via a GUI. */
FILE *instream;
int baud_rate = -1;
+/* Timeout limit for response from target. */
+
+int remote_timeout = 20; /* Set default to 20 */
+
/* Non-zero tells remote* modules to output debugging info. */
int remote_debug = 0;
void (*command_loop_hook) PARAMS ((void));
+
/* Called instead of fputs for all output. */
void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream));
+/* Called when the target says something to the host, which may
+ want to appear in a different window. */
+
+void (*target_output_hook) PARAMS ((char *));
+
/* Called from print_frame_info to list the line we stopped in. */
void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line,
void (*flush_hook) PARAMS ((FILE *stream));
+/* These three functions support getting lines of text from the user. They
+ are used in sequence. First readline_begin_hook is called with a text
+ string that might be (for example) a message for the user to type in a
+ sequence of commands to be executed at a breakpoint. If this function
+ calls back to a GUI, it might take this opportunity to pop up a text
+ interaction window with this message. Next, readline_hook is called
+ with a prompt that is emitted prior to collecting the user input.
+ It can be called multiple times. Finally, readline_end_hook is called
+ to notify the GUI that we are done with the interaction window and it
+ can close it. */
+
+void (*readline_begin_hook) PARAMS ((char *, ...));
+char * (*readline_hook) PARAMS ((char *));
+void (*readline_end_hook) PARAMS ((void));
+
/* Called as appropriate to notify the interface of the specified breakpoint
conditions. */
void (*create_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
-void (*enable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
-void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
/* Called during long calculations to allow GUI to repair window damage, and to
check for stop buttons, etc... */
void (*interactive_hook) PARAMS ((void));
+/* Called when the registers have changed, as a hint to a GUI
+ to minimize window update. */
+
+void (*registers_changed_hook) PARAMS ((void));
+
/* Called when going to wait for the target. Usually allows the GUI to run
while waiting for target events. */
void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
int from_tty));
-/* An alternate way to read memory for disassembly. This is used to provide a
- switch that allows disassembly to come from an exec file rather than a
- remote target. This is a speed hack. */
-int (*dis_asm_read_memory_hook) PARAMS ((bfd_vma memaddr, bfd_byte *myaddr,
- int len, disassemble_info *info));
/* Takes control from error (). Typically used to prevent longjmps out of the
middle of the GUI. Usually used in conjunction with a catch routine. */
-NORETURN void (*error_hook) PARAMS (());
+NORETURN void (*error_hook) PARAMS (()) ATTR_NORETURN;
\f
/* Where to go for return_to_top_level (RETURN_ERROR). */
int val;
struct cleanup *saved_cleanup_chain;
char *saved_error_pre_print;
+ char *saved_quit_pre_print;
saved_cleanup_chain = save_cleanups ();
saved_error_pre_print = error_pre_print;
+ saved_quit_pre_print = quit_pre_print;
if (mask & RETURN_MASK_ERROR)
- memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf));
+ {
+ memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf));
+ error_pre_print = errstring;
+ }
if (mask & RETURN_MASK_QUIT)
- memcpy (saved_quit, quit_return, sizeof (jmp_buf));
- error_pre_print = errstring;
+ {
+ memcpy (saved_quit, quit_return, sizeof (jmp_buf));
+ quit_pre_print = errstring;
+ }
if (setjmp (tmp_jmp) == 0)
{
restore_cleanups (saved_cleanup_chain);
- error_pre_print = saved_error_pre_print;
if (mask & RETURN_MASK_ERROR)
- memcpy (error_return, saved_error, sizeof (jmp_buf));
+ {
+ memcpy (error_return, saved_error, sizeof (jmp_buf));
+ error_pre_print = saved_error_pre_print;
+ }
if (mask & RETURN_MASK_QUIT)
- memcpy (quit_return, saved_quit, sizeof (jmp_buf));
+ {
+ memcpy (quit_return, saved_quit, sizeof (jmp_buf));
+ quit_pre_print = saved_quit_pre_print;
+ }
return val;
}
{
struct command_line *cmd;
+ if (args == NULL)
+ error ("if/while commands require arguments.\n");
+
cmd = (struct command_line *)xmalloc (sizeof (struct command_line));
cmd->next = NULL;
cmd->control_type = type;
make_cleanup (free_current_contents, &expr);
ret = simple_control;
- loop = true;
+ loop = 1;
/* Keep iterating so long as the expression is true. */
- while (loop == true)
+ while (loop == 1)
{
+ QUIT;
+
/* Evaluate the expression. */
val = evaluate_expression (expr);
looping. */
if (ret == invalid_control || ret == break_control)
{
- loop = false;
+ loop = 0;
break;
}
locate_arg (p)
char *p;
{
- while (p = strchr (p, '$'))
+ while ((p = strchr (p, '$')))
{
if (strncmp (p, "$arg", 4) == 0 && isdigit (p[4]))
return p;
/* First we need to know how much memory to allocate for the new line. */
save_line = line;
len = 0;
- while (p = locate_arg (line))
+ while ((p = locate_arg (line)))
{
len += p - line;
i = p[4] - '0';
/* Save pointer to beginning of new line. */
save_line = new_line;
- while (p = locate_arg (line))
+ while ((p = locate_arg (line)))
{
int i, len;
new_line += p - line;
i = p[4] - '0';
- if (len = user_args->a[i].len)
+ len = user_args->a[i].len;
+ if (len)
{
memcpy (new_line, user_args->a[i].arg, len);
new_line += len;
register struct cmd_list_element *c;
register enum language flang;
static int warned = 0;
+ extern FILE *serial_logfp;
free_all_values ();
if (p == NULL)
return;
+ if (serial_logfp != NULL)
+ serial_log_command (p);
+
while (*p == ' ' || *p == '\t') p++;
if (*p)
{
/* Pass null arg rather than an empty one. */
arg = *p ? p : 0;
+ /* Clear off trailing whitespace, except for set and complete command. */
+ if (arg && c->type != set_cmd && c->function.cfunc != complete_command)
+ {
+ p = arg + strlen (arg) - 1;
+ while (p >= arg && (*p == ' ' || *p == '\t'))
+ p--;
+ *(p + 1) = '\0';
+ }
+
/* If this command has been hooked, run the hook first. */
if (c->hook)
execute_user_command (c->hook, (char *)0);
char *command;
int stdin_is_tty = ISATTY (stdin);
long time_at_cmd_start;
+#ifdef HAVE_SBRK
long space_at_cmd_start;
+#endif
extern int display_time;
extern int display_space;
- while (!feof (instream))
+ while (instream && !feof (instream))
{
if (window_hook && instream == stdin)
(*window_hook) (instream, prompt);
if (display_space)
{
+#ifdef HAVE_SBRK
extern char **environ;
char *lim = (char *) sbrk (0);
space_at_cmd_start = (long) (lim - (char *) &environ);
+#endif
}
execute_command (command, instream == stdin);
if (display_space)
{
+#ifdef HAVE_SBRK
extern char **environ;
char *lim = (char *) sbrk (0);
long space_now = lim - (char *) &environ;
space_now,
(space_diff >= 0 ? '+' : '-'),
space_diff);
+#endif
}
}
}
character position to be off, since the newline we read from
the user is not accounted for. */
fputs_unfiltered (prrompt, gdb_stdout);
-/* start-sanitize-mpw */
#ifdef MPW
/* Move to a new line so the entered line doesn't have a prompt
on the front of it. */
fputs_unfiltered ("\n", gdb_stdout);
#endif /* MPW */
-/* end-sanitize-mpw */
gdb_flush (gdb_stdout);
}
rl_completer_word_break_characters =
gdb_completer_command_word_break_characters;
}
+ else if (c->enums)
+ {
+ list = complete_on_enum (c->enums, p, word);
+ rl_completer_word_break_characters =
+ gdb_completer_command_word_break_characters;
+ }
else
{
/* It is a normal command; what comes after it is
e.g. "info adsfkdj". */
list = NULL;
}
+ else if (c->enums)
+ {
+ list = complete_on_enum (c->enums, p, word);
+ }
else
{
/* It is a normal command. */
{
signal (SIGINT, request_quit);
+ /* If SIGTRAP was set to SIG_IGN, then the SIG_IGN will get passed
+ to the inferior and breakpoints will be ignored. */
+#ifdef SIGTRAP
+ signal (SIGTRAP, SIG_DFL);
+#endif
+
/* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get
passed to the inferior, which we don't want. It would be
possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but
char *p1;
char *rl;
char *local_prompt = prrompt;
- register int c;
char *nline;
char got_eof = 0;
}
/* Don't use fancy stuff if not talking to stdin. */
- if (command_editing_p && instream == stdin
- && ISATTY (instream))
- rl = readline (local_prompt);
+ if (readline_hook && instream == NULL)
+ {
+ rl = (*readline_hook) (local_prompt);
+ }
+ else if (command_editing_p && instream == stdin && ISATTY (instream))
+ {
+ rl = readline (local_prompt);
+ }
else
- rl = gdb_readline (local_prompt);
+ {
+ rl = gdb_readline (local_prompt);
+ }
if (annotation_level > 1 && instream == stdin)
{
/* If we just got an empty line, and that is supposed
to repeat the previous command, return the value in the
global buffer. */
- if (repeat)
- {
- if (p == linebuffer)
- return line;
- p1 = linebuffer;
- while (*p1 == ' ' || *p1 == '\t')
- p1++;
- if (!*p1)
- return line;
- }
+ if (repeat && p == linebuffer)
+ return line;
+ for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++) ;
+ if (repeat && !*p1)
+ return line;
*p = 0;
out the command and then later fetch it from the value history
and remove the '#'. The kill ring is probably better, but some
people are in the habit of commenting things out. */
- p1 = linebuffer;
- while ((c = *p1++) != '\0')
- {
- if (c == '"')
- while ((c = *p1++) != '"')
- {
- /* Make sure an escaped '"' doesn't make us think the string
- is ended. */
- if (c == '\\')
- parse_escape (&p1);
- if (c == '\0')
- break;
- }
- else if (c == '\'')
- while ((c = *p1++) != '\'')
- {
- /* Make sure an escaped '\'' doesn't make us think the string
- is ended. */
- if (c == '\\')
- parse_escape (&p1);
- if (c == '\0')
- break;
- }
- else if (c == '#')
- {
- /* Found a comment. */
- p1[-1] = '\0';
- break;
- }
- }
+ if (*p1 == '#')
+ *p1 = '\0'; /* Found a comment. */
/* Save into global buffer if appropriate. */
if (repeat)
error ("Control nesting too deep!\n");
/* Set a prompt based on the nesting of the control commands. */
- if (instream == stdin)
+ if (instream == stdin || (instream == 0 && readline_hook != NULL))
{
for (i = 0; i < control_level; i++)
control_prompt[i] = ' ';
*command = build_command_line (while_control, p + 6);
else if (p1 - p > 2 && !strncmp (p, "if", 2))
*command = build_command_line (if_control, p + 3);
- else if (p1 - p == 5 && !strncmp (p, "loop_break", 5))
+ else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
xmalloc (sizeof (struct command_line));
(*command)->body_count = 0;
(*command)->body_list = NULL;
}
- else if (p1 - p == 8 && !strncmp (p, "loop_continue", 8))
+ else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13))
{
*command = (struct command_line *)
xmalloc (sizeof (struct command_line));
}
/* Recursively read in the control structures and create a command_line
- tructure from them.
+ structure from them.
The parent_control parameter is the control structure in which the
following commands are nested. */
enum misc_command_type val;
enum command_control_type ret;
struct command_line **body_ptr, *child_tail, *next;
- struct cleanup *old_chains, *tmp_chains;
- old_chains = NULL;
child_tail = NULL;
current_body = 1;
}
else
{
- /* We have just read the first line of the child's control
- structure. From now on, arrange to throw away the line
- we have if we quit or get an error. */
body_ptr = current_cmd->body_list;
for (i = 1; i < current_body; i++)
body_ptr++;
*body_ptr = next;
- tmp_chains = make_cleanup (free_command_lines, body_ptr);
-
- if (!old_chains)
- old_chains = tmp_chains;
}
child_tail = next;
}
dont_repeat ();
- if (ret == invalid_control && old_chains)
- do_cleanups (old_chains);
- else if (old_chains)
- discard_cleanups (old_chains);
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. */
-/* Read lines from the input stream
- and accumulate them in a chain of struct command_line's
- which is then returned. */
+#define END_MESSAGE "End with a line saying just \"end\"."
struct command_line *
-read_command_lines ()
+read_command_lines (prompt, from_tty)
+char *prompt;
+int from_tty;
{
struct command_line *head, *tail, *next;
struct cleanup *old_chain;
enum command_control_type ret;
enum misc_command_type val;
+ if (readline_begin_hook)
+ {
+ /* Note - intentional to merge messages with no newline */
+ (*readline_begin_hook) ("%s %s\n", prompt, END_MESSAGE);
+ }
+ else if (from_tty && input_from_terminal_p ())
+ {
+ printf_unfiltered ("%s\n%s\n", prompt, END_MESSAGE);
+ gdb_flush (gdb_stdout);
+ }
+
head = tail = NULL;
old_chain = NULL;
if (ret != invalid_control)
{
discard_cleanups (old_chain);
- return head;
}
else
do_cleanups (old_chain);
}
- return NULL;
+ if (readline_end_hook)
+ {
+ (*readline_end_hook) ();
+ }
+ return (head);
}
/* Free a chain of struct command_line's. */
p = comname;
while (*p)
{
- if (!isalnum(*p) && *p != '-')
+ if (!isalnum(*p) && *p != '-' && *p != '_')
error ("Junk in argument list: \"%s\"", p);
p++;
}
register struct command_line *cmds;
register struct cmd_list_element *c, *newc, *hookc = 0;
char *tem = comname;
+ char tmpbuf[128];
#define HOOK_STRING "hook-"
#define HOOK_LEN 5
{
warning ("Your new `%s' command does not hook any existing command.",
comname);
- if (!query ("Proceed? ", (char *)0))
+ if (!query ("Proceed? "))
error ("Not confirmed.");
}
}
for (tem = comname; *tem; tem++)
if (isupper(*tem)) *tem = tolower(*tem);
- if (from_tty)
- {
- printf_unfiltered ("Type commands for definition of \"%s\".\n\
-End with a line saying just \"end\".\n", comname);
- gdb_flush (gdb_stdout);
- }
-
control_level = 0;
- cmds = read_command_lines ();
+ 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);
struct command_line *doclines;
register struct cmd_list_element *c;
char *tem = comname;
+ char tmpbuf[128];
validate_comname (comname);
if (c->class != class_user)
error ("Command \"%s\" is built-in.", comname);
- if (from_tty)
- printf_unfiltered ("Type documentation for \"%s\".\n\
-End with a line saying just \"end\".\n", comname);
-
- doclines = read_command_lines ();
+ sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
+ doclines = read_command_lines (tmpbuf, from_tty);
if (c->doc) free (c->doc);
fprintf_filtered (stream, "), ");
wrap_here("");
- fprintf_filtered (stream, "Copyright 1994 Free Software Foundation, Inc.");
+ fprintf_filtered (stream, "Copyright 1996 Free Software Foundation, Inc.");
}
/* ARGSUSED */
char *args;
int from_tty;
{
+ int exit_code = 0;
+
+ /* An optional expression may be used to cause gdb to terminate with the
+ value of that expression. */
+ if (args)
+ {
+ value_ptr val = parse_and_eval (args);
+
+ exit_code = (int) value_as_long (val);
+ }
+
if (inferior_pid != 0 && target_has_execution)
{
if (attach_flag)
if (write_history_p && history_filename)
write_history (history_filename);
- exit (0);
+ exit (exit_code);
}
/* Returns whether GDB is running on a terminal and whether the user
perror_with_name (dir);
len = strlen (dir);
- dir = savestring (dir, len - (len > 1 && dir[len-1] == '/'));
- if (dir[0] == '/')
+ dir = savestring (dir, len - (len > 1 && SLASH_P(dir[len-1])));
+ if (ROOTED_P(dir))
current_directory = dir;
else
{
- if (current_directory[0] == '/' && current_directory[1] == '\0')
+ if (SLASH_P (current_directory[0]) && current_directory[1] == '\0')
current_directory = concat (current_directory, dir, NULL);
else
- current_directory = concat (current_directory, "/", dir, NULL);
+ current_directory = concat (current_directory, SLASH_STRING, dir, NULL);
free (dir);
}
found_real_path = 0;
for (p = current_directory; *p;)
{
- if (p[0] == '/' && p[1] == '.' && (p[2] == 0 || p[2] == '/'))
+ if (SLASH_P (p[0]) && p[1] == '.' && (p[2] == 0 || SLASH_P (p[2])))
strcpy (p, p + 2);
- else if (p[0] == '/' && p[1] == '.' && p[2] == '.'
- && (p[3] == 0 || p[3] == '/'))
+ else if (SLASH_P (p[0]) && p[1] == '.' && p[2] == '.'
+ && (p[3] == 0 || SLASH_P (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 && q[-1] != '/')
+ while (q != current_directory && ! SLASH_P (q[-1]))
--q;
if (q == current_directory)
gdb_flush (gdb_stdout);
}
+/* ARGSUSED */
+static void
+dont_repeat_command (ignored, from_tty)
+ char *ignored;
+ int from_tty;
+{
+ *line = 0; /* Can't call dont_repeat here because we're not
+ necessarily reading from stdin. */
+}
\f
#ifdef TARGET_BYTE_ORDER_SELECTABLE
(target_byte_order_auto
? "The target endianness is set automatically (currently %s endian)\n"
: "The target is assumed to be %s endian\n");
- printf_unfiltered (msg, TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
+ printf_unfiltered ((char *) msg, TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
}
#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
#ifdef TARGET_BYTE_ORDER_SELECTABLE
int want;
- if (abfd->xvec->byteorder_big_p)
+ if (bfd_big_endian (abfd))
want = BIG_ENDIAN;
else
want = LITTLE_ENDIAN;
#else /* ! defined (TARGET_BYTE_ORDER_SELECTABLE) */
- if (abfd->xvec->byteorder_big_p
+ if (bfd_big_endian (abfd)
? TARGET_BYTE_ORDER != BIG_ENDIAN
: TARGET_BYTE_ORDER == BIG_ENDIAN)
warning ("%s endian file does not match %s endian target.",
- abfd->xvec->byteorder_big_p ? "big" : "little",
+ bfd_big_endian (abfd) ? "big" : "little",
TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
#endif /* ! defined (TARGET_BYTE_ORDER_SELECTABLE) */
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 do not take arguments.");
+Commands defined in this way may have up to ten arguments.");
#ifdef __STDC__
c = add_cmd ("source", class_support, source_command,
add_com_alias ("q", "quit", class_support, 1);
add_com_alias ("h", "help", class_support, 1);
+ add_com ("dont-repeat", class_support, dont_repeat_command, "Don't repeat this command.\n\
+Primarily used inside of user-defined commands that should not be repeated when\n\
+hitting return.");
c = add_set_cmd ("verbose", class_support, var_boolean, (char *)&info_verbose,
"Set ",
add_info ("set", show_command, "Show all GDB settings.");
add_cmd ("commands", no_class, show_commands,
- "Show the the history of commands you typed.\n\
+ "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_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\
-followed by a new line. The nested commands must be entered one per line,\
+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\
-followed by a new line. The nested commands must be entered one per line,\
-and should be terminated by the word 'else' or `end'. If an else clause\
+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
When enabled, each packet sent or received with the remote target\n\
is displayed.", &setlist),
&showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotetimeout", no_class, var_integer, (char *)&remote_timeout,
+ "Set timeout limit to wait for target to respond.\n\
+This value is used to set the time limit for gdb to wait for a response\n\
+from he target.", &setlist),
+ &showlist);
}