1/* Kernel Object Display generic routines and callbacks
2   Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
3
4   Written by Fernando Nasser <fnasser@cygnus.com> for Cygnus Solutions.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330,
21   Boston, MA 02111-1307, USA.  */
22
23#include "defs.h"
24#include "command.h"
25#include "gdbcmd.h"
26#include "target.h"
27#include "gdb_string.h"
28#include "kod.h"
29
30/* Prototypes for exported functions.  */
31void _initialize_kod (void);
32
33/* Prototypes for local functions.  */
34static void info_kod_command (char *, int);
35static void load_kod_library (char *);
36
37/* Prototypes for callbacks.  These are passed into the KOD modules.  */
38static void gdb_kod_display (char *);
39static void gdb_kod_query (char *, char *, int *);
40
41/* These functions are imported from the KOD module.
42
43   gdb_kod_open - initiates the KOD connection to the remote.  The
44   first argument is the display function the module should use to
45   communicate with the user.  The second argument is the query
46   function the display should use to communicate with the target.
47   This should call error() if there is an error.  Otherwise it should
48   return a malloc()d string of the form:
49
50   NAME VERSION - DESCRIPTION
51
52   Neither NAME nor VERSION should contain a hyphen.
53
54
55   gdb_kod_request - This is used when the user enters an "info
56   <module>" request.  The remaining arguments are passed as the first
57   argument.  The second argument is the standard `from_tty'
58   argument.
59
60
61   gdb_kod_close - This is called when the KOD connection to the
62   remote should be terminated.  */
63
64static char *(*gdb_kod_open) (kod_display_callback_ftype *display,
65			      kod_query_callback_ftype *query);
66static void (*gdb_kod_request) (char *, int);
67static void (*gdb_kod_close) ();
68
69
70/* Name of inferior's operating system.  */
71char *operating_system;
72
73/* We save a copy of the OS so that we can properly reset when
74   switching OS's.  */
75static char *old_operating_system;
76
77/* Print a line of data generated by the module.  */
78
79static void
80gdb_kod_display (char *arg)
81{
82  printf_filtered ("%s", arg);
83}
84
85/* Queries the target on behalf of the module.  */
86
87static void
88gdb_kod_query (char *arg, char *result, int *maxsiz)
89{
90  LONGEST bufsiz = 0;
91
92  /* Check if current target has remote_query capabilities.  If not,
93     it does not have kod either.  */
94  bufsiz = target_read_partial (&current_target, TARGET_OBJECT_KOD,
95				NULL, NULL, 0, 0);
96  if (bufsiz < 0)
97    {
98      strcpy (result,
99              "ERR: Kernel Object Display not supported by current target\n");
100      return;
101    }
102
103  /* Just get the maximum buffer size.  */
104
105  /* Check if *we* were called just for getting the buffer size.  */
106  if (*maxsiz == 0)
107    {
108      *maxsiz = bufsiz;
109      strcpy (result, "OK");
110      return;
111    }
112
113  /* Check if caller can handle a buffer this large, if not, adjust.  */
114  if (bufsiz > *maxsiz)
115    bufsiz = *maxsiz;
116
117  /* See if buffer can hold the query (usually it can, as the query is
118     short).  */
119  if (strlen (arg) >= bufsiz)
120    error ("kod: query argument too long");
121
122  /* Send actual request.  */
123  if (target_read_partial (&current_target, TARGET_OBJECT_KOD,
124			   arg, result, 0, bufsiz) < 0)
125    strcpy (result, "ERR: remote query failed");
126}
127
128/* Print name of kod command after selecting the appropriate kod
129   formatting library module.  As a side effect we create a new "info"
130   subcommand which is what the user actually uses to query the OS.  */
131
132static void
133kod_set_os (char *arg, int from_tty, struct cmd_list_element *command)
134{
135  char *p;
136
137  /* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set()
138     function clones the set command passed as a parameter.  The clone
139     operation will include (BUG?) any ``set'' command callback, if
140     present.  Commands like ``info set'' call all the ``show''
141     command callbacks.  Unfortunately, for ``show'' commands cloned
142     from ``set'', this includes callbacks belonging to ``set''
143     commands.  Making this worse, this only occures if
144     deprecated_add_show_from_set() is called after add_cmd_sfunc()
145     (BUG?).  */
146
147  if (cmd_type (command) != set_cmd)
148    return;
149
150  /* If we had already had an open OS, close it.  */
151  if (gdb_kod_close)
152    (*gdb_kod_close) ();
153
154  /* Also remove the old OS's command.  */
155  if (old_operating_system)
156    {
157      delete_cmd (old_operating_system, &infolist);
158      xfree (old_operating_system);
159    }
160
161  if (! operating_system || ! *operating_system)
162    {
163      /* If user set operating system to empty, we want to forget we
164	 had a module open.  Setting these variables is just nice for
165	 debugging and clarity.  */
166      gdb_kod_open = NULL;
167      gdb_kod_request = NULL;
168      gdb_kod_close = NULL;
169    }
170  else
171    {
172      char *kodlib;
173
174      old_operating_system = xstrdup (operating_system);
175
176      load_kod_library (operating_system);
177
178      kodlib = (*gdb_kod_open) (gdb_kod_display, gdb_kod_query);
179
180      /* Add kod related info commands to gdb.  */
181      add_info (operating_system, info_kod_command,
182		"Displays information about Kernel Objects.");
183
184      p = strrchr (kodlib, '-');
185      if (p != NULL)
186	p++;
187      else
188	p = "Unknown KOD library";
189      printf_filtered ("%s - %s\n", operating_system, p);
190
191      xfree (kodlib);
192    }
193}
194
195/* Print information about currently known kernel objects of the
196   specified type or a list of all known kernel object types if
197   argument is empty.  */
198
199static void
200info_kod_command (char *arg, int from_tty)
201{
202  (*gdb_kod_request) (arg, from_tty);
203}
204
205/* Print name of kod command after selecting the appropriate kod
206   formatting library module.  */
207
208static void
209load_kod_library (char *lib)
210{
211#if 0
212  /* FIXME: Don't have the eCos code here.  */
213  if (! strcmp (lib, "ecos"))
214    {
215      gdb_kod_open = ecos_kod_open;
216      gdb_kod_request = ecos_kod_request;
217      gdb_kod_close = ecos_kod_close;
218    }
219  else
220#endif /* 0 */
221   if (! strcmp (lib, "cisco"))
222    {
223      gdb_kod_open = cisco_kod_open;
224      gdb_kod_request = cisco_kod_request;
225      gdb_kod_close = cisco_kod_close;
226    }
227  else
228    error ("Unknown operating system: %s\n", operating_system);
229}
230
231void
232_initialize_kod (void)
233{
234  struct cmd_list_element *c;
235
236  c = add_set_cmd ("os", no_class, var_string,
237		   (char *) &operating_system,
238		   "Set operating system",
239		   &setlist);
240  set_cmd_sfunc (c, kod_set_os);
241  deprecated_add_show_from_set (c, &showlist);
242}
243