198944Sobrien/* Kernel Object Display generic routines and callbacks
298944Sobrien   Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
398944Sobrien
498944Sobrien   Written by Fernando Nasser <fnasser@cygnus.com> for Cygnus Solutions.
598944Sobrien
698944Sobrien   This file is part of GDB.
798944Sobrien
898944Sobrien   This program is free software; you can redistribute it and/or modify
998944Sobrien   it under the terms of the GNU General Public License as published by
1098944Sobrien   the Free Software Foundation; either version 2 of the License, or
1198944Sobrien   (at your option) any later version.
1298944Sobrien
1398944Sobrien   This program is distributed in the hope that it will be useful,
1498944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1598944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1698944Sobrien   GNU General Public License for more details.
1798944Sobrien
1898944Sobrien   You should have received a copy of the GNU General Public License
1998944Sobrien   along with this program; if not, write to the Free Software
2098944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2198944Sobrien   Boston, MA 02111-1307, USA.  */
2298944Sobrien
2398944Sobrien#include "defs.h"
2498944Sobrien#include "command.h"
2598944Sobrien#include "gdbcmd.h"
2698944Sobrien#include "target.h"
2798944Sobrien#include "gdb_string.h"
2898944Sobrien#include "kod.h"
2998944Sobrien
3098944Sobrien/* Prototypes for exported functions.  */
3198944Sobrienvoid _initialize_kod (void);
3298944Sobrien
3398944Sobrien/* Prototypes for local functions.  */
3498944Sobrienstatic void info_kod_command (char *, int);
3598944Sobrienstatic void load_kod_library (char *);
3698944Sobrien
3798944Sobrien/* Prototypes for callbacks.  These are passed into the KOD modules.  */
3898944Sobrienstatic void gdb_kod_display (char *);
3998944Sobrienstatic void gdb_kod_query (char *, char *, int *);
4098944Sobrien
4198944Sobrien/* These functions are imported from the KOD module.
4298944Sobrien
4398944Sobrien   gdb_kod_open - initiates the KOD connection to the remote.  The
4498944Sobrien   first argument is the display function the module should use to
4598944Sobrien   communicate with the user.  The second argument is the query
4698944Sobrien   function the display should use to communicate with the target.
4798944Sobrien   This should call error() if there is an error.  Otherwise it should
4898944Sobrien   return a malloc()d string of the form:
4998944Sobrien
5098944Sobrien   NAME VERSION - DESCRIPTION
5198944Sobrien
5298944Sobrien   Neither NAME nor VERSION should contain a hyphen.
5398944Sobrien
5498944Sobrien
5598944Sobrien   gdb_kod_request - This is used when the user enters an "info
5698944Sobrien   <module>" request.  The remaining arguments are passed as the first
5798944Sobrien   argument.  The second argument is the standard `from_tty'
5898944Sobrien   argument.
5998944Sobrien
6098944Sobrien
6198944Sobrien   gdb_kod_close - This is called when the KOD connection to the
6298944Sobrien   remote should be terminated.  */
6398944Sobrien
6498944Sobrienstatic char *(*gdb_kod_open) (kod_display_callback_ftype *display,
6598944Sobrien			      kod_query_callback_ftype *query);
6698944Sobrienstatic void (*gdb_kod_request) (char *, int);
6798944Sobrienstatic void (*gdb_kod_close) ();
6898944Sobrien
6998944Sobrien
7098944Sobrien/* Name of inferior's operating system.  */
7198944Sobrienchar *operating_system;
7298944Sobrien
7398944Sobrien/* We save a copy of the OS so that we can properly reset when
7498944Sobrien   switching OS's.  */
7598944Sobrienstatic char *old_operating_system;
7698944Sobrien
7798944Sobrien/* Print a line of data generated by the module.  */
7898944Sobrien
7998944Sobrienstatic void
8098944Sobriengdb_kod_display (char *arg)
8198944Sobrien{
8298944Sobrien  printf_filtered ("%s", arg);
8398944Sobrien}
8498944Sobrien
8598944Sobrien/* Queries the target on behalf of the module.  */
8698944Sobrien
8798944Sobrienstatic void
8898944Sobriengdb_kod_query (char *arg, char *result, int *maxsiz)
8998944Sobrien{
90130803Smarcel  LONGEST bufsiz = 0;
9198944Sobrien
92130803Smarcel  /* Check if current target has remote_query capabilities.  If not,
93130803Smarcel     it does not have kod either.  */
94130803Smarcel  bufsiz = target_read_partial (&current_target, TARGET_OBJECT_KOD,
95130803Smarcel				NULL, NULL, 0, 0);
96130803Smarcel  if (bufsiz < 0)
9798944Sobrien    {
9898944Sobrien      strcpy (result,
9998944Sobrien              "ERR: Kernel Object Display not supported by current target\n");
10098944Sobrien      return;
10198944Sobrien    }
10298944Sobrien
10398944Sobrien  /* Just get the maximum buffer size.  */
10498944Sobrien
10598944Sobrien  /* Check if *we* were called just for getting the buffer size.  */
10698944Sobrien  if (*maxsiz == 0)
10798944Sobrien    {
10898944Sobrien      *maxsiz = bufsiz;
10998944Sobrien      strcpy (result, "OK");
11098944Sobrien      return;
11198944Sobrien    }
11298944Sobrien
11398944Sobrien  /* Check if caller can handle a buffer this large, if not, adjust.  */
11498944Sobrien  if (bufsiz > *maxsiz)
11598944Sobrien    bufsiz = *maxsiz;
11698944Sobrien
11798944Sobrien  /* See if buffer can hold the query (usually it can, as the query is
11898944Sobrien     short).  */
11998944Sobrien  if (strlen (arg) >= bufsiz)
12098944Sobrien    error ("kod: query argument too long");
12198944Sobrien
12298944Sobrien  /* Send actual request.  */
123130803Smarcel  if (target_read_partial (&current_target, TARGET_OBJECT_KOD,
124130803Smarcel			   arg, result, 0, bufsiz) < 0)
12598944Sobrien    strcpy (result, "ERR: remote query failed");
12698944Sobrien}
12798944Sobrien
12898944Sobrien/* Print name of kod command after selecting the appropriate kod
12998944Sobrien   formatting library module.  As a side effect we create a new "info"
13098944Sobrien   subcommand which is what the user actually uses to query the OS.  */
13198944Sobrien
13298944Sobrienstatic void
13398944Sobrienkod_set_os (char *arg, int from_tty, struct cmd_list_element *command)
13498944Sobrien{
13598944Sobrien  char *p;
13698944Sobrien
137130803Smarcel  /* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
138130803Smarcel     the set command passed as a parameter.  The clone operation will
139130803Smarcel     include (BUG?) any ``set'' command callback, if present.
140130803Smarcel     Commands like ``info set'' call all the ``show'' command
141130803Smarcel     callbacks.  Unfortunately, for ``show'' commands cloned from
142130803Smarcel     ``set'', this includes callbacks belonging to ``set'' commands.
143130803Smarcel     Making this worse, this only occures if add_show_from_set() is
144130803Smarcel     called after add_cmd_sfunc() (BUG?).  */
145130803Smarcel
146130803Smarcel  if (cmd_type (command) != set_cmd)
14798944Sobrien    return;
14898944Sobrien
14998944Sobrien  /* If we had already had an open OS, close it.  */
15098944Sobrien  if (gdb_kod_close)
15198944Sobrien    (*gdb_kod_close) ();
15298944Sobrien
15398944Sobrien  /* Also remove the old OS's command.  */
15498944Sobrien  if (old_operating_system)
15598944Sobrien    {
15698944Sobrien      delete_cmd (old_operating_system, &infolist);
15798944Sobrien      xfree (old_operating_system);
15898944Sobrien    }
15998944Sobrien
16098944Sobrien  if (! operating_system || ! *operating_system)
16198944Sobrien    {
16298944Sobrien      /* If user set operating system to empty, we want to forget we
16398944Sobrien	 had a module open.  Setting these variables is just nice for
16498944Sobrien	 debugging and clarity.  */
16598944Sobrien      gdb_kod_open = NULL;
16698944Sobrien      gdb_kod_request = NULL;
16798944Sobrien      gdb_kod_close = NULL;
16898944Sobrien    }
16998944Sobrien  else
17098944Sobrien    {
17198944Sobrien      char *kodlib;
17298944Sobrien
173130803Smarcel      old_operating_system = xstrdup (operating_system);
174130803Smarcel
17598944Sobrien      load_kod_library (operating_system);
17698944Sobrien
17798944Sobrien      kodlib = (*gdb_kod_open) (gdb_kod_display, gdb_kod_query);
17898944Sobrien
17998944Sobrien      /* Add kod related info commands to gdb.  */
18098944Sobrien      add_info (operating_system, info_kod_command,
18198944Sobrien		"Displays information about Kernel Objects.");
18298944Sobrien
18398944Sobrien      p = strrchr (kodlib, '-');
18498944Sobrien      if (p != NULL)
18598944Sobrien	p++;
18698944Sobrien      else
18798944Sobrien	p = "Unknown KOD library";
18898944Sobrien      printf_filtered ("%s - %s\n", operating_system, p);
18998944Sobrien
19098944Sobrien      xfree (kodlib);
19198944Sobrien    }
19298944Sobrien}
19398944Sobrien
19498944Sobrien/* Print information about currently known kernel objects of the
19598944Sobrien   specified type or a list of all known kernel object types if
19698944Sobrien   argument is empty.  */
19798944Sobrien
19898944Sobrienstatic void
19998944Sobrieninfo_kod_command (char *arg, int from_tty)
20098944Sobrien{
20198944Sobrien  (*gdb_kod_request) (arg, from_tty);
20298944Sobrien}
20398944Sobrien
20498944Sobrien/* Print name of kod command after selecting the appropriate kod
20598944Sobrien   formatting library module.  */
20698944Sobrien
20798944Sobrienstatic void
20898944Sobrienload_kod_library (char *lib)
20998944Sobrien{
21098944Sobrien#if 0
21198944Sobrien  /* FIXME: Don't have the eCos code here.  */
21298944Sobrien  if (! strcmp (lib, "ecos"))
21398944Sobrien    {
21498944Sobrien      gdb_kod_open = ecos_kod_open;
21598944Sobrien      gdb_kod_request = ecos_kod_request;
21698944Sobrien      gdb_kod_close = ecos_kod_close;
21798944Sobrien    }
21898944Sobrien  else
21998944Sobrien#endif /* 0 */
22098944Sobrien   if (! strcmp (lib, "cisco"))
22198944Sobrien    {
22298944Sobrien      gdb_kod_open = cisco_kod_open;
22398944Sobrien      gdb_kod_request = cisco_kod_request;
22498944Sobrien      gdb_kod_close = cisco_kod_close;
22598944Sobrien    }
22698944Sobrien  else
22798944Sobrien    error ("Unknown operating system: %s\n", operating_system);
22898944Sobrien}
22998944Sobrien
23098944Sobrienvoid
23198944Sobrien_initialize_kod (void)
23298944Sobrien{
23398944Sobrien  struct cmd_list_element *c;
23498944Sobrien
23598944Sobrien  c = add_set_cmd ("os", no_class, var_string,
23698944Sobrien		   (char *) &operating_system,
23798944Sobrien		   "Set operating system",
23898944Sobrien		   &setlist);
23998944Sobrien  set_cmd_sfunc (c, kod_set_os);
24098944Sobrien  add_show_from_set (c, &showlist);
24198944Sobrien}
242