import gdb-1999-08-09 snapshot
[external/binutils.git] / gdb / kod.c
1 /* Kernel Object Display generic routines and callbacks
2    Copyright 1998, 1999 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
29 /* Prototypes for exported functions.  */
30 void _initialize_kod (void);
31
32 /* Prototypes for local functions.  */
33 static void show_kod (char *, int);
34 static void info_kod_command (char *, int);
35 static void load_kod_library (char *);
36
37 /* Prototypes for callbacks.  These are passed into the KOD modules.  */
38 static void gdb_kod_display (char *);
39 static 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
64 static char *(*gdb_kod_open) (void *, void *);
65 static void (*gdb_kod_request) (char *, int);
66 static void (*gdb_kod_close) ();
67
68
69 /* Name of inferior's operating system.  */
70 char *operating_system;
71
72 /* We save a copy of the OS so that we can properly reset when
73    switching OS's.  */
74 static char *old_operating_system;
75
76 /* Functions imported from the library for all supported OSes.
77    FIXME: we really should do something better, such as dynamically
78    loading the KOD modules.  */
79 extern char *ecos_kod_open (void *, void *);
80 extern void ecos_kod_request (char *, int);
81 extern void ecos_kod_close ();
82 extern char *cisco_kod_open (void *, void *);
83 extern void cisco_kod_request (char *, int);
84 extern void cisco_kod_close ();
85
86
87 /* Print a line of data generated by the module.  */
88
89 static void
90 gdb_kod_display (char *arg)
91 {
92   printf_filtered ("%s", arg);
93 }
94
95 /* Queries the target on behalf of the module.  */
96
97 static void
98 gdb_kod_query (char *arg, char *result, int *maxsiz)
99 {
100   int bufsiz = 0;
101
102   /* Check if current target has remote_query capabilities.
103      If not, it does not have kod either.  */
104   if (! current_target.to_query)
105     {
106       strcpy (result,
107               "ERR: Kernel Object Display not supported by current target\n");
108       return;
109     }
110
111   /* Just get the maximum buffer size.  */
112   target_query ((int) 'K', 0, 0, &bufsiz);
113
114   /* Check if *we* were called just for getting the buffer size.  */
115   if (*maxsiz == 0)
116     {
117       *maxsiz = bufsiz;
118       strcpy (result, "OK");
119       return;
120     }
121
122   /* Check if caller can handle a buffer this large, if not, adjust.  */
123   if (bufsiz > *maxsiz)
124     bufsiz = *maxsiz;
125
126   /* See if buffer can hold the query (usually it can, as the query is
127      short).  */
128   if (strlen (arg) >= bufsiz)
129     error ("kod: query argument too long");
130
131   /* Send actual request.  */
132   if (target_query ((int) 'K', arg, result, &bufsiz))
133     strcpy (result, "ERR: remote query failed");
134 }
135
136 /* Print name of kod command after selecting the appropriate kod
137    formatting library module.  As a side effect we create a new "info"
138    subcommand which is what the user actually uses to query the OS.  */
139
140 static void
141 kod_set_os (char *arg, int from_tty, struct cmd_list_element *command)
142 {
143   char *p;
144
145   if (command->type != set_cmd)
146     return;
147
148   /* If we had already had an open OS, close it.  */
149   if (gdb_kod_close)
150     (*gdb_kod_close) ();
151
152   /* Also remove the old OS's command.  */
153   if (old_operating_system)
154     {
155       delete_cmd (old_operating_system, &infolist);
156       free (old_operating_system);
157     }
158   old_operating_system = strdup (operating_system);
159
160   if (! operating_system || ! *operating_system)
161     {
162       /* If user set operating system to empty, we want to forget we
163          had a module open.  Setting these variables is just nice for
164          debugging and clarity.  */
165       gdb_kod_open = NULL;
166       gdb_kod_request = NULL;
167       gdb_kod_close = NULL;
168     }
169   else
170     {
171       char *kodlib;
172
173       load_kod_library (operating_system);
174
175       kodlib = (*gdb_kod_open) (gdb_kod_display, gdb_kod_query);
176
177       /* Add kod related info commands to gdb.  */
178       add_info (operating_system, info_kod_command,
179                 "Displays information about Kernel Objects.");
180
181       p = strrchr (kodlib, '-');
182       if (p != NULL)
183         p++;
184       else
185         p = "Unknown KOD library";
186       printf_filtered ("%s - %s\n", operating_system, p);
187
188       free (kodlib);
189     }
190 }
191
192 /* Print information about currently known kernel objects of the
193    specified type or a list of all known kernel object types if
194    argument is empty.  */
195
196 static void
197 info_kod_command (char *arg, int from_tty)
198 {
199   (*gdb_kod_request) (arg, from_tty);
200 }
201
202 /* Print name of kod command after selecting the appropriate kod
203    formatting library module.  */
204
205 static void
206 load_kod_library (char *lib)
207 {
208 #if 0
209   /* FIXME: Don't have the eCos code here.  */
210   if (! strcmp (lib, "ecos"))
211     {
212       gdb_kod_open = ecos_kod_open;
213       gdb_kod_request = ecos_kod_request;
214       gdb_kod_close = ecos_kod_close;
215     }
216   else
217 #endif /* 0 */
218    if (! strcmp (lib, "cisco"))
219     {
220       gdb_kod_open = cisco_kod_open;
221       gdb_kod_request = cisco_kod_request;
222       gdb_kod_close = cisco_kod_close;
223     }
224   else
225     error ("Unknown operating system: %s\n", operating_system);
226 }
227
228 void
229 _initialize_kod ()
230 {
231   struct cmd_list_element *c;
232
233   c = add_set_cmd ("os", no_class, var_string,
234                    (char *) &operating_system,
235                    "Set operating system",
236                    &setlist);
237   c->function.sfunc = kod_set_os;
238   add_show_from_set (c, &showlist);
239 }