#include <ctype.h>
#include "defs.h"
#include "gdb_string.h"
#include "gdbcmd.h"
#include "target.h"
#include "serial.h"
#include "gdbcore.h"
#include "inferior.h"
#include "remote-utils.h"
#include "regcache.h"
void _initialize_sr_support (void);
struct _sr_settings sr_settings =
{
4,
10,
NULL,
NULL,
};
struct gr_settings *gr_settings = NULL;
static void usage (char *, char *);
static void sr_com (char *, int);
static void
usage (char *proto, char *junk)
{
if (junk != NULL)
fprintf_unfiltered (gdb_stderr, "Unrecognized arguments: `%s'.\n", junk);
error ("Usage: target %s [DEVICE [SPEED [DEBUG]]]\n\
where DEVICE is the name of a device or HOST:PORT", proto);
return;
}
#define CHECKDONE(p, q) \
{ \
if (q == p) \
{ \
if (*p == '\0') \
return; \
else \
usage(proto, p); \
} \
}
void
sr_scan_args (char *proto, char *args)
{
int n;
char *p, *q;
if (args == NULL || *args == '\0')
return;
for (p = args; isspace (*p); ++p);;
for (q = p; *q != '\0' && !isspace (*q); ++q);;
CHECKDONE (p, q);
sr_set_device (savestring (p, q - p));
n = strtol (q, &p, 10);
CHECKDONE (p, q);
baud_rate = n;
n = strtol (p, &q, 10);
CHECKDONE (p, q);
sr_set_debug (n);
for (p = q; isspace (*p); ++p);;
if (*p != '\0')
usage (proto, p);
return;
}
void
gr_generic_checkin (void)
{
sr_write_cr ("");
gr_expect_prompt ();
}
void
gr_open (char *args, int from_tty, struct gr_settings *gr)
{
target_preopen (from_tty);
sr_scan_args (gr->ops->to_shortname, args);
unpush_target (gr->ops);
gr_settings = gr;
if (sr_get_desc () != NULL)
gr_close (0);
if (sr_get_device () == NULL)
usage (gr->ops->to_shortname, NULL);
sr_set_desc (serial_open (sr_get_device ()));
if (!sr_get_desc ())
perror_with_name ((char *) sr_get_device ());
if (baud_rate != -1)
{
if (serial_setbaudrate (sr_get_desc (), baud_rate) != 0)
{
serial_close (sr_get_desc ());
perror_with_name (sr_get_device ());
}
}
serial_raw (sr_get_desc ());
serial_flush_input (sr_get_desc ());
if (sr_get_retries () == 0)
sr_set_retries (1);
if (gr_settings->clear_all_breakpoints == NULL)
gr_settings->clear_all_breakpoints = remove_breakpoints;
if (from_tty)
{
printf_filtered ("Remote debugging using `%s'", sr_get_device ());
if (baud_rate != -1)
printf_filtered (" at baud rate of %d",
baud_rate);
printf_filtered ("\n");
}
push_target (gr->ops);
gr_checkin ();
gr_clear_all_breakpoints ();
return;
}
int
sr_readchar (void)
{
int buf;
buf = serial_readchar (sr_get_desc (), sr_get_timeout ());
if (buf == SERIAL_TIMEOUT)
error ("Timeout reading from remote system.");
if (sr_get_debug () > 0)
printf_unfiltered ("%c", buf);
return buf & 0x7f;
}
int
sr_pollchar (void)
{
int buf;
buf = serial_readchar (sr_get_desc (), 0);
if (buf == SERIAL_TIMEOUT)
buf = 0;
if (sr_get_debug () > 0)
{
if (buf)
printf_unfiltered ("%c", buf);
else
printf_unfiltered ("<empty character poll>");
}
return buf & 0x7f;
}
void
sr_expect (char *string)
{
char *p = string;
immediate_quit++;
while (1)
{
if (sr_readchar () == *p)
{
p++;
if (*p == '\0')
{
immediate_quit--;
return;
}
}
else
p = string;
}
}
void
sr_write (char *a, int l)
{
int i;
if (serial_write (sr_get_desc (), a, l) != 0)
perror_with_name ("sr_write: Error writing to remote");
if (sr_get_debug () > 0)
for (i = 0; i < l; i++)
printf_unfiltered ("%c", a[i]);
return;
}
void
sr_write_cr (char *s)
{
sr_write (s, strlen (s));
sr_write ("\r", 1);
return;
}
int
sr_timed_read (char *buf, int n)
{
int i;
char c;
i = 0;
while (i < n)
{
c = sr_readchar ();
if (c == 0)
return i;
buf[i] = c;
i++;
}
return i;
}
int
sr_get_hex_digit (int ignore_space)
{
int ch;
while (1)
{
ch = sr_readchar ();
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch != ' ' || !ignore_space)
{
gr_expect_prompt ();
error ("Invalid hex digit from remote system.");
}
}
}
void
sr_get_hex_byte (char *byt)
{
int val;
val = sr_get_hex_digit (1) << 4;
val |= sr_get_hex_digit (0);
*byt = val;
}
long
sr_get_hex_word (void)
{
long val;
int j;
val = 0;
for (j = 0; j < 8; j++)
val = (val << 4) + sr_get_hex_digit (j == 0);
return val;
}
static void
sr_com (char *args, int fromtty)
{
sr_check_open ();
if (!args)
return;
sr_write_cr (args);
sr_write ("\030", 1);
registers_changed ();
gr_expect_prompt ();
}
void
gr_close (int quitting)
{
gr_clear_all_breakpoints ();
if (sr_is_open ())
{
serial_close (sr_get_desc ());
sr_set_desc (NULL);
}
return;
}
void
gr_detach (char *args, int from_tty)
{
if (args)
error ("Argument given to \"detach\" when remotely debugging.");
if (sr_is_open ())
gr_clear_all_breakpoints ();
pop_target ();
if (from_tty)
puts_filtered ("Ending remote debugging.\n");
return;
}
void
gr_files_info (struct target_ops *ops)
{
#ifdef __GO32__
printf_filtered ("\tAttached to DOS asynctsr\n");
#else
printf_filtered ("\tAttached to %s", sr_get_device ());
if (baud_rate != -1)
printf_filtered ("at %d baud", baud_rate);
printf_filtered ("\n");
#endif
if (exec_bfd)
{
printf_filtered ("\tand running program %s\n",
bfd_get_filename (exec_bfd));
}
printf_filtered ("\tusing the %s protocol.\n", ops->to_shortname);
}
void
gr_mourn (void)
{
gr_clear_all_breakpoints ();
unpush_target (gr_get_ops ());
generic_mourn_inferior ();
}
void
gr_kill (void)
{
return;
}
void
gr_create_inferior (char *execfile, char *args, char **env)
{
int entry_pt;
if (args && *args)
error ("Can't pass arguments to remote process.");
if (execfile == 0 || exec_bfd == 0)
error ("No executable file specified");
entry_pt = (int) bfd_get_start_address (exec_bfd);
sr_check_open ();
gr_kill ();
gr_clear_all_breakpoints ();
init_wait_for_inferior ();
gr_checkin ();
insert_breakpoints ();
proceed (entry_pt, -1, 0);
}
int
gr_multi_scan (char *list[], int passthrough)
{
char *swallowed = NULL;
char *swallowed_p = swallowed;
int ch;
int ch_handled;
int i;
int string_count;
int max_length;
char **plist;
for (max_length = string_count = i = 0;
list[i] != NULL;
++i, ++string_count)
{
int length = strlen (list[i]);
if (length > max_length)
max_length = length;
}
if (string_count == 0)
return (-1);
swallowed_p = swallowed = alloca (max_length << 1);
plist = (char **) alloca (string_count * sizeof (*plist));
for (i = 0; i < string_count; ++i)
plist[i] = list[i];
for (ch = sr_readchar (); ; ch = sr_readchar ())
{
QUIT;
ch_handled = 0;
for (i = 0; i < string_count; ++i)
{
if (ch == *plist[i] || *plist[i] == '?')
{
++plist[i];
if (*plist[i] == '\0')
return (i);
if (!ch_handled)
*swallowed_p++ = ch;
ch_handled = 1;
}
else
plist[i] = list[i];
}
if (!ch_handled)
{
char *p;
if (passthrough)
{
for (p = swallowed; p < swallowed_p; ++p)
fputc_unfiltered (*p, gdb_stdout);
fputc_unfiltered (ch, gdb_stdout);
}
swallowed_p = swallowed;
}
}
#if 0
return (-1);
#endif
}
void
gr_prepare_to_store (void)
{
}
void
_initialize_sr_support (void)
{
add_show_from_set (add_set_cmd ("remotedevice", no_class,
var_filename, (char *) &sr_settings.device,
"Set device for remote serial I/O.\n\
This device is used as the serial port when debugging using remote\n\
targets.", &setlist),
&showlist);
add_com ("remote <command>", class_obscure, sr_com,
"Send a command to the remote monitor.");
}