3 #include "static_init.h"
4 #include "jdb_module.h"
7 * The core of the modularized Jdb.
11 * This class provides the core functions for handling
12 * Jdb_modules and providing them with the right input.
20 * The command structure for Jdb_core.
22 * This structure consists of a pointer to the Jdb_module
23 * and a Jdb_module::Cmd structure. It is used in exec_cmd()
24 * and returned from has_cmd().
29 * Pointer to the module providing this command.
34 * The Jdb_module::Cmd structure, describing the command.
36 * If this is a null pointer the command is invalid.
38 * @see Jdb_module::Cmd
40 Jdb_module::Cmd const *cmd;
43 * Create a Jdb_core::Cmd.
44 * @param _mod the Jdb_module providing the command.
45 * @param _cmd the command structure (see Jdb_module::Cmd).
47 Cmd(Jdb_module *_mod, Jdb_module::Cmd const *_cmd = 0)
48 : mod(_mod), cmd(_cmd)
53 * Get the command structure accoring to the given name.
54 * @param cmd the command to look for.
55 * @return A valid Cmd structure if cmd was found, or a
56 * Cmd structure where Cmd::cmd is a null pointer if
57 * no module provides such a command.
59 static Cmd has_cmd(char const *cmd);
62 * Execute the command according to cmd.
63 * @param cmd the command structure (see Jdb_core::Cmd), which
64 * describes the command to execute.
65 * @return 0 if Jdb_module::action() returned LEAVE
66 * 1 if Jdb_module::action() returned NOTHING
67 * 2 if Jdb_module::action() returned GO_BACK (KEY_HOME entered)
68 * 3 if the input was aborted (KEY_ESC entered) or was invalid
70 * This method is actually responsible for reading the input
71 * with respect to the commands format string and calling
72 * the Jdb_module::action() method after that.
75 static int exec_cmd(Cmd const cmd, char const *str, int push_next_char = -1);
78 * Overwritten getchar() to be able to handle next_char.
80 static int getchar(void);
83 * Call this function every time a `\n' is written to the
84 * console and it stops output when the screen is full.
85 * @return 0 if user wants to abort the output (escape or 'q' pressed)
87 static int new_line(unsigned &line);
89 static void prompt_start();
90 static void prompt_end();
92 static int prompt_len();
93 static void update_prompt();
94 static int set_prompt_color(char v);
97 * Like strlen but do not count ESC sequences.
99 static int print_len(const char *s);
101 static char esc_prompt[];
103 static void (*wait_for_input)();
106 static bool short_mode;
107 typedef int (Input_fmt)(char fmt, int *size, char const *cmd_str, void *buf);
110 static int next_char;
111 static Input_fmt *_fmt_list[26];
114 #define JDB_ANSI_black "30"
115 #define JDB_ANSI_gray "30;1"
116 #define JDB_ANSI_red "31"
117 #define JDB_ANSI_lightred "31;1"
118 #define JDB_ANSI_green "32"
119 #define JDB_ANSI_lightgreen "32;1"
120 #define JDB_ANSI_brown "33"
121 #define JDB_ANSI_yellow "33;1"
122 #define JDB_ANSI_blue "34"
123 #define JDB_ANSI_lightblue "34;1"
124 #define JDB_ANSI_magenta "35"
125 #define JDB_ANSI_lightmagenta "35;1"
126 #define JDB_ANSI_cyan "36"
127 #define JDB_ANSI_lightcyan "36;1"
128 #define JDB_ANSI_white "37"
129 #define JDB_ANSI_brightwhite "37;1"
130 #define JDB_ANSI_default ""
132 #define JDB_ANSI_COLOR(color) "\033[" JDB_ANSI_##color "m"
134 #define JDB_ANSI_END "\033[m"
144 #include <simpleio.h>
147 #include "l4_types.h"
148 #include "kernel_console.h"
149 #include "keycodes.h"
150 #include "jdb_prompt_ext.h"
151 #include "jdb_screen.h"
152 #include "processor.h"
154 bool Jdb_core::short_mode = true;
155 int Jdb_core::next_char = -1;
156 char Jdb_core::esc_prompt[32] = JDB_ANSI_COLOR(green);
157 Jdb_core::Input_fmt *Jdb_core::_fmt_list[26];
158 void (*Jdb_core::wait_for_input)();
162 Jdb_core::add_fmt_handler(char fmt, Input_fmt* hdlr)
164 if (fmt < 'a' || (fmt - 'a') >= (int)(sizeof(_fmt_list)/sizeof(_fmt_list[0])))
167 if (_fmt_list[fmt - 'a'])
170 _fmt_list[fmt - 'a'] = hdlr;
176 Jdb_core::print_prompt()
177 { prompt_start(); prompt(); prompt_end(); }
180 void Jdb_core::update_prompt()
182 Jdb_prompt_ext::update_all();
186 void Jdb_core::prompt_start()
192 void Jdb_core::prompt_end()
194 putstr(JDB_ANSI_END);
198 void Jdb_core::prompt()
200 Jdb_prompt_ext::do_all();
208 int Jdb_core::prompt_len()
214 int Jdb_core::print_len(const char *s)
219 if (s[0] == '\033' && s[1] == '[')
222 while (*s && *s != 'm')
238 Jdb_core::get_ansi_color(char c)
242 case 'N': case 'n': return 30;
243 case 'R': case 'r': return 31;
244 case 'G': case 'g': return 32;
245 case 'Y': case 'y': return 33;
246 case 'B': case 'b': return 34;
247 case 'M': case 'm': return 35;
248 case 'C': case 'c': return 36;
249 case 'W': case 'w': return 37;
256 int Jdb_core::set_prompt_color(char x)
258 unsigned pc = get_ansi_color(x);
263 if (x >= 'A' && x <= 'Z')
264 snprintf(esc_prompt, sizeof(esc_prompt) - 1, "\033[%u;%dm", pc, 1);
266 snprintf(esc_prompt, sizeof(esc_prompt) - 1, "\033[%um", pc);
273 Jdb_core::Cmd Jdb_core::has_cmd(char const *cmd)
275 for (Jdb_module::List::Const_iterator m = Jdb_module::modules.begin();
276 m != Jdb_module::modules.end(); ++m)
279 c.cmd = m->has_cmd(cmd, short_mode);
289 Jdb_core::match_len(char const *a, char const *b, unsigned l)
292 while (*a && *b && p < l && *a == *b)
301 Jdb_core::print_alternatives(char const *prefix)
303 unsigned prefix_len = 0;
304 char const *match = 0;
305 typedef Jdb_module::List::Const_iterator Iter;
306 for (Iter m = Jdb_module::modules.begin(); m != Jdb_module::modules.end(); ++m)
308 unsigned sc_max = m->num_cmds();
309 Jdb_module::Cmd const *cmds = m->cmds();
310 for (unsigned sc = 0; sc < sc_max; ++sc)
312 if (!Jdb_module::match(cmds[sc].cmd, prefix, false))
317 match = cmds[sc].cmd;
318 prefix_len = strlen(match);
321 prefix_len = match_len(match, cmds[sc].cmd, prefix_len);
322 printf("%s %s\n", cmds[sc].cmd, cmds[sc].fmt);
330 Jdb_core::complete_cmd(char const *prefix, bool &multi_match)
334 typedef Jdb_module::List::Const_iterator Iter;
335 for (Iter m = Jdb_module::modules.begin(); m != Jdb_module::modules.end(); ++m)
337 unsigned sc_max = m->num_cmds();
338 Jdb_module::Cmd const *cmds = m->cmds();
339 for (unsigned sc = 0; sc < sc_max; ++sc)
341 if (!Jdb_module::match(cmds[sc].cmd, prefix, false))
347 match = Cmd(*m, cmds + sc);
355 int Jdb_core::getchar()
368 c = Kconsole::console()->getchar(false);
381 Jdb_core::cmd_getchar(char const *&str)
402 PUBLIC static inline NEEDS[<cstdio>]
404 Jdb_core::cmd_putchar(int c)
405 { if (short_mode) putchar(c); }
408 int Jdb_core::exec_cmd(Cmd const cmd, char const *str, int push_next_char = -1)
410 char const* f = cmd.cmd->fmt;
414 void *argbuf = (void*)cmd.cmd->argbuf;
423 int num_pos = 0, num_digit = 0;
424 int max_len = 0, max_digit = 0;
428 next_char = push_next_char;
432 char *next_arg = (char*)argbuf;
433 char const *old_f = f;
442 putnstr( f1, (f-f1) );
446 int long_fmt = sizeof(long long int) == sizeof(void*);
447 bool negative = false;
448 long long int val = 0;
454 // Attention: Each case statement must finish with "continue"
455 // else it falls through to int_done!
457 case '0': case '1': case '2':
458 case '3': case '4': case '5':
459 case '6': case '7': case '8':
461 max_len = max_len * 10 + fm - '0';
487 if(sizeof(short int)==sizeof(void*))
489 else if(sizeof(int)==sizeof(void*))
491 else if(sizeof(long int)==sizeof(void*))
493 else //if(sizeof(long long int)==sizeof(void*))
520 num_pos = num_digit = 0;
525 max_digit = 2*sizeof(short int);
526 else if (long_fmt == 0)
527 max_digit = 2*sizeof(int);
528 else if (long_fmt == 1)
529 max_digit = 2*sizeof(long int);
531 max_digit = 2*sizeof(long long int);
533 while((c = cmd_getchar(str)) != ' ' && c!=KEY_RETURN)
538 if(c==KEY_BACKSPACE && num_pos>0)
541 if(num_pos == 1 && negative)
543 else if(num_pos==1 && num_mode==MULTI && num_base==8)
545 else if(num_pos==2 && num_mode==MULTI && num_base==16)
549 val = div32(val, num_base);
556 else if(num_mode!=UNSIGNED && num_pos==0 && c=='-')
563 else if(num_mode==MULTI && num_pos==0 && c=='0')
570 else if(num_mode==MULTI && num_pos==1 && num_base==8
571 && (c=='x' || c=='X'))
578 else if(num_pos==1 && (c=='x' || c=='X'))
580 // ignore 0x to allow direct pasting of addresses
586 else if(c>='0' && c<='9')
590 else if((c|0x20)>='a' && (c|0x20)<='f')
592 cv = (c|0x20) - 'a' + 10;
602 val = val * num_base + cv;
603 if ((max_len != 0 && num_pos >= max_len) ||
604 (max_digit != 0 && num_digit >= max_digit))
612 case 't': printf("%%t is not supported...\n");
618 int c = cmd_getchar(str);
622 if(fm == 'c' && isprint(c))
635 while((c = cmd_getchar(str)) != KEY_RETURN && c!=' ')
640 if(c==KEY_BACKSPACE && num_pos)
645 else if(isprint(c) && (num_pos+1 < max_len))
648 next_arg[num_pos++] = c;
651 next_arg[num_pos] = '\0';
655 int oldlen = num_pos;
656 (**(Jdb_module::Gotkey**)(next_arg+max_len))
657 (next_arg, max_len, c);
658 int newlen = strlen(next_arg);
660 printf("%s", next_arg + oldlen);
661 else if (newlen < oldlen)
662 for (int i=newlen; i<oldlen; i++)
667 next_arg[num_pos] = '\0';
668 next_arg[max_len-1] = 0;
674 && (fm - 'a') < (int)(sizeof(_fmt_list)/sizeof(_fmt_list[0]))
675 && _fmt_list[fm -'a'])
677 int size = sizeof(int);
681 case 1: size = sizeof(long int); break;
682 case 2: size = sizeof(long long int); break;
683 case -1: size = sizeof(short int); break;
685 int res = (_fmt_list[fm - 'a'])(fm, &size, str, next_arg);
693 puts(" unknown format! ");
698 if(negative) val = -val;
705 int *v = (int*)next_arg;
707 next_arg += sizeof(int);
712 long int *v = (long int*)next_arg;
714 next_arg += sizeof(long int);
719 long long int *v = (long long int*)next_arg;
721 next_arg += sizeof(long long int);
726 short int *v = (short int*)next_arg;
728 next_arg += sizeof(short int);
739 switch (cmd.mod->action(cmd.cmd->id, argbuf, f, next_char))
741 case Jdb_module::EXTRA_INPUT:
742 // more input expected
745 case Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR:
746 // more input expected, also consider previously entered key
748 case Jdb_module::LEAVE:
749 // leave kernel debugger
751 case Jdb_module::GO_BACK:
752 // user entered KEY_HOME
754 case Jdb_module::NOTHING:
755 // finished successfully
758 // there was an error
767 Jdb_core::new_line( unsigned &line )
769 if (line++ > Jdb_screen::height()-3)
771 putstr("--- CR: line, SPACE: page, ESC: abort ---");
794 //===================
796 //===================
800 * Private 'go' module.
802 * This module handles the 'go' or 'g' command
803 * that continues normal program execution.
805 class Go_m : public Jdb_module
811 static Go_m go_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
815 : Jdb_module("GENERAL")
819 Jdb_module::Action_code Go_m::action( int, void *&, char const *&, int & )
825 int Go_m::num_cmds() const
831 Jdb_module::Cmd const * Go_m::cmds() const
836 "g\tleave kernel debugger\n"
837 "Return\tshow debug message", 0 },
845 * Private 'help' module.
847 * This module handles the 'help' or 'h' command and
848 * prints out a help screen.
850 class Help_m : public Jdb_module
853 Help_m() FIASCO_INIT;
857 static Help_m help_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
861 Jdb_module::Action_code Help_m::action( int, void *&, char const *&, int & )
863 size_t const tab_width = 27;
865 if(Jdb_category::categories.begin() == Jdb_category::categories.end())
867 printf("No debugger commands seem to have been registered\n");
874 for (Jdb_category::List::Const_iterator c = Jdb_category::categories.begin();
875 c != Jdb_category::categories.end(); ++c)
878 for (Jdb_module::List::Const_iterator m = Jdb_module::modules.begin();
879 m != Jdb_module::modules.end(); ++m)
881 if (m->category() != *c)
886 if(!Jdb_core::new_line(line))
888 printf("\033[1m[%s]\033[0m %s", c->name(), c->description());
890 if(!Jdb_core::new_line(line))
894 unsigned ncmds = m->num_cmds();
895 Jdb_module::Cmd const *cmds = m->cmds();
896 for(unsigned x = 0; x < ncmds; x++)
898 char const *descr = cmds[x].descr;
901 size_t pos = strcspn(descr, "\n\t");
904 while( pos < strlen(descr))
912 if(!Jdb_core::new_line(line))
933 descr = descr + pos + 1;
934 pos = strcspn(descr, "\n\t");
939 if(!Jdb_core::new_line(line))
951 int Help_m::num_cmds() const
957 Jdb_module::Cmd const * Help_m::cmds() const
961 { 0, "h", "help", "", "h\tShow this help screen.", 0 },
962 { 0, "?", 0, "", 0, 0 },
970 : Jdb_module("GENERAL")
973 #define CAT(n, x...) static Jdb_category INIT_PRIORITY(JDB_CATEGORY_INIT_PRIO) n(x)
974 CAT(a, "GENERAL", "general debugger commands", 0);
975 CAT(b, "INFO", "information about kernel state", 1);
976 CAT(c, "MONITORING", "monitoring kernel events", 2);
977 CAT(d, "DEBUGGING", "real debugging stuff", 3);