Пример #1
0
static void
gdbsim_load (char *args, int fromtty)
{
  char **argv;
  char *prog;

  if (args == NULL)
      error_no_arg (_("program to load"));

  argv = gdb_buildargv (args);
  make_cleanup_freeargv (argv);

  prog = tilde_expand (argv[0]);

  if (argv[1] != NULL)
    error (_("GDB sim does not yet support a load offset."));

  if (remote_debug)
    printf_filtered ("gdbsim_load: prog \"%s\"\n", prog);

  /* FIXME: We will print two messages on error.
     Need error to either not print anything if passed NULL or need
     another routine that doesn't take any arguments.  */
  if (sim_load (gdbsim_desc, prog, NULL, fromtty) == SIM_RC_FAIL)
    error (_("unable to load program"));

  /* FIXME: If a load command should reset the targets registers then
     a call to sim_create_inferior() should go here. */

  program_loaded = 1;
}
Пример #2
0
static void
kgdb_set_proc_cmd (char *arg, int from_tty)
{
	CORE_ADDR addr;
	struct kthr *thr;

	if (!arg)
		error_no_arg ("proc address for the new context");

	if (kvm == NULL)
		error ("only supported for core file target");

	addr = (CORE_ADDR) parse_and_eval_address (arg);

	if (!INKERNEL (addr)) {
		thr = kgdb_thr_lookup_pid((int)addr);
		if (thr == NULL)
			error ("invalid pid");
	} else {
		thr = kgdb_thr_lookup_paddr(addr);
		if (thr == NULL)
			error("invalid proc address");
	}
	kgdb_switch_to_thread(thr->tid);
}
Пример #3
0
static void
trace_save_command (char *args, int from_tty)
{
  int target_does_save = 0;
  char **argv;
  char *filename = NULL;
  struct cleanup *back_to;
  int generate_ctf = 0;
  struct trace_file_writer *writer = NULL;

  if (args == NULL)
    error_no_arg (_("file in which to save trace data"));

  argv = gdb_buildargv (args);
  back_to = make_cleanup_freeargv (argv);

  for (; *argv; ++argv)
    {
      if (strcmp (*argv, "-r") == 0)
	target_does_save = 1;
      if (strcmp (*argv, "-ctf") == 0)
	generate_ctf = 1;
      else if (**argv == '-')
	error (_("unknown option `%s'"), *argv);
      else
	filename = *argv;
    }

  if (!filename)
    error_no_arg (_("file in which to save trace data"));

  if (generate_ctf)
    writer = ctf_trace_file_writer_new ();
  else
    writer = tfile_trace_file_writer_new ();

  make_cleanup (trace_file_writer_xfree, writer);

  trace_save (filename, writer, target_does_save);

  if (from_tty)
    printf_filtered (_("Trace data saved to %s '%s'.\n"),
		     generate_ctf ? "directory" : "file", filename);

  do_cleanups (back_to);
}
Пример #4
0
static void
dt_command (char *arg, int from_tty)
{
	char* type_or_expr;

	if (!arg)
		error_no_arg (_("type or variable name"));
	type_or_expr = strdup(arg);
	print_type_layout (type_or_expr);
	free (type_or_expr);
}
Пример #5
0
static void
inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
{
  char *exec_file;
  pid_t pid;
  char *dummy;
  struct inferior *inf;

  if (!args)
    error_no_arg (_("process-id to attach"));

  dummy = args;
  pid = strtol (args, &dummy, 0);
  /* Some targets don't set errno on errors, grrr!  */
  if (pid == 0 && args == dummy)
    error (_("Illegal process-id: %s."), args);

  if (pid == getpid ())		/* Trying to m********e?  */
    error (_("I refuse to debug myself!"));

  if (from_tty)
    {
      exec_file = get_exec_file (0);

      if (exec_file)
	printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
			   target_pid_to_str (pid_to_ptid (pid)));
      else
	printf_unfiltered (_("Attaching to %s\n"),
			   target_pid_to_str (pid_to_ptid (pid)));

      gdb_flush (gdb_stdout);
    }

#ifdef PT_ATTACH
  errno = 0;
  ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
  if (errno != 0)
    perror_with_name (("ptrace"));
#else
  error (_("This system does not support attaching to a process"));
#endif

  inferior_ptid = pid_to_ptid (pid);

  inf = add_inferior (pid);
  inf->attach_flag = 1;

  /* Always add a main thread.  If some target extends the ptrace
     target, it should decorate the ptid later with more info.  */
  add_thread_silent (inferior_ptid);

  push_target(ops);
}
Пример #6
0
static void
inf_ptrace_attach (char *args, int from_tty)
{
  char *exec_file;
  pid_t pid;
  char *dummy;

  if (!args)
    error_no_arg (_("process-id to attach"));

  dummy = args;
  pid = strtol (args, &dummy, 0);
  /* Some targets don't set errno on errors, grrr!  */
  if (pid == 0 && args == dummy)
    error (_("Illegal process-id: %s."), args);

  if (pid == getpid ())		/* Trying to m********e?  */
    error (_("I refuse to debug myself!"));

  if (from_tty)
    {
      exec_file = get_exec_file (0);

      if (exec_file)
	printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
			   target_pid_to_str (pid_to_ptid (pid)));
      else
	printf_unfiltered (_("Attaching to %s\n"),
			   target_pid_to_str (pid_to_ptid (pid)));

      gdb_flush (gdb_stdout);
    }

#ifdef PT_ATTACH
  errno = 0;
  ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
  if (errno != 0)
    perror_with_name (("ptrace"));
  attach_flag = 1;
#else
  error (_("This system does not support attaching to a process"));
#endif

  inferior_ptid = pid_to_ptid (pid);
  push_target (ptrace_ops_hack);

  /* Do this first, before anything has had a chance to query the
     inferior's symbol table or similar.  */
  observer_notify_inferior_created (&current_target, from_tty);
}
Пример #7
0
static void
child_attach_to_process (char *args, int from_tty, int after_fork)
{
  if (!args)
    error_no_arg ("process-id to attach");

#ifndef ATTACH_DETACH
  error ("Can't attach to a process on this machine.");
#else
  {
    char *exec_file;
    int pid;
    char *dummy;

    dummy = args;
    pid = strtol (args, &dummy, 0);
    /* Some targets don't set errno on errors, grrr! */
    if ((pid == 0) && (args == dummy))
      error ("Illegal process-id: %s\n", args);

    if (pid == getpid ())	/* Trying to m********e? */
      error ("I refuse to debug myself!");

    if (from_tty)
      {
	exec_file = (char *) get_exec_file (0);

	if (after_fork)
	  printf_unfiltered ("Attaching after fork to %s\n",
			     target_pid_to_str (pid_to_ptid (pid)));
	else if (exec_file)
	  printf_unfiltered ("Attaching to program: %s, %s\n", exec_file,
			     target_pid_to_str (pid_to_ptid (pid)));
	else
	  printf_unfiltered ("Attaching to %s\n", 
	                     target_pid_to_str (pid_to_ptid (pid)));

	gdb_flush (gdb_stdout);
      }

    if (!after_fork)
      attach (pid);
    else
      REQUIRE_ATTACH (pid);

    inferior_ptid = pid_to_ptid (pid);
    push_target (&child_ops);
  }
#endif /* ATTACH_DETACH */
}
Пример #8
0
static void
obj_command (char *arg, int from_tty)
{
	struct cleanup *old_chain;

	if (!arg)
		error_no_arg (_("type or variable name"));

	/* We depend on typed segments */
	if (!update_memory_segments_and_heaps())
		return;

	old_chain = make_cleanup_restore_current_thread ();
	search_cplusplus_objects_and_references(arg, CA_FALSE);
	// remember to resume the current thread/frame
	do_cleanups (old_chain);
}
Пример #9
0
static void
kgdb_set_tid_cmd (char *arg, int from_tty)
{
	CORE_ADDR addr;
	struct kthr *thr;

	if (!arg)
		error_no_arg ("TID or thread address for the new context");

	addr = (CORE_ADDR) parse_and_eval_address (arg);

	if (kvm != NULL && INKERNEL (addr)) {
		thr = kgdb_thr_lookup_taddr(addr);
		if (thr == NULL)
			error("invalid thread address");
		addr = thr->tid;
	}
	kgdb_switch_to_thread(addr);
}
Пример #10
0
static void
child_attach (char *args, int from_tty)
{
  char *exec_file;
  int pid;
  char *dummy;

  if (!args)
    error_no_arg (_("process-id to attach"));

  dummy = args;
  pid = strtol (args, &dummy, 0);
  /* Some targets don't set errno on errors, grrr! */
  if ((pid == 0) && (args == dummy))
      error (_("Illegal process-id: %s."), args);
  
  if (pid == getpid ())	/* Trying to m********e? */
    error (_("I refuse to debug myself!"));
  
  if (from_tty)
    {
      exec_file = (char *) get_exec_file (0);
      
      if (exec_file)
	printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
			   target_pid_to_str (pid_to_ptid (pid)));
      else
	printf_unfiltered (_("Attaching to %s\n"),
			   target_pid_to_str (pid_to_ptid (pid)));
      
      gdb_flush (gdb_stdout);
    }

  attach (pid);
  
  inferior_ptid = pid_to_ptid (pid);
  push_target (&deprecated_child_ops);

  /* Do this first, before anything has had a chance to query the
     inferior's symbol table or similar.  */
  observer_notify_inferior_created (&current_target, from_tty);
}
Пример #11
0
static void
unassign_command (char *args, int from_tty)
{
	// Parse user input options
	// argument is a list of addresses
	if (args)
	{
		char* options[MAX_NUM_OPTIONS];
		int num_options = ca_parse_options(args, options);
		int i;
		for (i = 0; i < num_options; i++)
		{
			char* option = options[i];
			address_t addr = parse_and_eval_address (option);
			unset_value (addr);
		}
	}
	else
		error_no_arg (_("address"));
}
Пример #12
0
static void
haiku_child_attach (char *args, int from_tty)
{
	extern int stop_after_trap;
	thread_id threadID;
	thread_info threadInfo;
	status_t result;

	TRACE(("haiku_child_attach(`%s', %d)\n", args, from_tty));

	if (!args)
		error_no_arg ("thread-id to attach");

	// get the thread ID
	threadID = strtoul (args, 0, 0);
	if (threadID <= 0)
		error("The given thread-id %ld is invalid.", threadID);

	haiku_init_child_debugging(threadID, true);

	TRACE(("haiku_child_attach() done\n"));
}
Пример #13
0
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);
}
Пример #14
0
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 *newstr;
	    char *p;
	    char *q;
	    int ch;

	    if (arg == NULL)
	      arg = "";
	    newstr = (char *)xmalloc(strlen(arg) + 2);
	    p = arg;
	    q = newstr;
	    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 /* 0 */
	    *q++ = '\0';
	    newstr = (char *)xrealloc(newstr, (q - newstr));
	    if (*(char **)c->var != NULL)
	      xfree(*(char **)c->var);
	    *(char **)c->var = newstr;
	  }
	  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);
	  *(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 = (unsigned int)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 = (unsigned int)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 = (int)parse_and_eval_long(arg);
	  break;
	case var_enum:
	  {
	    int i;
	    int len;
	    int nmatches = 0;
	    const char *match = NULL;
	    char *p;

	    /* APPLE LOCAL: Give the valid options for all error
	       messages for enum type commands. */

	    /* If an argument was supplied, parse it. */
	    if (arg != NULL)
	      {
		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 == 1)
	      *(const char **)c->var = match;
	    else
	      {
                /* If there was an error, print an informative
                   error message.  */
                struct ui_file *tmp_error_stream = mem_fileopen();
                make_cleanup_ui_file_delete (tmp_error_stream);

                if (arg == NULL)
                  fprintf_unfiltered(tmp_error_stream, "Requires an argument.");
                else if (nmatches <= 0)
                  fprintf_unfiltered(tmp_error_stream, "Undefined item: \"%s\".", arg);
		else if (nmatches > 1)
                  fprintf_unfiltered(tmp_error_stream, "Ambiguous item \"%s\".", arg);

                fprintf_unfiltered(tmp_error_stream, " Valid arguments are ");
                for (i = 0; c->enums[i]; i++)
                  {
                    if (i != 0)
                      fprintf_unfiltered(tmp_error_stream, ", ");
                    fputs_unfiltered(c->enums[i], tmp_error_stream);
                  }
                fprintf_unfiltered(tmp_error_stream, ".");
                error_stream(tmp_error_stream);
	      }

	    /* END APPLE LOCAL */
	  }
	  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 (*(unsigned 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);
}
Пример #15
0
void
do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
{
  /* A flag to indicate the option is changed or not.  */
  int option_changed = 0;

  gdb_assert (c->type == set_cmd);

  switch (c->var_type)
    {
    case var_string:
      {
	char *newobj;
	const char *p;
	char *q;
	int ch;

	if (arg == NULL)
	  arg = "";
	newobj = (char *) xmalloc (strlen (arg) + 2);
	p = arg;
	q = newobj;
	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 (get_current_arch (), &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';
	newobj = (char *) xrealloc (newobj, q - newobj);

	if (*(char **) c->var == NULL
	    || strcmp (*(char **) c->var, newobj) != 0)
	  {
	    xfree (*(char **) c->var);
	    *(char **) c->var = newobj;

	    option_changed = 1;
	  }
	else
	  xfree (newobj);
      }
      break;
    case var_string_noescape:
      if (arg == NULL)
	arg = "";

      if (*(char **) c->var == NULL || strcmp (*(char **) c->var, arg) != 0)
	{
	  xfree (*(char **) c->var);
	  *(char **) c->var = xstrdup (arg);

	  option_changed = 1;
	}
      break;
    case var_filename:
      if (arg == NULL)
	error_no_arg (_("filename to set it to."));
      /* FALLTHROUGH */
    case var_optional_filename:
      {
	char *val = NULL;

	if (arg != NULL)
	  {
	    /* Clear trailing whitespace of filename.  */
	    const char *ptr = arg + strlen (arg) - 1;
	    char *copy;

	    while (ptr >= arg && (*ptr == ' ' || *ptr == '\t'))
	      ptr--;
	    copy = xstrndup (arg, ptr + 1 - arg);

	    val = tilde_expand (copy);
	    xfree (copy);
	  }
	else
	  val = xstrdup ("");

	if (*(char **) c->var == NULL
	    || strcmp (*(char **) c->var, val) != 0)
	  {
	    xfree (*(char **) c->var);
	    *(char **) c->var = val;

	    option_changed = 1;
	  }
	else
	  xfree (val);
      }
      break;
    case var_boolean:
      {
	int val = parse_cli_boolean_value (arg);

	if (val < 0)
	  error (_("\"on\" or \"off\" expected."));
	if (val != *(int *) c->var)
	  {
	    *(int *) c->var = val;

	    option_changed = 1;
	  }
      }
      break;
    case var_auto_boolean:
      {
	enum auto_boolean val = parse_auto_binary_operation (arg);

	if (*(enum auto_boolean *) c->var != val)
	  {
	    *(enum auto_boolean *) c->var = val;

	    option_changed = 1;
	  }
      }
      break;
    case var_uinteger:
    case var_zuinteger:
      {
	LONGEST val;

	if (arg == NULL)
	  {
	    if (c->var_type == var_uinteger)
	      error_no_arg (_("integer to set it to, or \"unlimited\"."));
	    else
	      error_no_arg (_("integer to set it to."));
	  }

	if (c->var_type == var_uinteger && is_unlimited_literal (arg))
	  val = 0;
	else
	  val = parse_and_eval_long (arg);

	if (c->var_type == var_uinteger && val == 0)
	  val = UINT_MAX;
	else if (val < 0
		 /* For var_uinteger, don't let the user set the value
		    to UINT_MAX directly, as that exposes an
		    implementation detail to the user interface.  */
		 || (c->var_type == var_uinteger && val >= UINT_MAX)
		 || (c->var_type == var_zuinteger && val > UINT_MAX))
	  error (_("integer %s out of range"), plongest (val));

	if (*(unsigned int *) c->var != val)
	  {
	    *(unsigned int *) c->var = val;

	    option_changed = 1;
	  }
      }
      break;
    case var_integer:
    case var_zinteger:
      {
	LONGEST val;

	if (arg == NULL)
	  {
	    if (c->var_type == var_integer)
	      error_no_arg (_("integer to set it to, or \"unlimited\"."));
	    else
	      error_no_arg (_("integer to set it to."));
	  }

	if (c->var_type == var_integer && is_unlimited_literal (arg))
	  val = 0;
	else
	  val = parse_and_eval_long (arg);

	if (val == 0 && c->var_type == var_integer)
	  val = INT_MAX;
	else if (val < INT_MIN
		 /* For var_integer, don't let the user set the value
		    to INT_MAX directly, as that exposes an
		    implementation detail to the user interface.  */
		 || (c->var_type == var_integer && val >= INT_MAX)
		 || (c->var_type == var_zinteger && val > INT_MAX))
	  error (_("integer %s out of range"), plongest (val));

	if (*(int *) c->var != val)
	  {
	    *(int *) c->var = val;

	    option_changed = 1;
	  }
	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);

	if (*(const char **) c->var != match)
	  {
	    *(const char **) c->var = match;

	    option_changed = 1;
	  }
      }
      break;
    case var_zuinteger_unlimited:
      {
	LONGEST val;

	if (arg == NULL)
	  error_no_arg (_("integer to set it to, or \"unlimited\"."));

	if (is_unlimited_literal (arg))
	  val = -1;
	else
	  val = parse_and_eval_long (arg);

	if (val > INT_MAX)
	  error (_("integer %s out of range"), plongest (val));
	else if (val < -1)
	  error (_("only -1 is allowed to set as unlimited"));

	if (*(int *) c->var != val)
	  {
	    *(int *) c->var = val;
	    option_changed = 1;
	  }
      }
      break;
    default:
      error (_("gdb internal error: bad var_type in do_setshow_command"));
    }
  c->func (c, NULL, from_tty);

  if (notify_command_param_changed_p (option_changed, c))
    {
      char *name, *cp;
      struct cmd_list_element **cmds;
      struct cmd_list_element *p;
      int i;
      int length = 0;

      /* Compute the whole multi-word command options.  If user types command
	 'set foo bar baz on', c->name is 'baz', and GDB can't pass "bar" to
	 command option change notification, because it is confusing.  We can
	 trace back through field 'prefix' to compute the whole options,
	 and pass "foo bar baz" to notification.  */

      for (i = 0, p = c; p != NULL; i++)
	{
	  length += strlen (p->name);
	  length++;

	  p = p->prefix;
	}
      cp = name = (char *) xmalloc (length);
      cmds = XNEWVEC (struct cmd_list_element *, i);

      /* Track back through filed 'prefix' and cache them in CMDS.  */
      for (i = 0, p = c; p != NULL; i++)
	{
	  cmds[i] = p;
	  p = p->prefix;
	}

      /* Don't trigger any observer notification if prefixlist is not
	 setlist.  */
      i--;
      if (cmds[i]->prefixlist != &setlist)
	{
	  xfree (cmds);
	  xfree (name);

	  return;
	}
      /* Traverse them in the reversed order, and copy their names into
	 NAME.  */
      for (i--; i >= 0; i--)
	{
	  memcpy (cp, cmds[i]->name, strlen (cmds[i]->name));
	  cp += strlen (cmds[i]->name);

	  if (i != 0)
	    {
	      cp[0] = ' ';
	      cp++;
	    }
	}
      cp[0] = 0;

      xfree (cmds);

      switch (c->var_type)
	{
	case var_string:
	case var_string_noescape:
	case var_filename:
	case var_optional_filename:
	case var_enum:
	  observer_notify_command_param_changed (name, *(char **) c->var);
	  break;
	case var_boolean:
	  {
	    char *opt = *(int *) c->var ? "on" : "off";

	    observer_notify_command_param_changed (name, opt);
	  }
	  break;
	case var_auto_boolean:
	  {
	    const char *s = auto_boolean_enums[*(enum auto_boolean *) c->var];

	    observer_notify_command_param_changed (name, s);
	  }
	  break;
	case var_uinteger:
	case var_zuinteger:
	  {
	    char s[64];

	    xsnprintf (s, sizeof s, "%u", *(unsigned int *) c->var);
	    observer_notify_command_param_changed (name, s);
	  }
	  break;
	case var_integer:
	case var_zinteger:
	case var_zuinteger_unlimited:
	  {
	    char s[64];

	    xsnprintf (s, sizeof s, "%d", *(int *) c->var);
	    observer_notify_command_param_changed (name, s);
	  }
	  break;
	}
      xfree (name);
    }
}
Пример #16
0
static void
mem_command (char *args, int from_tty)
{
  CORE_ADDR lo, hi;
  char *tok;
  struct mem_attrib attrib;

  if (!args)
    error_no_arg (_("No mem"));

  /* For "mem auto", switch back to using a target provided list.  */
  if (strcmp (args, "auto") == 0)
    {
      if (mem_use_target)
	return;

      if (mem_region_list != target_mem_region_list)
	{
	  mem_clear ();
	  mem_region_list = target_mem_region_list;
	}

      mem_use_target = 1;
      return;
    }

  require_user_regions (from_tty);

  tok = strtok (args, " \t");
  if (!tok)
    error (_("no lo address"));
  lo = parse_and_eval_address (tok);

  tok = strtok (NULL, " \t");
  if (!tok)
    error (_("no hi address"));
  hi = parse_and_eval_address (tok);

  attrib = default_mem_attrib;
  while ((tok = strtok (NULL, " \t")) != NULL)
    {
      if (strcmp (tok, "rw") == 0)
	attrib.mode = MEM_RW;
      else if (strcmp (tok, "ro") == 0)
	attrib.mode = MEM_RO;
      else if (strcmp (tok, "wo") == 0)
	attrib.mode = MEM_WO;

      else if (strcmp (tok, "8") == 0)
	attrib.width = MEM_WIDTH_8;
      else if (strcmp (tok, "16") == 0)
	{
	  if ((lo % 2 != 0) || (hi % 2 != 0))
	    error (_("region bounds not 16 bit aligned"));
	  attrib.width = MEM_WIDTH_16;
	}
      else if (strcmp (tok, "32") == 0)
	{
	  if ((lo % 4 != 0) || (hi % 4 != 0))
	    error (_("region bounds not 32 bit aligned"));
	  attrib.width = MEM_WIDTH_32;
	}
      else if (strcmp (tok, "64") == 0)
	{
	  if ((lo % 8 != 0) || (hi % 8 != 0))
	    error (_("region bounds not 64 bit aligned"));
	  attrib.width = MEM_WIDTH_64;
	}

#if 0
      else if (strcmp (tok, "hwbreak") == 0)
	attrib.hwbreak = 1;
      else if (strcmp (tok, "swbreak") == 0)
	attrib.hwbreak = 0;
#endif

      else if (strcmp (tok, "cache") == 0)
	attrib.cache = 1;
      else if (strcmp (tok, "nocache") == 0)
	attrib.cache = 0;

#if 0
      else if (strcmp (tok, "verify") == 0)
	attrib.verify = 1;
      else if (strcmp (tok, "noverify") == 0)
	attrib.verify = 0;
#endif

      else
	error (_("unknown attribute: %s"), tok);
    }

  create_mem_region (lo, hi, &attrib);
}