]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_module.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_module.cpp
1 INTERFACE:
2
3 #include <cstdarg>
4 #include <cxx/hlist>
5 #include <cxx/slist>
6
7 #include "initcalls.h"
8
9 class Jdb_category;
10
11 /**
12  * Base class for any kernel debugger module.
13  *
14  * This class is the base for any module of the
15  * modularized Jdb. Ths idea is that Jdb can be
16  * extended by plugging in a new module, which
17  * provides one ore more commands and their
18  * implementations to Jdb.
19  *
20  * A new module can be created by
21  * deriving from Jdb_module and providing the neccessary
22  * methods (num_cmds, cmds, action, and maybe the
23  * constructor). To plug the module into Jdb a static
24  * instance of the module must be created, with
25  * "INIT_PRIORITY(JDB_MODULE_INIT_PRIO)".
26  *
27  */
28 class Jdb_module : public cxx::H_list_item
29 {
30 public:
31
32   /**
33    * A Jdb command description.
34    *
35    * A Jdb_module provides an array of such Cmd
36    * structures, where each structure describes
37    * one command.
38    */
39   struct Cmd {
40     /**
41      * The unique ID of the command within the module.
42      *
43      * This ID is handed to action().
44      */
45     int id;
46
47     /**
48      * The short command.
49      */
50     char const *scmd;
51
52     /**
53      * The normal (long) command.
54      */
55     char const *cmd;
56
57     /**
58      * The command format (possible options).
59      *
60      * This format string is somewhat like a "scanf"
61      * format. It may contain normal text interleaved with
62      * input format descriptions (like \%c). After the Jdb core
63      * recognized the command the format string is printed
64      * up to the first format descriptor, then input according
65      * to the given format is requested, after this input the
66      * procedure is repeated until there are no more format
67      * descriptors and action() is called.
68      *
69      * The values read via the format input are stored into
70      * Cmd::argbuf, which must provide enough space for storing
71      * all the data according to the whole format string.
72      *
73      * Format descriptors:\n
74      * A format descriptor always starts with \%; the \% may be
75      * followed by an unsigned decimal number (len argument) which
76      * specifies the maximum number of characters to read.
77      * The integer formats ('d', 'i', 'o', 'u', 'X', and 'x') may be prefixed
78      * with one or two 'l's, for reading "long int" or "long long int".
79      *
80      * The integer read formats require an int, long int, or long long int
81      * sized buffer according to the number of 'l' modifiers; for the others
82      * see the respective format description.
83      *
84      * @li '\%' print the "\%" character
85      * @li 'i' read an integer (optionally as hexadecimal number,
86      *   if it starts with "0x" or as octal number, if it
87      *   starts with "0")
88      * @li 'p' read a pointer in hexadecimal format ('void*' buffer)
89      * @li 'o' read an octal integer
90      * @li 'X', 'x' read a hexadecimal integer
91      * @li 'd' read a decimal (optionally signed) integer
92      * @li 'u' read a decimal unsigned integer
93      * @li 'c' read a character and continue immediately ('char'
94      *         buffer)
95      * @li 's' read a string (the len argument must be given)
96      *         ('char[len]' buffer)
97      *
98      */
99     char const *fmt;
100
101     /**
102      * The description of the command.
103      *
104      * The description of a command must contain the command
105      * syntax itself and followed by "\\t" the description.
106      * If more than one line is needed "\\n" can be used to switch
107      * to a new line and "\\t" again to align the description.
108      */
109     char const *descr;
110
111     /**
112      * The buffer for the read arguments.
113      *
114      * This buffer is used to store the data read via the
115      * format description (see Cmd::fmt).
116      */
117     void *argbuf;
118
119     /**
120      * Creates a Jdb command.
121      * @param _id command ID (see Cmd::id)
122      * @param _scmd short command (see Cmd::scmd)
123      * @param _cmd long command (see Cmd::cmd)
124      * @param _fmt input format (see Cmd::fmt)
125      * @param _descr command description (see Cmd::descr)
126      * @param _argbuf pointer to argument buffer (see Cmd::argbuf)
127      */
128   };
129
130   /**
131    * Possible return codes from action().
132    *
133    * The actual handler of the Jdb_module (action())
134    * may return any value of this type.
135    *
136    */
137   enum Action_code {
138
139     /// Do nothing, wait for the next command.
140     NOTHING = 0,
141
142     /// Leave the kernel debugger
143     LEAVE,
144
145     /// got KEY_HOME
146     GO_BACK,
147
148     /// there was an error (abort or invalid input)
149     ERROR,
150
151     /**
152      * Wait for new input arguments
153      * @see action() for detailed information.
154      */
155     EXTRA_INPUT,
156
157     /**
158      * Wait for new input arguments and interpret character
159      *        in next_char as next keystroke
160      * @see action() for detailed information.
161      */
162     EXTRA_INPUT_WITH_NEXTCHAR,
163   };
164
165   typedef void (Gotkey)(char *&str, int maxlen, int c);
166
167   /**
168    * Create a new instance of an Jdb_module.
169    * @param category the name of the category the module
170    *        fits in. This category must exist (see
171    *        Jdb_category) or the module is added to the
172    *        "MISC" category.
173    *
174    * This constructor automatically registers the module at the
175    * Jdb_core. The derived modules must provide an own constructor
176    * if another category than "MISC" should be used.
177    *
178    * @see Jdb_core
179    * @see Jdb_category
180    *
181    */
182   Jdb_module(char const *category = "MISC") FIASCO_INIT;
183
184   /// dtor
185   virtual ~Jdb_module() = 0;
186
187   /**
188    * The actual handler of the module.
189    * @param cmd the command ID (see Cmd::id) of the executed command.
190    * @param args a reference to the argument buffer pointer.
191    * @param fmt a reference to the format string pointer.
192    *
193    * This method is pure virtual and must be provided by the
194    * specific derivate of the Jdb_module. action() is called
195    * if one of the module's commands was issued and the input
196    * according to the format string is read.
197    *
198    * The args and fmt arguments are references because they may
199    * be modified by the action() method and extra input may be
200    * requested by returning Action_code::EXTRA_INPUT. In the
201    * case where Action_code::EXTRA_INPUT is returned the Jdb_core
202    * reads again the values according to the given format (fmt)
203    * and enters action(). With this mechanism it is possible to
204    * request further input depending on the already given input.
205    *
206    */
207   virtual Action_code action(int cmd, void *&args, char const* &fmt,
208                              int &next_char) = 0;
209
210   /**
211    * The number of commands this modules provides.
212    *
213    * This method must return how many Cmd structures can be
214    * found in the array returned by cmds().
215    *
216    * @see cmds()
217    *
218    */
219   virtual int num_cmds() const = 0;
220
221   /**
222    * The commands this module provides.
223    *
224    * An array of Cmd structures must be returned,
225    * where each entry describes a single command.
226    * The command IDs (see Cmd::id) should be unique
227    * within the module, so that action() can distinguish
228    * between the different commands.
229    *
230    * @see num_cmds()
231    * @see Cmd
232    * @see action()
233    */
234   virtual Cmd const * cmds() const = 0;
235
236   /**
237    * Get the category of this module.
238    */
239   Jdb_category const *category() const;
240
241   /**
242    * Get Cmd structure according to cmd.
243    * @param cmd the command you are looking for.
244    * @param short_mode if true the short commands are looked up
245    *        (see Cmd::scmd).
246    * @return A pointer to the Cmd structure if the command is
247    *         found, or a null pointer otherwise.
248    */
249   Cmd const* has_cmd( char const* cmd, bool short_mode = false,
250                       bool full = true) const;
251
252   typedef cxx::H_list_bss<Jdb_module> List;
253   static List modules;
254
255 private:
256   Jdb_category const *_cat;
257 };
258
259 /**
260  * A category that may contain some Jdb_modules.
261  *
262  * Each registered Jdb_module must be a member of one
263  * category. The help-module Help_m uses this categories
264  * for displaying sorted help.
265  *
266  */
267 class Jdb_category : public cxx::S_list_item
268 {
269 public:
270   /**
271    * Create a new category.
272    * @param name the name of the new category, also used
273    *        at Jdb_module creation (see Jdb_module::Jdb_module())
274    * @param desc the short description of this category.
275    * @param order the ordering number of the category.
276    */
277   Jdb_category(char const *name, char const *desc,
278                unsigned order = 0 ) FIASCO_INIT;
279
280   /**
281    * Get the name of this category.
282    */
283   char const * name() const;
284
285   /**
286    * Get the description of this category.
287    */
288   char const * description() const;
289
290 public:
291
292   /**
293    * Look for the category with the given name.
294    * @param name the name of the category you are lokking for.
295    * @param _default if set to true the default ("MISC") 
296    *        category is returned if no category with the given 
297    *        name is found.
298    *
299    */
300   static Jdb_category *find(char const *name, bool _default = false);
301
302   typedef cxx::S_list_bss<Jdb_category> List;
303   static List categories;
304
305 private:
306   char const *const _name;
307   char const *const _desc;
308   unsigned const _order;
309 };
310
311
312 IMPLEMENTATION:
313
314 #include <cassert>
315 #include <cstring>
316
317 #include "static_init.h"
318
319 Jdb_category::List Jdb_category::categories;
320 Jdb_module::List Jdb_module::modules;
321
322 static Jdb_category INIT_PRIORITY(JDB_CATEGORY_INIT_PRIO)
323   misc_cat("MISC", "misc debugger commands", 2000);
324
325 IMPLEMENT
326 Jdb_category::Jdb_category(char const *const name,
327                            char const *const desc,
328                            unsigned order)
329   : _name(name), _desc(desc), _order(order)
330 {
331   List::Iterator c = categories.begin();
332
333   for (; c != categories.end(); ++c)
334     if (c->_order >= order)
335       break;
336   categories.insert_before(this, c);
337 }
338
339 IMPLEMENT inline
340 char const * Jdb_category::name() const
341 {
342   return _name;
343 }
344
345 IMPLEMENT inline
346 char const * Jdb_category::description() const
347 {
348   return _desc;
349 }
350
351 IMPLEMENT
352 Jdb_category *Jdb_category::find(char const* name, bool _default)
353 {
354   List::Const_iterator a;
355   for (a = categories.begin();
356        a != categories.end() && strcmp(a->name(), name) != 0; ++a)
357     ;
358
359   if (_default && a == categories.end())
360     return &misc_cat;
361
362   return *a;
363 }
364
365
366 IMPLEMENT
367 Jdb_module::Jdb_module(char const *category)
368   : _cat(Jdb_category::find(category, true))
369 {
370   modules.push_front(this);
371 }
372
373 IMPLEMENT inline Jdb_module::~Jdb_module() {}
374
375 PUBLIC static
376 bool
377 Jdb_module::match(char const *cmd, char const *match, bool full = true)
378 {
379   if (!cmd || !*cmd || !match)
380     return false;
381
382   while (*cmd && *match && *match != ' ')
383     {
384       if (*cmd != *match)
385         return false;
386
387       ++cmd;
388       ++match;
389     }
390
391   if ((!*match || *match == ' ') && !*cmd)
392     return true;
393
394   if (!full && !*match)
395     return true;
396
397   return false;
398 }
399
400 IMPLEMENT
401 Jdb_module::Cmd const*
402 Jdb_module::has_cmd(char const* cmd, bool short_mode, bool full) const
403 {
404   int n = num_cmds();
405   Cmd const* cs = cmds();
406   for (int i = 0; i < n; ++i)
407     {
408       if (short_mode)
409         {
410           if (match(cs[i].scmd, cmd))
411             return cs + i;
412         }
413       else
414         {
415           if (match(cs[i].cmd, cmd, full))
416             return cs + i;
417         }
418     }
419
420   return 0;
421 }
422
423 IMPLEMENT inline
424 Jdb_category const *
425 Jdb_module::category() const
426 { return _cat; }
427