+ return 0;
+}
+
+/* Initialize a struct disassemble_info for gdb_buffered_insn_length. */
+
+static void
+gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
+ struct disassemble_info *di,
+ const gdb_byte *insn, int max_len,
+ CORE_ADDR addr)
+{
+ init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
+
+ /* init_disassemble_info installs buffer_read_memory, etc.
+ so we don't need to do that here.
+ The cast is necessary until disassemble_info is const-ified. */
+ di->buffer = (gdb_byte *) insn;
+ di->buffer_length = max_len;
+ di->buffer_vma = addr;
+
+ di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
+ di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+ di->endian = gdbarch_byte_order (gdbarch);
+ di->endian_code = gdbarch_byte_order_for_code (gdbarch);
+
+ di->disassembler_options = get_disassembler_options (gdbarch);
+ disassemble_init_for_target (di);
+}
+
+/* Return the length in bytes of INSN. MAX_LEN is the size of the
+ buffer containing INSN. */
+
+int
+gdb_buffered_insn_length (struct gdbarch *gdbarch,
+ const gdb_byte *insn, int max_len, CORE_ADDR addr)
+{
+ struct disassemble_info di;
+
+ gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
+
+ return gdbarch_print_insn (gdbarch, addr, &di);
+}
+
+char *
+get_disassembler_options (struct gdbarch *gdbarch)
+{
+ char **disassembler_options = gdbarch_disassembler_options (gdbarch);
+ if (disassembler_options == NULL)
+ return NULL;
+ return *disassembler_options;
+}
+
+void
+set_disassembler_options (char *prospective_options)
+{
+ struct gdbarch *gdbarch = get_current_arch ();
+ char **disassembler_options = gdbarch_disassembler_options (gdbarch);
+ const disasm_options_t *valid_options;
+ char *options = remove_whitespace_and_extra_commas (prospective_options);
+ const char *opt;
+
+ /* Allow all architectures, even ones that do not support 'set disassembler',
+ to reset their disassembler options to NULL. */
+ if (options == NULL)
+ {
+ if (disassembler_options != NULL)
+ {
+ free (*disassembler_options);
+ *disassembler_options = NULL;
+ }
+ return;
+ }
+
+ valid_options = gdbarch_valid_disassembler_options (gdbarch);
+ if (valid_options == NULL)
+ {
+ fprintf_filtered (gdb_stdlog, _("\
+'set disassembler-options ...' is not supported on this architecture.\n"));
+ return;
+ }
+
+ /* Verify we have valid disassembler options. */
+ FOR_EACH_DISASSEMBLER_OPTION (opt, options)
+ {
+ size_t i;
+ for (i = 0; valid_options->name[i] != NULL; i++)
+ if (disassembler_options_cmp (opt, valid_options->name[i]) == 0)
+ break;
+ if (valid_options->name[i] == NULL)
+ {
+ fprintf_filtered (gdb_stdlog,
+ _("Invalid disassembler option value: '%s'.\n"),
+ opt);
+ return;
+ }
+ }
+
+ free (*disassembler_options);
+ *disassembler_options = xstrdup (options);
+}
+
+static void
+set_disassembler_options_sfunc (const char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ set_disassembler_options (prospective_options);
+}
+
+static void
+show_disassembler_options_sfunc (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ struct gdbarch *gdbarch = get_current_arch ();
+ const disasm_options_t *valid_options;
+
+ const char *options = get_disassembler_options (gdbarch);
+ if (options == NULL)
+ options = "";
+
+ fprintf_filtered (file, _("The current disassembler options are '%s'\n"),
+ options);
+
+ valid_options = gdbarch_valid_disassembler_options (gdbarch);
+
+ if (valid_options == NULL)
+ return;
+
+ fprintf_filtered (file, _("\n\
+The following disassembler options are supported for use with the\n\
+'set disassembler-options <option>[,<option>...]' command:\n"));
+
+ if (valid_options->description != NULL)
+ {
+ size_t i, max_len = 0;
+
+ /* Compute the length of the longest option name. */
+ for (i = 0; valid_options->name[i] != NULL; i++)
+ {
+ size_t len = strlen (valid_options->name[i]);
+ if (max_len < len)
+ max_len = len;
+ }
+
+ for (i = 0, max_len++; valid_options->name[i] != NULL; i++)
+ {
+ fprintf_filtered (file, " %s", valid_options->name[i]);
+ if (valid_options->description[i] != NULL)
+ fprintf_filtered (file, "%*c %s",
+ (int)(max_len - strlen (valid_options->name[i])), ' ',
+ valid_options->description[i]);
+ fprintf_filtered (file, "\n");
+ }
+ }
+ else
+ {
+ size_t i;
+ fprintf_filtered (file, " ");
+ for (i = 0; valid_options->name[i] != NULL; i++)
+ {
+ fprintf_filtered (file, "%s", valid_options->name[i]);
+ if (valid_options->name[i + 1] != NULL)
+ fprintf_filtered (file, ", ");
+ wrap_here (" ");
+ }
+ fprintf_filtered (file, "\n");
+ }
+}
+
+/* A completion function for "set disassembler". */
+
+static void
+disassembler_options_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ struct gdbarch *gdbarch = get_current_arch ();
+ const disasm_options_t *opts = gdbarch_valid_disassembler_options (gdbarch);
+
+ if (opts != NULL)
+ {
+ /* Only attempt to complete on the last option text. */
+ const char *separator = strrchr (text, ',');
+ if (separator != NULL)
+ text = separator + 1;
+ text = skip_spaces (text);
+ complete_on_enum (tracker, opts->name, text, word);
+ }
+}
+
+
+/* Initialization code. */
+
+void
+_initialize_disasm (void)
+{
+ struct cmd_list_element *cmd;
+
+ /* Add the command that controls the disassembler options. */
+ cmd = add_setshow_string_noescape_cmd ("disassembler-options", no_class,
+ &prospective_options, _("\
+Set the disassembler options.\n\
+Usage: set disassembler-options <option>[,<option>...]\n\n\
+See: 'show disassembler-options' for valid option values.\n"), _("\
+Show the disassembler options."), NULL,
+ set_disassembler_options_sfunc,
+ show_disassembler_options_sfunc,
+ &setlist, &showlist);
+ set_cmd_completer (cmd, disassembler_options_completer);