Subject: Re: ddb help command patch
To: Bill Stouder-Studenmund <wrstuden@netbsd.org>
From: Adam Hamsik <haaaad@gmail.com>
List: tech-kern
Date: 07/09/2007 23:23:40
This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--Apple-Mail-9--449409817
Content-Type: multipart/mixed; boundary=Apple-Mail-8--449409839


--Apple-Mail-8--449409839
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	delsp=yes;
	format=flowed


On Jun 27, 2007, at 8:03 PM, Bill Stouder-Studenmund wrote:

> On Tue, Jun 26, 2007 at 05:48:32PM +0200, Adam Hamsik wrote:
>>
>> 2) I think about dynamic ddb command/help API which could be used for
>> registering/unregistering ddb commands. Now all ddb commands are
>> stored in static array db_command_table. Problem is that if every
>> kernel component want to add some ddb_commands kernel programer have
>> to add entry to the ddb_command_table. If we use dynamic structure
>> like linked list we can add/remove commands in realtime.
>
> Sounds good.
>
>> API:
>>
>> int
>> db_reg_command(struct cmd_list *cmd_list, struct cmd_list  
>> **cmd_command,
>> char *cmd_name,*cmd_func);
>>
>> db_reg_help(*cmd_command,char* descr, char** cmd_func_arg);
>>
>> db_unreg_command(*cmd_list, char* cmd_name);
>>
>> struct cmd_list*
>> db_search_command(struct cmd_list*, char* cmd_name);
>>
>> /*this function will create default list of commands*/
>> db_init(struct cmd_list**);
>>
>> (db_get_help,db_get_func,db_get_cmd) ??
>>
>> Pro:
>>
>> LKM and other parts of kernel can register/unregister ddb commands in
>> easy way.
>>
>> more useable ddb.
>>
>>
>> Cons:
>> I have to initialize this list when ddb is run.(lot of malloc's for
>> every added command 2 one for command structure and second for help
>> (not needed))
>
> Actually, I think if we are clever about our list creation, we  
> don't have
> too much of an issue.
>
> Make the list a list of tables. So built-in commands are in one static
> table, and we have a static command list head. We then have a malloc'd
> list of:
>
> struct ddb_command_list_entry {
> 	TAILQ_ENTRY(ddb_command_list_entry)
> 				ddbcl_next;
> 	int			ddbcl_count;		/* count of cmds */
> 	struct ddb_command	*ddbcl_commands;
> };
>
> Yes, there will probably be a pad int in there too on LP64.
>
> The upshot of this is that everything other than these list entries  
> can be
> in text sections. We only need to malloc one of these command list  
> entry
> structures per table of commands.
>
> Take care,
>
> Bill

Hi

This is first review of my ddb command api. After some of list  
comunication with @wrstunden I decided to use 2 lists. One list for  
base commands and another for show subcommands(show registers). I do  
it this way because only show command has it's own subcommands.  
Difference between old ddb behavior and
pathched are:

1) added help command help {command} print command description and  
arguments.
2) I moved show all * commands one level up so from show all  
processes is show processes. (I'm looking for way to implement way to  
keep old interface behavior here. But everything looks to me too  
hackish :(. )

How to use this api.

in subsystem/lkm you have to include db_command_extr.h file
define array or one struct db_command's with proper values.

call db_add_command_tbl(type,*db_array);

type can be DDB_BASE_CMD or DDB_SHOW_CMD.

removing commands from list is done with

db_rem_command_tbl(type,*db_array);
Q: is here type needed or I have to search all lists and check there  
if *db_array address is present.


--Apple-Mail-8--449409839
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
	x-unix-mode=0644;
	name=db_cmd.diff
Content-Disposition: attachment;
	filename=db_cmd.diff

Index: db_command.c
===================================================================
RCS file: /cvsroot/src/sys/ddb/db_command.c,v
retrieving revision 1.96
diff -u -r1.96 db_command.c
--- db_command.c	30 Apr 2007 14:44:30 -0000	1.96
+++ db_command.c	9 Jul 2007 21:17:25 -0000
@@ -1,4 +1,39 @@
 /*	$NetBSD: db_command.c,v 1.96 2007/04/30 14:44:30 rmind Exp $	*/
+/*
+ * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Adam Hamsik.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 
 /*
  * Mach Operating System
@@ -51,6 +86,9 @@
 #include <sys/lockdebug.h>
 #include <sys/sleepq.h>
 
+/*include queue macros*/
+#include <sys/queue.h>
+
 #include <machine/db_machdep.h>		/* type definitions */
 
 #if defined(_KERNEL_OPT)
@@ -70,6 +108,7 @@
 #include <ddb/db_interface.h>
 #include <ddb/db_sym.h>
 #include <ddb/db_extern.h>
+#include <ddb/db_command_extr.h>
 
 #include <uvm/uvm_extern.h>
 #include <uvm/uvm_ddb.h>
@@ -83,7 +122,23 @@
 #define	CMD_FOUND	1
 #define	CMD_NONE	2
 #define	CMD_AMBIGUOUS	3
-#define	CMD_HELP	4
+
+#define CMD_SWITCH(result) do {          \
+        switch (result) {                \
+        case CMD_NONE:                   \
+		 db_printf("No such command\n"); \
+		 db_flush_lex();                 \
+		 return;                         \
+        case CMD_AMBIGUOUS:              \
+		 db_printf("Ambiguous\n");       \
+		 db_flush_lex();                 \
+		 return;                         \
+        default:                         \
+		 break;                          \
+        }                                \
+        } while(0)
+
+
 
 /*
  * Exported global variables
@@ -95,6 +150,23 @@
 db_addr_t	db_prev;
 db_addr_t	db_next;
 
+
+/*
+  New DDB api for adding and removing commands uses two lists, because
+  we use two types of commands
+  a) standard commands without subcommands -> reboot
+  b) show commands which are subcommands of show command -> show aio_jobs
+
+  ddb_add_cmd, ddb_rem_cmd use type (DDB_SHOW_CMD||DDB_BASE_CMD)argument to add them
+  to representativ lists.
+ */
+
+/*head of base commands list*/
+static struct db_cmd_tbl_en_head db_base_cmd_list;
+
+/*head of show commands list*/
+static struct db_cmd_tbl_en_head db_show_cmd_list;
+
 /*
  * if 'ed' style: 'dot' is set at start of last item printed,
  * and '+' points to next line.
@@ -102,14 +174,20 @@
  */
 static bool	 db_ed_style = true;
 
-static void	db_buf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
-static void	db_cmd_list(const struct db_command *);
+static void	db_cmd_list(const struct db_cmd_tbl_en_head *);
 static int	db_cmd_search(const char *, const struct db_command *,
 		    const struct db_command **);
-static void	db_command(const struct db_command **,
-		    const struct db_command *);
+static void	db_command(const struct db_command **);
+static int  db_get_list_type(const char *);
+static void db_init_commands(void);
+
+static void	db_buf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_event_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_fncall(db_expr_t, bool, db_expr_t, const char *);
+static void db_help_print_cmd(db_expr_t, bool, db_expr_t, const char *);
+static void	db_lock_print_cmd(db_expr_t, bool, db_expr_t, const char *);
+static void	db_mount_print_cmd(db_expr_t, bool, db_expr_t, const char *);
+static void	db_mbuf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_malloc_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_map_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_namecache_print_cmd(db_expr_t, bool, db_expr_t, const char *);
@@ -123,46 +201,61 @@
 static void	db_sync_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_uvmexp_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_vnode_print_cmd(db_expr_t, bool, db_expr_t, const char *);
-static void	db_lock_print_cmd(db_expr_t, bool, db_expr_t, const char *);
-static void	db_mount_print_cmd(db_expr_t, bool, db_expr_t, const char *);
-static void	db_mbuf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
+
 
 /*
  * 'show' commands
  */
-
-static const struct db_command db_show_all_cmds[] = {
-	{ "callout",	db_show_callout,	0, NULL },
-	{ "pages",	db_show_all_pages,	0, NULL },
-	{ "procs",	db_show_all_procs,	0, NULL },
-	{ "pools",	db_show_all_pools,	0, NULL },
-	{ NULL, 	NULL, 			0, NULL }
-};
-
+#if defined(DDB_VERBOSE_HELP)
+#define DDB_ADD_CMD(name,funct,type,cmd_descr,cmd_arg)\
+ name,funct,type,cmd_descr,cmd_arg
+#else
+#define DDB_ADD_CMD(name,funct,type,cmd_descr,cmd_arg)\
+ name,funct,type,NULL,NULL
+#endif
+   
 static const struct db_command db_show_cmds[] = {
-	{ "aio_jobs",	db_show_aio_jobs,	0,	NULL },
-	{ "all",	NULL,			0,	db_show_all_cmds },
+  /*added from all sub cmds*/
+  { DDB_ADD_CMD("callout",  db_show_callout,	0,NULL,NULL) },
+  { DDB_ADD_CMD("pages",	db_show_all_pages,	0,NULL,NULL) },
+  { DDB_ADD_CMD("procs",	db_show_all_procs,	0,NULL,NULL) },
+  { DDB_ADD_CMD("pools",	db_show_all_pools,	0,NULL,NULL) },
+  /*added from all sub cmds*/
+  { DDB_ADD_CMD("aio_jobs",	db_show_aio_jobs,	0,"Show aio jobs", NULL) },
 #if defined(INET) && (NARP > 0)
-	{ "arptab",	db_show_arptab,		0,	NULL },
+  { DDB_ADD_CMD("arptab",	db_show_arptab,		0,NULL,NULL) },
 #endif
-	{ "breaks",	db_listbreak_cmd, 	0,	NULL },
-	{ "buf",	db_buf_print_cmd,	0,	NULL },
-	{ "event",	db_event_print_cmd,	0,	NULL },
-	{ "lock",	db_lock_print_cmd,	0,	NULL },
-	{ "malloc",	db_malloc_print_cmd,	0,	NULL },
-	{ "map",	db_map_print_cmd,	0,	NULL },
-	{ "mount",	db_mount_print_cmd,	0,	NULL },
-	{ "mbuf",	db_mbuf_print_cmd,	0,	NULL },
-	{ "ncache",	db_namecache_print_cmd,	0,	NULL },
-	{ "object",	db_object_print_cmd,	0,	NULL },
-	{ "page",	db_page_print_cmd,	0,	NULL },
-	{ "pool",	db_pool_print_cmd,	0,	NULL },
-	{ "registers",	db_show_regs,		0,	NULL },
-	{ "sched_qs",	db_show_sched_qs,	0,	NULL },
-	{ "uvmexp",	db_uvmexp_print_cmd,	0,	NULL },
-	{ "vnode",	db_vnode_print_cmd,	0,	NULL },
-	{ "watches",	db_listwatch_cmd, 	0,	NULL },
-	{ NULL,		NULL,			0,	NULL }
+  { DDB_ADD_CMD("breaks",	db_listbreak_cmd, 	0,"Display all breaks.", NULL) },
+  { DDB_ADD_CMD("buf",	db_buf_print_cmd,	0,
+				"Print the struct buf at address.", "[/f] address") },
+  { DDB_ADD_CMD("event",	db_event_print_cmd,	0,
+				"Print all the non-zero evcnt(9) event counters.", "[/f]") },
+  { DDB_ADD_CMD("lock",	db_lock_print_cmd,	0,NULL,NULL) },
+  { DDB_ADD_CMD("malloc",	db_malloc_print_cmd,0,NULL,NULL) },
+  { DDB_ADD_CMD("map",	db_map_print_cmd,	0,
+				"Print the vm_map at address.", "[/f] address") },
+  { DDB_ADD_CMD("mount",	db_mount_print_cmd,	0,
+				"Print the mount structure at address.", "[/f] address") },
+  { DDB_ADD_CMD("mbuf",	db_mbuf_print_cmd,	0,NULL,NULL) },
+  { DDB_ADD_CMD("ncache",	db_namecache_print_cmd,	0,
+				"Dump the namecache list.", "address") },
+  { DDB_ADD_CMD("object",	db_object_print_cmd,	0,
+				"Print the vm_object at address.", "[/f] address") },
+  { DDB_ADD_CMD("page",	db_page_print_cmd,	0,
+				"Print the vm_page at address.", "[/f] address") },
+  { DDB_ADD_CMD("pool",	db_pool_print_cmd,	0,
+				"Print the pool at address.", "[/clp] address") },
+  { DDB_ADD_CMD("registers",	db_show_regs,		0,
+				"Display the register set.", "[/u]") },
+  { DDB_ADD_CMD("sched_qs",	db_show_sched_qs,	0,
+				"Print the state of the scheduler's run queues.",NULL) },
+  { DDB_ADD_CMD("uvmexp",	db_uvmexp_print_cmd, 0,
+				"Print a selection of UVM counters and statistics.", NULL) },
+  { DDB_ADD_CMD("vnode",	db_vnode_print_cmd,	0,
+				"Print the vnode at address.", "[/f] address") },
+  { DDB_ADD_CMD("watches",	db_listwatch_cmd, 	0,
+				"Display all watchpoints.", NULL) },
+  { DDB_ADD_CMD(NULL,		NULL,			0,NULL,NULL) }
 };
 
 /* arch/<arch>/<arch>/db_interface.c */
@@ -171,45 +264,82 @@
 #endif
 
 static const struct db_command db_command_table[] = {
-	{ "b",		db_breakpoint_cmd,	0,		NULL },
-	{ "break",	db_breakpoint_cmd,	0,		NULL },
-	{ "bt",		db_stack_trace_cmd,	0,		NULL },
-	{ "c",		db_continue_cmd,	0,		NULL },
-	{ "call",	db_fncall,		CS_OWN,		NULL },
-	{ "callout",	db_show_callout,	0,		NULL },
-	{ "continue",	db_continue_cmd,	0,		NULL },
-	{ "d",		db_delete_cmd,		0,		NULL },
-	{ "delete",	db_delete_cmd,		0,		NULL },
-	{ "dmesg",	db_dmesg,		0,		NULL },
-	{ "dwatch",	db_deletewatch_cmd,	0,		NULL },
-	{ "examine",	db_examine_cmd,		CS_SET_DOT, 	NULL },
-	{ "kill",	db_kill_proc,		CS_OWN,		NULL },
-#ifdef KGDB
-	{ "kgdb",	db_kgdb_cmd,		0,		NULL },
-#endif
-#ifdef DB_MACHINE_COMMANDS
-	{ "machine",	NULL,			0, db_machine_command_table },
-#endif
-	{ "match",	db_trace_until_matching_cmd,0,		NULL },
-	{ "next",	db_trace_until_matching_cmd,0,		NULL },
-	{ "p",		db_print_cmd,		0,		NULL },
-	{ "print",	db_print_cmd,		0,		NULL },
-	{ "ps",		db_show_all_procs,	0,		NULL },
-	{ "reboot",	db_reboot_cmd,		CS_OWN,		NULL },
-	{ "s",		db_single_step_cmd,	0,		NULL },
-	{ "search",	db_search_cmd,		CS_OWN|CS_SET_DOT, NULL },
-	{ "set",	db_set_cmd,		CS_OWN,		NULL },
-	{ "show",	NULL,			0,		db_show_cmds },
-	{ "sifting",	db_sifting_cmd,		CS_OWN,		NULL },
-	{ "step",	db_single_step_cmd,	0,		NULL },
-	{ "sync",	db_sync_cmd,		CS_OWN,		NULL },
-	{ "trace",	db_stack_trace_cmd,	0,		NULL },
-	{ "until",	db_trace_until_call_cmd,0,		NULL },
-	{ "w",		db_write_cmd,		CS_MORE|CS_SET_DOT, NULL },
-	{ "watch",	db_watchpoint_cmd,	CS_MORE,	NULL },
-	{ "write",	db_write_cmd,		CS_MORE|CS_SET_DOT, NULL },
-	{ "x",		db_examine_cmd,		CS_SET_DOT, 	NULL },
-	{ NULL, 	NULL,			0,		NULL }
+  { DDB_ADD_CMD("b",		db_breakpoint_cmd,	0,
+				"Set a breakpoint at address", "[/u] address[,count].") },
+  { DDB_ADD_CMD("break",	db_breakpoint_cmd,	0,
+				"Set a breakpoint at address", "[/u] address[,count].") },
+  { DDB_ADD_CMD("bt",		db_stack_trace_cmd,	0,
+				"Show backtrace.", "See help trace.") },
+  { DDB_ADD_CMD("c",		db_continue_cmd,	0,"Continue execution.", "[/c]") },
+  { DDB_ADD_CMD("call",	db_fncall,		CS_OWN,
+				"Call the function", "address[(expression[,...])]") },
+  { DDB_ADD_CMD("callout",	db_show_callout,	0, NULL, NULL) },
+  { DDB_ADD_CMD("continue",	db_continue_cmd,	0,"Continue execution.", "[/c]") },
+  { DDB_ADD_CMD("d",		db_delete_cmd,		0,
+				"Delete a breakpoint.", "address | #number") },
+  { DDB_ADD_CMD("delete",	db_delete_cmd,		0,
+				"Delete a breakpoint.", "address | #number") },
+  { DDB_ADD_CMD("dmesg",	db_dmesg,		0,
+				"Show kernel message buffer.", "[count]") },
+  { DDB_ADD_CMD("dwatch",	db_deletewatch_cmd,	0,
+				"Delete the watchpoint.", "address") },
+  { DDB_ADD_CMD("examine",	db_examine_cmd,		CS_SET_DOT,
+				"Display the address locations.",
+				"[/modifier] address[,count]") },
+  { DDB_ADD_CMD("help",   db_help_print_cmd, CS_OWN,"Display help about commands",
+				"Use other commands as arguments.") },
+  { DDB_ADD_CMD("kill",	db_kill_proc,		CS_OWN,
+				"Send a signal to the process","pid[,signal_number]") },
+  /*#ifdef KGDB
+	{ DDB_ADD_CMD("kgdb",	db_kgdb_cmd,		0,		NULL) },
+	#endif
+	#ifdef DB_MACHINE_COMMANDS
+	{ DDB_ADD_CMD("machine",	NULL,			0, NULL,NULL,db_machine_command_table) },
+	#endif*/
+  { DDB_ADD_CMD("match",	db_trace_until_matching_cmd,0,
+				"Stop at the matching return instruction.","See help next") },
+  { DDB_ADD_CMD("next",	db_trace_until_matching_cmd,0,
+				"Stop at the matching return instruction.","[/p]") },
+  { DDB_ADD_CMD("p",		db_print_cmd,		0,
+				"Print address according to the format.",
+				"[/axzodurc] address [address ...]") },
+  { DDB_ADD_CMD("print",	db_print_cmd,		0,
+				"Print address according to the format.",
+				"[/axzodurc] address [address ...]") },
+  { DDB_ADD_CMD("ps",		db_show_all_procs,	0,
+				"Print all processes.","See show all procs") },
+  { DDB_ADD_CMD("reboot",	db_reboot_cmd,		CS_OWN,
+				"Reboot","0x1  RB_ASKNAME, 0x2 RB_SINGLE, 0x4 RB_NOSYNC, 0x8 RB_HALT,"
+				"0x40 RB_KDB, 0x100 RB_DUMP, 0x808 RB_POWERDOWN") },
+  { DDB_ADD_CMD("s",		db_single_step_cmd,	0,
+				"Single-step count times.","[/p] [,count]") },
+  { DDB_ADD_CMD("search",	db_search_cmd,		CS_OWN|CS_SET_DOT,
+				"Search memory from address for value.",
+				"[/bhl] address value [mask] [,count]") },
+  { DDB_ADD_CMD("set",	db_set_cmd,		CS_OWN,
+				"Set the named variable","$variable [=] expression") },
+  { DDB_ADD_CMD("show",	NULL,			0,"Show kernel stats.", NULL) },
+  { DDB_ADD_CMD("sifting",	db_sifting_cmd,		CS_OWN,
+				"Search the symbol tables ","[/F] string") },
+  { DDB_ADD_CMD("step",	db_single_step_cmd,	0,
+				"Single-step count times.","[/p] [,count]") },
+  { DDB_ADD_CMD("sync",	db_sync_cmd,		CS_OWN,
+				"Force a crash dump, and then reboot.",NULL) },
+  { DDB_ADD_CMD("trace",	db_stack_trace_cmd,	0,
+				"Stack trace from frame-address.",
+				"[/u[l]] [frame-address][,count]") },
+  { DDB_ADD_CMD("until",	db_trace_until_call_cmd,0,
+				"Stop at the next call or return instruction.","[/p]") },
+  { DDB_ADD_CMD("w",		db_write_cmd,		CS_MORE|CS_SET_DOT,
+				"Set a watchpoint for a region. ","address[,size]") },
+  { DDB_ADD_CMD("watch",	db_watchpoint_cmd,	CS_MORE,
+				"Set a watchpoint for a region. ","address[,size]") },
+  { DDB_ADD_CMD("write",	db_write_cmd,		CS_MORE|CS_SET_DOT,
+				"Write the expressions at succeeding locations.",
+				"[/bhl] address expression [expression ...]") },
+  { DDB_ADD_CMD("x",		db_examine_cmd,		CS_SET_DOT,
+				"Display the address locations.", "[/modifier] address[,count]") },
+  { DDB_ADD_CMD(NULL, 	NULL,		   0, NULL, NULL) }
 };
 
 static const struct db_command	*db_last_command = NULL;
@@ -220,22 +350,23 @@
 #endif /* defined(DDB_COMMANDONENTER) */
 #define	DB_LINE_SEP	';'
 
+
+
+
 /*
  * Utility routine - discard tokens through end-of-line.
  */
 void
-db_skip_to_eol(void)
-{
+db_skip_to_eol(void){
+  
 	int t;
-
 	do {
 		t = db_read_token();
 	} while (t != tEOL);
 }
 
 void
-db_error(const char *s)
-{
+db_error(const char *s){
 
 	if (s)
 		db_printf("%s", s);
@@ -243,9 +374,10 @@
 	longjmp(db_recover);
 }
 
+/*Execute commandlist after ddb start*/
 static void
-db_execute_commandlist(const char *cmdlist)
-{
+db_execute_commandlist(const char *cmdlist){
+  
 	const char *cmd = cmdlist;
 	const struct db_command	*dummy = NULL;
 
@@ -256,278 +388,525 @@
 			ep++;
 		}
 		db_set_line(cmd, ep);
-		db_command(&dummy, db_command_table);
+		db_command(&dummy);
 		cmd = ep;
 		if (*cmd == DB_LINE_SEP) {
-			cmd++;
+		  cmd++;
 		}
 	}
 }
 
-void
-db_command_loop(void)
-{
-	label_t	db_jmpbuf;
-	label_t	*savejmp;
+/*Initialize ddb command tables*/
+static void
+db_init_commands(void){
 
-	/*
-	 * Initialize 'prev' and 'next' to dot.
-	 */
-	db_prev = db_dot;
-	db_next = db_dot;
+  TAILQ_INIT(&db_base_cmd_list);
+   TAILQ_INIT(&db_show_cmd_list);
+
+   printf("Initialize command tables\n");
+
+
+   (void)db_add_command_tbl(DDB_BASE_CMD,db_command_table);
+   (void)db_add_command_tbl(DDB_BASE_CMD,db_machine_command_table);
+   
+   (void)db_add_command_tbl(DDB_SHOW_CMD,db_show_cmds);
 
-	db_cmd_loop_done = 0;
 
-	savejmp = db_recover;
-	db_recover = &db_jmpbuf;
-	(void) setjmp(&db_jmpbuf);
+  /*  (void)db_rem_command_tbl(DDB_BASE_CMD,db_command_table);
+	  (void)db_rem_command_tbl(DDB_SHOW_CMD,db_show_cmds);*/
+   return;
+}
+
+
+/*
+ * Add command table to the specified list
+ * Arg:
+ * int type specifies type of command DDB_SHOW_CMD|DDB_BASE_CMD
+ * *cmd_tbl poiter to static allocated db_command table
+ *
+ *Command talbe have to be NULL terminated array of struct db_command
+ */
+int
+db_add_command_tbl(uint8_t type, const struct db_command *cmd_tbl){
 
-	db_execute_commandlist(db_cmd_on_enter);
+  uint32_t i=0; /*XXX what is better count number of elements here or use num argument ?*/
+  struct db_cmd_tbl_en *list_ent;
+  const struct db_command *cmd;
+
+  if (cmd_tbl->name != 0) {   /*I have to check this because e.g. machine commands can be NULL*/
+
+	if ((list_ent = malloc (sizeof(struct db_cmd_tbl_en),M_TEMP,M_ZERO)) == NULL)
+	  return (ENOMEM);
+
+	list_ent->db_cmd=cmd_tbl;
+  
+
+	for (cmd = cmd_tbl; cmd->name != 0; cmd++)
+	  i++;
+
+	list_ent->db_cmd_num=i;
+	printf("Number of elements :%d \n",i);
+
+	/*Type specify list*/
+	if (type == DDB_BASE_CMD){
+	  printf("Adding base cmds\n");
+	  if (TAILQ_EMPTY(&db_base_cmd_list))
+		/*If head is empty we add first table here*/
+		TAILQ_INSERT_HEAD(&db_base_cmd_list,list_ent,db_cmd_next); 
+	  
+	  else 
+		TAILQ_INSERT_TAIL(&db_base_cmd_list,list_ent,db_cmd_next); /*new commands go to the end*/
+	  
+	} else if (type == DDB_SHOW_CMD){
+	  printf("Adding Show cmds\n");
+
+	  if (TAILQ_EMPTY(&db_show_cmd_list))
+		/*If head is empty we add first table here*/
+		TAILQ_INSERT_HEAD(&db_show_cmd_list,list_ent,db_cmd_next);
 
-	while (!db_cmd_loop_done) {
-		if (db_print_position() != 0)
-			db_printf("\n");
-		db_output_line = 0;
+	  else
+		TAILQ_INSERT_TAIL(&db_show_cmd_list,list_ent,db_cmd_next); /*new commands go to the end*/
+
+	} else
+	  return (ENOENT);
+  }	
+  return 0;
+}
+/*
+ *Remove command table specified with db_cmd address == cmd_tbl
+ */
+int
+db_rem_command_tbl(uint8_t type,const struct db_command *cmd_tbl){
+
+  struct db_cmd_tbl_en *list_ent;
+  int error=ENOENT;
+  
+  if  (db_base_cmd_list.tqh_first == NULL)
+	return (error);
+  printf("Removing command table\n");
+
+  /*I go through the list, selected with type and look for
+	cmd_tbl address in list entries.*/
+  if (type == DDB_BASE_CMD){
+
+	TAILQ_FOREACH(list_ent,&db_base_cmd_list,db_cmd_next){
+	  if (list_ent->db_cmd == cmd_tbl){
+		/*first I need to remove command table from TAILQ list and then I can freed it*/
+		TAILQ_REMOVE(&db_base_cmd_list,list_ent,db_cmd_next);
+		free(list_ent,M_TEMP);
+		error=0;/*I succefully find address so I return 0*/
+	  }
+	}
+
+  }else if (type == DDB_SHOW_CMD){
+
+	TAILQ_FOREACH(list_ent,&db_show_cmd_list,db_cmd_next){
+	  if (list_ent->db_cmd == cmd_tbl){
+		TAILQ_REMOVE(&db_show_cmd_list,list_ent,db_cmd_next);
+		free(list_ent,M_TEMP);
+		error=0;
+	  }
+	}
+
+  } else
+	error=EINVAL;
+
+  return (error);
+}
+
+
+void
+db_command_loop(void){
+  
+  label_t	db_jmpbuf;
+  label_t	*savejmp;
+
+  /*
+   * Initialize 'prev' and 'next' to dot.
+   */
+  db_prev = db_dot;
+  db_next = db_dot;
+
+  db_cmd_loop_done = 0;
+
+  /*save context for return from ddb*/
+  savejmp = db_recover;
+  db_recover = &db_jmpbuf;
+  (void) setjmp(&db_jmpbuf);
+
+  /*Init default command tables add machine, base,
+	show command tables to the list*/
+  (void) db_init_commands();
+
+  /*Execute default ddb start commands*/
+  db_execute_commandlist(db_cmd_on_enter);
+
+  while (!db_cmd_loop_done) {
+	if (db_print_position() != 0)
+	  db_printf("\n");
+	db_output_line = 0;
 
 
 #ifdef MULTIPROCESSOR
-		db_printf("db{%ld}> ", (long)cpu_number());
+	db_printf("db{%ld}> ", (long)cpu_number());
 #else
-		db_printf("db> ");
+	db_printf("db> ");
 #endif
-		(void) db_read_line();
+	(void) db_read_line();
 
-		db_command(&db_last_command, db_command_table);
-	}
+	db_command(&db_last_command);
+  }
 
-	db_recover = savejmp;
+  db_recover = savejmp;
 }
 
 /*
- * Search for command prefix.
+ * Search for command table for command prefix
+ * ret: CMD_UNIQUE -> completly match cmd prefix
+ *      CMD_FOUND  -> partialy match cmd prefix
+ *      CMD_AMBIGIOUS ->more partialy matches
+ *      CMD_NONE   -> command not found
  */
 static int
-db_cmd_search(const char *name, const struct db_command *table,
-    const struct db_command **cmdp)
-{
-	const struct db_command	*cmd;
-	int			result = CMD_NONE;
-
-	for (cmd = table; cmd->name != 0; cmd++) {
-		const char *lp;
-		const char *rp;
-		int  c;
-
-		lp = name;
-		rp = cmd->name;
-		while ((c = *lp) == *rp) {
-			if (c == 0) {
-				/* complete match */
-				*cmdp = cmd;
-				return (CMD_UNIQUE);
-			}
-			lp++;
-			rp++;
-		}
-		if (c == 0) {
-			/* end of name, not end of command -
-			   partial match */
-			if (result == CMD_FOUND) {
-				result = CMD_AMBIGUOUS;
-				/* but keep looking for a full match -
-				   this lets us match single letters */
-			} else {
-				*cmdp = cmd;
-				result = CMD_FOUND;
-			}
-		}
+db_cmd_search(const char *name,const struct db_command *table,
+			  const struct db_command **cmdp){
+  
+  const struct db_command	*cmd;
+  int			result = CMD_NONE;
+
+  for (cmd = table; cmd->name != 0; cmd++) {
+	const char *lp;
+	const char *rp;
+	int  c;
+
+	lp = name;
+	rp = cmd->name;
+	while ((c = *lp) == *rp) {
+	  if (c == 0) {
+		/* complete match */
+		*cmdp = cmd;
+		return (CMD_UNIQUE);
+	  }
+	  lp++;
+	  rp++;
 	}
-	if (result == CMD_NONE) {
-		/* check for 'help' */
-		if (name[0] == 'h' && name[1] == 'e'
-		    && name[2] == 'l' && name[3] == 'p')
-			result = CMD_HELP;
+	if (c == 0) {
+	  /* end of name, not end of command -
+		 partial match */
+	  if (result == CMD_FOUND) {
+		result = CMD_AMBIGUOUS;
+		/* but keep looking for a full match -
+		   this lets us match single letters */
+	  } else {
+		*cmdp = cmd;
+		result = CMD_FOUND;
+	  }
 	}
-	return (result);
+  }
+  return (result);
 }
 
 static void
-db_cmd_list(const struct db_command *table)
-{
-	int	 i, j, w, columns, lines, width=0, numcmds;
-	const char	*p;
+db_cmd_list(const struct db_cmd_tbl_en_head *list){
 
-	for (numcmds = 0; table[numcmds].name != NULL; numcmds++) {
-		w = strlen(table[numcmds].name);
-		if (w > width)
-			width = w;
+  struct db_cmd_tbl_en *list_ent;
+  const struct db_command *table;
+  int	 i, j, w, columns, lines, width=0, numcmds=0;
+  const char	*p;
+
+  TAILQ_FOREACH(list_ent,list,db_cmd_next){	  
+	numcmds+=list_ent->db_cmd_num;
+	table=list_ent->db_cmd;
+	
+	for (i = 0; i<list_ent->db_cmd_num; i++) {
+	  w = strlen(table[i].name);
+	  if (w > width)
+		width = w;
 	}
-	width = DB_NEXT_TAB(width);
+  }
+
+  width = DB_NEXT_TAB(width);
+
+  columns = db_max_width / width;
+  if (columns == 0)
+	columns = 1;
 
-	columns = db_max_width / width;
-	if (columns == 0)
-		columns = 1;
-	lines = (numcmds + columns - 1) / columns;
+  
+  TAILQ_FOREACH(list_ent,list,db_cmd_next){
+	table=list_ent->db_cmd;
+
+	lines = (list_ent->db_cmd_num + columns - 1) / columns;
+	
 	for (i = 0; i < lines; i++) {
-		for (j = 0; j < columns; j++) {
-			p = table[j * lines + i].name;
-			if (p)
-				db_printf("%s", p);
-			if (j * lines + i + lines >= numcmds) {
-				db_putchar('\n');
-				break;
-			}
-			if (p) {
-				w = strlen(p);
-				while (w < width) {
-					w = DB_NEXT_TAB(w);
-					db_putchar('\t');
-				}
-			}
+	  for (j = 0; j < columns; j++) {
+		p = table[j * lines + i].name;
+		if (p)
+		  db_printf("%s", p);
+		if (j * lines + i + lines >= list_ent->db_cmd_num){
+		  db_putchar('\n');
+		  break;
+		}
+		if (p) {
+		  w = strlen(p);
+		  while (w < width) {
+			w = DB_NEXT_TAB(w);
+			db_putchar('\t');
+		  }
 		}
+	  }
 	}
+  }
+  return;
 }
 
-static void
-db_command(const struct db_command **last_cmdp,
-    const struct db_command *cmd_table)
-{
-	const struct db_command	*cmd;
-	int		t;
-	char		modif[TOK_STRING_SIZE];
-	db_expr_t	addr, count;
-	bool		have_addr = false;
-	int		result;
-	static db_expr_t last_count = 0;
+static int
+db_get_list_type(const char *name){
 
-	cmd = NULL;	/* XXX gcc */
+  const struct db_command    *cmd;
+  struct db_cmd_tbl_en *list_ent;
+  int error,ret=-1;
+
+  /*I go through base cmd list and search command with name(form cmd line)*/
+  TAILQ_FOREACH(list_ent,&db_base_cmd_list,db_cmd_next){
+	/*cmd_search returns CMD_UNIQUE, CMD_FOUND ...
+	 *CMD_UNIQUE when name was completly matched to cmd->name
+	 *CMD_FOUND when name was only partially matched to cmd->name
+	 */
+	error=db_cmd_search(name,list_ent->db_cmd,&cmd);
+	if (error == CMD_UNIQUE){ /*because I can't have better result then CMD_UNIQUE I break*/
+	  if (strncmp(cmd->name,"show",4) == 0){
+		ret=DDB_SHOW_CMD;
+		break;
+	  } else {
+		ret=DDB_BASE_CMD;
+		break;
+	  }
+	  
+	} else if (error == CMD_FOUND){/*I have only partially matched name so I continue search*/
+	  if (strncmp(cmd->name,"show",4) == 0)
+		ret=DDB_SHOW_CMD;
+	  else
+		ret=DDB_BASE_CMD;
+	}
+  }
+  
+  return(ret);
+}
 
-	t = db_read_token();
-	if ((t == tEOL) || (t == tCOMMA)) {
-		/*
-		 * An empty line repeats last command, at 'next'.
-		 * Only a count repeats the last command with the new count.
-		 */
-		cmd = *last_cmdp;
-		addr = (db_expr_t)db_next;
-		if (t == tCOMMA) {
-			if (!db_expression(&count)) {
-				db_printf("Count missing\n");
-				db_flush_lex();
-				return;
-			}
-		} else
-			count = last_count;
-		have_addr = false;
-		modif[0] = '\0';
-		db_skip_to_eol();
-	} else if (t == tEXCL) {
-		db_fncall(0, 0, 0, NULL);
+/*
+ *Parse command line and execute apropriate function.
+ */
+static void
+db_command(const struct db_command **last_cmdp){
+  const struct db_command *command;
+  struct db_cmd_tbl_en *list_ent;
+  struct db_cmd_tbl_en_head *list;
+  
+  int		t;
+  char		modif[TOK_STRING_SIZE];
+  db_expr_t	addr, count;
+  bool		have_addr = false;
+  int		result;
+  static db_expr_t last_count = 0;
+  
+  command = NULL;	/* XXX gcc */
+
+  t = db_read_token();
+  if ((t == tEOL) || (t == tCOMMA)) {
+	/*
+	 * An empty line repeats last command, at 'next'.
+	 * Only a count repeats the last command with the new count.
+	 */
+	command = *last_cmdp;
+	addr = (db_expr_t)db_next;
+	if (t == tCOMMA) {
+	  if (!db_expression(&count)) {
+		db_printf("Count missing\n");
+		db_flush_lex();
 		return;
-	} else if (t != tIDENT) {
-		db_printf("?\n");
+	  }
+	} else
+	  count = last_count;
+	have_addr = false;
+	modif[0] = '\0';
+	db_skip_to_eol();
+
+  } else if (t == tEXCL) {
+	db_fncall(0, 0, 0, NULL);
+	return;
+
+  } else if (t != tIDENT) {
+	db_printf("?\n");
+	db_flush_lex();
+	return;
+
+  } else {
+	switch(db_get_list_type(db_tok_string)){
+	  
+	case DDB_BASE_CMD:
+	  list=&db_base_cmd_list;
+	  break;
+	case DDB_SHOW_CMD:
+	  list=&db_show_cmd_list;
+
+	  t = db_read_token(); /*I need to read show subcommand If show command list is used.*/
+
+	  if (t != tIDENT) {
+		/*if only show command is executed I print all subcommands*/
+		db_cmd_list(&db_show_cmd_list); 
 		db_flush_lex();
 		return;
-	} else {
-		/*
-		 * Search for command
-		 */
-		while (cmd_table) {
-			result = db_cmd_search(db_tok_string, cmd_table, &cmd);
-			switch (result) {
-			case CMD_NONE:
-				db_printf("No such command\n");
-				db_flush_lex();
-				return;
-			case CMD_AMBIGUOUS:
-				db_printf("Ambiguous\n");
-				db_flush_lex();
-				return;
-			case CMD_HELP:
-				db_cmd_list(cmd_table);
-				db_flush_lex();
-				return;
-			default:
-				break;
-			}
-			if ((cmd_table = cmd->more) != 0) {
-				t = db_read_token();
-				if (t != tIDENT) {
-					db_cmd_list(cmd_table);
-					db_flush_lex();
-					return;
-				}
-			}
+	  }
+	  
+	  break;
+	default:
+	  db_printf("No such command\n");
+	  db_flush_lex();                 
+	  return;
+	}
+
+	TAILQ_FOREACH(list_ent,list,db_cmd_next){
+	  result = db_cmd_search(db_tok_string, list_ent->db_cmd, &command);
+	  /*after CMD_UNIQUE in cmd_list only one same command name is possible*/
+	  if (result == CMD_UNIQUE)
+		break;
+	}
+
+	if ((command->flag & CS_OWN) == 0) {
+
+	  /*
+	   * Standard syntax:
+	   * command [/modifier] [addr] [,count]
+	   */
+	  t = db_read_token(); /*get modifier*/
+	  if (t == tSLASH) { 
+		t = db_read_token();
+		if (t != tIDENT) {
+		  db_printf("Bad modifier\n");
+		  db_flush_lex();
+		  return;
 		}
+		strlcpy(modif, db_tok_string, sizeof(modif)); /*save modifier*/
+		
+	  } else {
+		db_unread_token(t);
+		modif[0] = '\0';
+	  }
 
-		if ((cmd->flag & CS_OWN) == 0) {
-			/*
-			 * Standard syntax:
-			 * command [/modifier] [addr] [,count]
-			 */
-			t = db_read_token();
-			if (t == tSLASH) {
-				t = db_read_token();
-				if (t != tIDENT) {
-					db_printf("Bad modifier\n");
-					db_flush_lex();
-					return;
-				}
-				strlcpy(modif, db_tok_string, sizeof(modif));
-			} else {
-				db_unread_token(t);
-				modif[0] = '\0';
-			}
+	  if (db_expression(&addr)) { /*get address*/
+		db_dot = (db_addr_t) addr;
+		db_last_addr = db_dot;
+		have_addr = true;
+	  } else {
+		addr = (db_expr_t) db_dot;
+		have_addr = false;
+	  }
 
-			if (db_expression(&addr)) {
-				db_dot = (db_addr_t) addr;
-				db_last_addr = db_dot;
-				have_addr = true;
-			} else {
-				addr = (db_expr_t) db_dot;
-				have_addr = false;
-			}
-			t = db_read_token();
-			if (t == tCOMMA) {
-				if (!db_expression(&count)) {
-					db_printf("Count missing\n");
-					db_flush_lex();
-					return;
-				}
-			} else {
-				db_unread_token(t);
-				count = -1;
-			}
-			if ((cmd->flag & CS_MORE) == 0) {
-				db_skip_to_eol();
-			}
+	  t = db_read_token();
+	  if (t == tCOMMA) { /*Get count*/
+		if (!db_expression(&count)) {
+		  db_printf("Count missing\n");
+		  db_flush_lex();
+		  return;
 		}
+	  } else { 
+		db_unread_token(t);
+		count = -1;
+	  }
+	  if ((command->flag & CS_MORE) == 0) {
+		db_skip_to_eol();
+	  }
 	}
-	*last_cmdp = cmd;
-	last_count = count;
-	if (cmd != 0) {
-		/*
-		 * Execute the command.
-		 */
-		(*cmd->fcn)(addr, have_addr, count, modif);
-
-		if (cmd->flag & CS_SET_DOT) {
-			/*
-			 * If command changes dot, set dot to
-			 * previous address displayed (if 'ed' style).
-			 */
-			if (db_ed_style)
-				db_dot = db_prev;
-			else
-				db_dot = db_next;
-		} else {
-			/*
-			 * If command does not change dot,
-			 * set 'next' location to be the same.
-			 */
-			db_next = db_dot;
-		}
+  }
+
+  *last_cmdp = command;
+  last_count = count;
+
+  if (command != 0) {
+	/*
+	 * Execute the command.
+	 */
+	(*command->fcn)(addr, have_addr, count, modif);
+
+	if (command->flag & CS_SET_DOT) {
+	  /*
+	   * If command changes dot, set dot to
+	   * previous address displayed (if 'ed' style).
+	   */
+	  if (db_ed_style)
+		db_dot = db_prev;
+	  else
+		db_dot = db_next;
+	} else {
+	  /*
+	   * If command does not change dot,
+	   * set 'next' location to be the same.
+	   */
+	  db_next = db_dot;
 	}
+  }
+}
+/*
+ *Print help for commands
+ *
+ */
+static void
+db_help_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
+				  const char *modif){
+  
+  const struct db_cmd_tbl_en_head *list;
+  const struct db_cmd_tbl_en *list_ent;
+  const struct db_command *help;
+  int t,result;
+  
+  t=db_read_token();
+  /*I have also another command not only help*/
+  if (t == tIDENT){
+
+	switch(db_get_list_type(db_tok_string)){
+
+	case DDB_BASE_CMD:
+	  list=&db_base_cmd_list;
+	  break;
+	case DDB_SHOW_CMD:
+	  list=&db_show_cmd_list;
+	  /*I need to read show subcommand If show command list is used.*/
+	  t = db_read_token(); 
+
+	  if (t != tIDENT) {
+		/*if only show command is executed I print all subcommands*/
+		db_cmd_list(&db_show_cmd_list);
+		db_flush_lex();
+		return;
+	  }
+	  
+	  break;
+	default:
+	  db_printf("No such command\n");
+	  db_flush_lex();
+	  return;
+	}
+
+	TAILQ_FOREACH(list_ent,list,db_cmd_next){
+	  result = db_cmd_search(db_tok_string, list_ent->db_cmd, &help);
+	  /*after CMD_UNIQUE in cmd_list only one same command name is possible*/
+	  if (result == CMD_UNIQUE)
+		break;
+	}
+
+	/*print help*/
+	if (help->cmd_arg != NULL)
+	  db_printf("Command: %s Arguments: %s\n Descr: %s\n",
+				help->name,help->cmd_arg,help->cmd_descr);
+	else
+	  db_printf("Command: %s Doesn't have any help message included.\n",
+				help->name);
+
+  } else
+	/*print base commands*/
+	db_cmd_list(&db_base_cmd_list);
+		
+	return;
 }
 
 /*ARGSUSED*/
Index: db_command.h
===================================================================
RCS file: /cvsroot/src/sys/ddb/db_command.h,v
retrieving revision 1.27
diff -u -r1.27 db_command.h
--- db_command.h	22 Feb 2007 04:38:05 -0000	1.27
+++ db_command.h	9 Jul 2007 21:17:28 -0000
@@ -1,5 +1,41 @@
 /*	$NetBSD: db_command.h,v 1.27 2007/02/22 04:38:05 matt Exp $	*/
 
+/*-
+ * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Adam Hamsik.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
 /*
  * Mach Operating System
  * Copyright (c) 1991,1990 Carnegie Mellon University
@@ -29,11 +65,6 @@
  *	Date:	7/90
  */
 
-/*
- * Command loop declarations.
- */
-struct db_command;
-
 void	db_skip_to_eol(void);
 void	db_command_loop(void);
 void	db_error(const char *) __attribute__((__noreturn__));
@@ -41,23 +72,23 @@
 extern db_addr_t db_dot;	/* current location */
 extern db_addr_t db_last_addr;	/* last explicit address typed */
 extern db_addr_t db_prev;	/* last address examined
-				   or written */
+							   or written */
 extern db_addr_t db_next;	/* next address to be examined
-				   or written */
+							   or written */
 
 extern char db_cmd_on_enter[];
 
-/*
- * Command table
- */
-struct db_command {
-	const char	*name;		/* command name */
-	/* function to call */
-	void		(*fcn)(db_expr_t, bool, db_expr_t, const char *);
-	int		flag;		/* extra info: */
-#define	CS_OWN		0x1		/* non-standard syntax */
-#define	CS_MORE		0x2		/* standard syntax, but may have other
-					   words at end */
-#define	CS_SET_DOT	0x100		/* set dot after command */
-	const struct db_command *more;	/* another level of command */
+struct db_command;
+
+
+/**/
+TAILQ_HEAD(db_cmd_tbl_en_head, db_cmd_tbl_en);
+
+/*TAILQ entry used in default commands and show commands lists.*/
+struct db_cmd_tbl_en {
+  uint32_t db_cmd_num;    /*Number of commands in cmd table*/
+  const struct db_command *db_cmd;  /*pointer to static allocated cmd table*/
+  TAILQ_ENTRY(db_cmd_tbl_en) db_cmd_next; /*TAILQ pointers*/
 };
+
+
Index: files.ddb
===================================================================
RCS file: /cvsroot/src/sys/ddb/files.ddb,v
retrieving revision 1.1
diff -u -r1.1 files.ddb
--- files.ddb	27 Nov 2005 22:44:35 -0000	1.1
+++ files.ddb	9 Jul 2007 21:17:28 -0000
@@ -3,10 +3,10 @@
 #
 # DDB options
 #
-defflag opt_ddb.h		DDB
+defflag opt_ddb.h		DDB 
 defparam opt_ddbparam.h		DDB_FROMCONSOLE DDB_ONPANIC DDB_HISTORY_SIZE
 				DDB_BREAK_CHAR DDB_KEYCODE SYMTAB_SPACE
-				DDB_COMMANDONENTER
+				DDB_COMMANDONENTER DDB_VERBOSE_HELP
 
 file	ddb/db_access.c			ddb | kgdb	# XXX kgdb reference
 file	ddb/db_aout.c			ddb

--Apple-Mail-8--449409839
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed


Regards
-----------------------------------------
Adam Hamsik
jabber: haad@jabber.org
icq: 249727910

Proud NetBSD user.

We program to have fun.
Even when we program for money, we want to have fun as well.
~~ Yukihiro Matsumoto





--Apple-Mail-8--449409839--

--Apple-Mail-9--449409817
content-type: application/pgp-signature; x-mac-type=70674453;
	name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)

iD8DBQFGkqdclIxPgX3Go0MRAqXSAJ9PJhqqrjMSZuJS25Gesu2KWcmdUACdEVIy
Pen8Lz9RgJiaPpaFH4GV+Nk=
=tn2o
-----END PGP SIGNATURE-----

--Apple-Mail-9--449409817--