db_command.c revision 85944
18876Srgrimes/*
24Srgrimes * Mach Operating System
34Srgrimes * Copyright (c) 1991,1990 Carnegie Mellon University
44Srgrimes * All Rights Reserved.
58876Srgrimes *
64Srgrimes * Permission to use, copy, modify and distribute this software and its
74Srgrimes * documentation is hereby granted, provided that both the copyright
84Srgrimes * notice and this permission notice appear in all copies of the
94Srgrimes * software, derivative works or modified versions, and any portions
104Srgrimes * thereof, and that both notices appear in supporting documentation.
118876Srgrimes *
128876Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
134Srgrimes * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
144Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
158876Srgrimes *
164Srgrimes * Carnegie Mellon requests users of this software to return to
178876Srgrimes *
184Srgrimes *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
194Srgrimes *  School of Computer Science
204Srgrimes *  Carnegie Mellon University
214Srgrimes *  Pittsburgh PA 15213-3890
228876Srgrimes *
234Srgrimes * any improvements or extensions that they make and grant Carnegie the
244Srgrimes * rights to redistribute these changes.
254Srgrimes *
2650477Speter * $FreeBSD: head/sys/ddb/db_command.c 85944 2001-11-03 04:55:48Z peter $
274Srgrimes */
28623Srgrimes
294Srgrimes/*
304Srgrimes *	Author: David B. Golub, Carnegie Mellon University
314Srgrimes *	Date:	7/90
324Srgrimes */
33623Srgrimes
344Srgrimes/*
354Srgrimes * Command dispatcher.
364Srgrimes */
372056Swollman#include <sys/param.h>
3842654Sjdp#include <sys/linker_set.h>
3917848Spst#include <sys/reboot.h>
402056Swollman#include <sys/systm.h>
4149558Sphk#include <sys/cons.h>
4212734Sbde
432056Swollman#include <ddb/ddb.h>
4412473Sbde#include <ddb/db_command.h>
454Srgrimes#include <ddb/db_lex.h>
464Srgrimes#include <ddb/db_output.h>
474Srgrimes
4879418Sjulian#include <machine/setjmp.h>
494Srgrimes
504Srgrimes/*
514Srgrimes * Exported global variables
524Srgrimes */
534Srgrimesboolean_t	db_cmd_loop_done;
5418296Sbdedb_addr_t	db_dot;
554Srgrimesjmp_buf		db_jmpbuf;
564Srgrimesdb_addr_t	db_last_addr;
574Srgrimesdb_addr_t	db_prev;
584Srgrimesdb_addr_t	db_next;
594Srgrimes
6078161SpeterSET_DECLARE(db_cmd_set, struct command);
6178161SpeterSET_DECLARE(db_show_cmd_set, struct command);
6278161Speter
6312515Sphkstatic db_cmdfcn_t	db_fncall;
6417848Spststatic db_cmdfcn_t	db_gdb;
6585944Speterstatic db_cmdfcn_t	db_reset;
6617848Spst
6718296Sbde/* XXX this is actually forward-static. */
6818296Sbdeextern struct command	db_show_cmds[];
6918296Sbde
704Srgrimes/*
714Srgrimes * if 'ed' style: 'dot' is set at start of last item printed,
724Srgrimes * and '+' points to next line.
734Srgrimes * Otherwise: 'dot' points to next item, '..' points to last.
744Srgrimes */
7512515Sphkstatic boolean_t	db_ed_style = TRUE;
764Srgrimes
774Srgrimes/*
784Srgrimes * Utility routine - discard tokens through end-of-line.
794Srgrimes */
804Srgrimesvoid
814Srgrimesdb_skip_to_eol()
824Srgrimes{
834Srgrimes	int	t;
844Srgrimes	do {
854Srgrimes	    t = db_read_token();
864Srgrimes	} while (t != tEOL);
874Srgrimes}
884Srgrimes
894Srgrimes/*
904Srgrimes * Results of command search.
914Srgrimes */
924Srgrimes#define	CMD_UNIQUE	0
934Srgrimes#define	CMD_FOUND	1
944Srgrimes#define	CMD_NONE	2
954Srgrimes#define	CMD_AMBIGUOUS	3
964Srgrimes#define	CMD_HELP	4
974Srgrimes
9818296Sbdestatic void	db_cmd_list __P((struct command *table,
9978161Speter				 struct command **aux_tablep,
10078161Speter				 struct command **aux_tablep_end));
10112515Sphkstatic int	db_cmd_search __P((char *name, struct command *table,
10218296Sbde				   struct command **aux_tablep,
10378161Speter				   struct command **aux_tablep_end,
10412473Sbde				   struct command **cmdp));
10512515Sphkstatic void	db_command __P((struct command **last_cmdp,
10618296Sbde				struct command *cmd_table,
10778161Speter				struct command **aux_cmd_tablep,
10878161Speter				struct command **aux_cmd_tablep_end));
10912473Sbde
1104Srgrimes/*
1114Srgrimes * Search for command prefix.
1124Srgrimes */
11312515Sphkstatic int
11478161Speterdb_cmd_search(name, table, aux_tablep, aux_tablep_end, cmdp)
1154Srgrimes	char *		name;
1164Srgrimes	struct command	*table;
11718296Sbde	struct command	**aux_tablep;
11878161Speter	struct command	**aux_tablep_end;
1194Srgrimes	struct command	**cmdp;	/* out */
1204Srgrimes{
1214Srgrimes	struct command	*cmd;
12218296Sbde	struct command	**aux_cmdp;
1234Srgrimes	int		result = CMD_NONE;
1244Srgrimes
1254Srgrimes	for (cmd = table; cmd->name != 0; cmd++) {
1264Srgrimes	    register char *lp;
1274Srgrimes	    register char *rp;
1284Srgrimes	    register int  c;
1294Srgrimes
1304Srgrimes	    lp = name;
1314Srgrimes	    rp = cmd->name;
1324Srgrimes	    while ((c = *lp) == *rp) {
1334Srgrimes		if (c == 0) {
1344Srgrimes		    /* complete match */
1354Srgrimes		    *cmdp = cmd;
1364Srgrimes		    return (CMD_UNIQUE);
1374Srgrimes		}
1384Srgrimes		lp++;
1394Srgrimes		rp++;
1404Srgrimes	    }
1414Srgrimes	    if (c == 0) {
1424Srgrimes		/* end of name, not end of command -
1434Srgrimes		   partial match */
1444Srgrimes		if (result == CMD_FOUND) {
1454Srgrimes		    result = CMD_AMBIGUOUS;
1464Srgrimes		    /* but keep looking for a full match -
1474Srgrimes		       this lets us match single letters */
1484Srgrimes		}
1494Srgrimes		else {
1504Srgrimes		    *cmdp = cmd;
1514Srgrimes		    result = CMD_FOUND;
1524Srgrimes		}
1534Srgrimes	    }
1544Srgrimes	}
15518296Sbde	if (result == CMD_NONE && aux_tablep != 0)
15618296Sbde	    /* XXX repeat too much code. */
15778161Speter	    for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
15818296Sbde		register char *lp;
15918296Sbde		register char *rp;
16018296Sbde		register int  c;
16118296Sbde
16218296Sbde		lp = name;
16318296Sbde		rp = (*aux_cmdp)->name;
16418296Sbde		while ((c = *lp) == *rp) {
16518296Sbde		    if (c == 0) {
16618296Sbde			/* complete match */
16718296Sbde			*cmdp = *aux_cmdp;
16818296Sbde			return (CMD_UNIQUE);
16918296Sbde		    }
17018296Sbde		    lp++;
17118296Sbde		    rp++;
17218296Sbde		}
17318296Sbde		if (c == 0) {
17418296Sbde		    /* end of name, not end of command -
17518296Sbde		       partial match */
17618296Sbde		    if (result == CMD_FOUND) {
17718296Sbde			result = CMD_AMBIGUOUS;
17818296Sbde			/* but keep looking for a full match -
17918296Sbde			   this lets us match single letters */
18018296Sbde		    }
18118296Sbde		    else {
18218296Sbde			*cmdp = *aux_cmdp;
18318296Sbde			result = CMD_FOUND;
18418296Sbde		    }
18518296Sbde		}
18618296Sbde	    }
1874Srgrimes	if (result == CMD_NONE) {
1884Srgrimes	    /* check for 'help' */
1894Srgrimes		if (name[0] == 'h' && name[1] == 'e'
1904Srgrimes		    && name[2] == 'l' && name[3] == 'p')
1914Srgrimes			result = CMD_HELP;
1924Srgrimes	}
1934Srgrimes	return (result);
1944Srgrimes}
1954Srgrimes
19612515Sphkstatic void
19778161Speterdb_cmd_list(table, aux_tablep, aux_tablep_end)
1984Srgrimes	struct command *table;
19918296Sbde	struct command **aux_tablep;
20078161Speter	struct command **aux_tablep_end;
2014Srgrimes{
2024Srgrimes	register struct command *cmd;
20318296Sbde	register struct command **aux_cmdp;
2044Srgrimes
2054Srgrimes	for (cmd = table; cmd->name != 0; cmd++) {
2064Srgrimes	    db_printf("%-12s", cmd->name);
2074Srgrimes	    db_end_line();
2084Srgrimes	}
20918296Sbde	if (aux_tablep == 0)
21018296Sbde	    return;
21178161Speter	for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
21218296Sbde	    db_printf("%-12s", (*aux_cmdp)->name);
21318296Sbde	    db_end_line();
21418296Sbde	}
2154Srgrimes}
2164Srgrimes
21712515Sphkstatic void
21878161Speterdb_command(last_cmdp, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end)
2194Srgrimes	struct command	**last_cmdp;	/* IN_OUT */
2204Srgrimes	struct command	*cmd_table;
22118296Sbde	struct command	**aux_cmd_tablep;
22278161Speter	struct command	**aux_cmd_tablep_end;
2234Srgrimes{
2244Srgrimes	struct command	*cmd;
2254Srgrimes	int		t;
2264Srgrimes	char		modif[TOK_STRING_SIZE];
2274Srgrimes	db_expr_t	addr, count;
228798Swollman	boolean_t	have_addr = FALSE;
2294Srgrimes	int		result;
2304Srgrimes
2314Srgrimes	t = db_read_token();
2324Srgrimes	if (t == tEOL) {
2334Srgrimes	    /* empty line repeats last command, at 'next' */
2344Srgrimes	    cmd = *last_cmdp;
2354Srgrimes	    addr = (db_expr_t)db_next;
2364Srgrimes	    have_addr = FALSE;
2374Srgrimes	    count = 1;
2384Srgrimes	    modif[0] = '\0';
2394Srgrimes	}
2404Srgrimes	else if (t == tEXCL) {
24110348Sbde	    db_fncall((db_expr_t)0, (boolean_t)0, (db_expr_t)0, (char *)0);
2424Srgrimes	    return;
2434Srgrimes	}
2444Srgrimes	else if (t != tIDENT) {
2454Srgrimes	    db_printf("?\n");
2464Srgrimes	    db_flush_lex();
2474Srgrimes	    return;
2484Srgrimes	}
2494Srgrimes	else {
2504Srgrimes	    /*
2514Srgrimes	     * Search for command
2524Srgrimes	     */
2534Srgrimes	    while (cmd_table) {
2544Srgrimes		result = db_cmd_search(db_tok_string,
2554Srgrimes				       cmd_table,
25618296Sbde				       aux_cmd_tablep,
25778161Speter				       aux_cmd_tablep_end,
2584Srgrimes				       &cmd);
2594Srgrimes		switch (result) {
2604Srgrimes		    case CMD_NONE:
2614Srgrimes			db_printf("No such command\n");
2624Srgrimes			db_flush_lex();
2634Srgrimes			return;
2644Srgrimes		    case CMD_AMBIGUOUS:
2654Srgrimes			db_printf("Ambiguous\n");
2664Srgrimes			db_flush_lex();
2674Srgrimes			return;
2684Srgrimes		    case CMD_HELP:
26978161Speter			db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
2704Srgrimes			db_flush_lex();
2714Srgrimes			return;
2724Srgrimes		    default:
2734Srgrimes			break;
2744Srgrimes		}
2754Srgrimes		if ((cmd_table = cmd->more) != 0) {
27618296Sbde		    /* XXX usually no more aux's. */
27718296Sbde		    aux_cmd_tablep = 0;
27818296Sbde		    if (cmd_table == db_show_cmds)
27978161Speter			aux_cmd_tablep = SET_BEGIN(db_show_cmd_set);
28078161Speter			aux_cmd_tablep_end = SET_LIMIT(db_show_cmd_set);
28118296Sbde
2824Srgrimes		    t = db_read_token();
2834Srgrimes		    if (t != tIDENT) {
28478161Speter			db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
2854Srgrimes			db_flush_lex();
2864Srgrimes			return;
2874Srgrimes		    }
2884Srgrimes		}
2894Srgrimes	    }
2904Srgrimes
2914Srgrimes	    if ((cmd->flag & CS_OWN) == 0) {
2924Srgrimes		/*
2934Srgrimes		 * Standard syntax:
2944Srgrimes		 * command [/modifier] [addr] [,count]
2954Srgrimes		 */
2964Srgrimes		t = db_read_token();
2974Srgrimes		if (t == tSLASH) {
2984Srgrimes		    t = db_read_token();
2994Srgrimes		    if (t != tIDENT) {
3004Srgrimes			db_printf("Bad modifier\n");
3014Srgrimes			db_flush_lex();
3024Srgrimes			return;
3034Srgrimes		    }
3044Srgrimes		    db_strcpy(modif, db_tok_string);
3054Srgrimes		}
3064Srgrimes		else {
3074Srgrimes		    db_unread_token(t);
3084Srgrimes		    modif[0] = '\0';
3094Srgrimes		}
3104Srgrimes
3114Srgrimes		if (db_expression(&addr)) {
3124Srgrimes		    db_dot = (db_addr_t) addr;
3134Srgrimes		    db_last_addr = db_dot;
3144Srgrimes		    have_addr = TRUE;
3154Srgrimes		}
3164Srgrimes		else {
3174Srgrimes		    addr = (db_expr_t) db_dot;
3184Srgrimes		    have_addr = FALSE;
3194Srgrimes		}
3204Srgrimes		t = db_read_token();
3214Srgrimes		if (t == tCOMMA) {
3224Srgrimes		    if (!db_expression(&count)) {
3234Srgrimes			db_printf("Count missing\n");
3244Srgrimes			db_flush_lex();
3254Srgrimes			return;
3264Srgrimes		    }
3274Srgrimes		}
3284Srgrimes		else {
3294Srgrimes		    db_unread_token(t);
3304Srgrimes		    count = -1;
3314Srgrimes		}
3324Srgrimes		if ((cmd->flag & CS_MORE) == 0) {
3334Srgrimes		    db_skip_to_eol();
3344Srgrimes		}
3354Srgrimes	    }
3364Srgrimes	}
3374Srgrimes	*last_cmdp = cmd;
3384Srgrimes	if (cmd != 0) {
3394Srgrimes	    /*
3404Srgrimes	     * Execute the command.
3414Srgrimes	     */
3424Srgrimes	    (*cmd->fcn)(addr, have_addr, count, modif);
3434Srgrimes
3444Srgrimes	    if (cmd->flag & CS_SET_DOT) {
3454Srgrimes		/*
3464Srgrimes		 * If command changes dot, set dot to
3474Srgrimes		 * previous address displayed (if 'ed' style).
3484Srgrimes		 */
3494Srgrimes		if (db_ed_style) {
3504Srgrimes		    db_dot = db_prev;
3514Srgrimes		}
3524Srgrimes		else {
3534Srgrimes		    db_dot = db_next;
3544Srgrimes		}
3554Srgrimes	    }
3564Srgrimes	    else {
3574Srgrimes		/*
3584Srgrimes		 * If command does not change dot,
3594Srgrimes		 * set 'next' location to be the same.
3604Srgrimes		 */
3614Srgrimes		db_next = db_dot;
3624Srgrimes	    }
3634Srgrimes	}
3644Srgrimes}
3654Srgrimes
3664Srgrimes/*
3674Srgrimes * 'show' commands
3684Srgrimes */
3692112Swollman
37012515Sphkstatic struct command db_show_all_cmds[] = {
3714Srgrimes#if 0
3721147Sguido	{ "threads",	db_show_all_threads,	0,	0 },
3732320Sdg#endif
3741549Srgrimes	{ "procs",	db_ps,			0,	0 },
3754Srgrimes	{ (char *)0 }
3764Srgrimes};
3774Srgrimes
37812515Sphkstatic struct command db_show_cmds[] = {
3794Srgrimes	{ "all",	0,			0,	db_show_all_cmds },
3804Srgrimes	{ "registers",	db_show_regs,		0,	0 },
3814Srgrimes	{ "breaks",	db_listbreak_cmd, 	0,	0 },
3824Srgrimes#if 0
3834Srgrimes	{ "thread",	db_show_one_thread,	0,	0 },
3844Srgrimes#endif
3854Srgrimes#if 0
3864Srgrimes	{ "port",	ipc_port_print,		0,	0 },
3874Srgrimes#endif
3884Srgrimes	{ (char *)0, }
3894Srgrimes};
3904Srgrimes
39112515Sphkstatic struct command db_command_table[] = {
3924Srgrimes	{ "print",	db_print_cmd,		0,	0 },
3936920Sjoerg	{ "p",		db_print_cmd,		0,	0 },
3944Srgrimes	{ "examine",	db_examine_cmd,		CS_SET_DOT, 0 },
3954Srgrimes	{ "x",		db_examine_cmd,		CS_SET_DOT, 0 },
3964Srgrimes	{ "search",	db_search_cmd,		CS_OWN|CS_SET_DOT, 0 },
3974Srgrimes	{ "set",	db_set_cmd,		CS_OWN,	0 },
3984Srgrimes	{ "write",	db_write_cmd,		CS_MORE|CS_SET_DOT, 0 },
3994Srgrimes	{ "w",		db_write_cmd,		CS_MORE|CS_SET_DOT, 0 },
4004Srgrimes	{ "delete",	db_delete_cmd,		0,	0 },
4014Srgrimes	{ "d",		db_delete_cmd,		0,	0 },
4024Srgrimes	{ "break",	db_breakpoint_cmd,	0,	0 },
4034Srgrimes	{ "dwatch",	db_deletewatch_cmd,	0,	0 },
4044Srgrimes	{ "watch",	db_watchpoint_cmd,	CS_MORE,0 },
40579573Sbsd	{ "dhwatch",	db_deletehwatch_cmd,	0,      0 },
40679573Sbsd	{ "hwatch",	db_hwatchpoint_cmd,	0,      0 },
4074Srgrimes	{ "step",	db_single_step_cmd,	0,	0 },
4084Srgrimes	{ "s",		db_single_step_cmd,	0,	0 },
4094Srgrimes	{ "continue",	db_continue_cmd,	0,	0 },
4104Srgrimes	{ "c",		db_continue_cmd,	0,	0 },
4114Srgrimes	{ "until",	db_trace_until_call_cmd,0,	0 },
4124Srgrimes	{ "next",	db_trace_until_matching_cmd,0,	0 },
4134Srgrimes	{ "match",	db_trace_until_matching_cmd,0,	0 },
4144Srgrimes	{ "trace",	db_stack_trace_cmd,	0,	0 },
4154Srgrimes	{ "call",	db_fncall,		CS_OWN,	0 },
4164Srgrimes	{ "show",	0,			0,	db_show_cmds },
4171147Sguido	{ "ps",		db_ps,			0,	0 },
41817848Spst	{ "gdb",	db_gdb,			0,	0 },
41985944Speter	{ "reset",	db_reset,		0,	0 },
4204Srgrimes	{ (char *)0, }
4214Srgrimes};
4224Srgrimes
42312515Sphkstatic struct command	*db_last_command = 0;
4244Srgrimes
4257090Sbde#if 0
4264Srgrimesvoid
4274Srgrimesdb_help_cmd()
4284Srgrimes{
4294Srgrimes	struct command *cmd = db_command_table;
4304Srgrimes
4314Srgrimes	while (cmd->name != 0) {
4324Srgrimes	    db_printf("%-12s", cmd->name);
4334Srgrimes	    db_end_line();
4344Srgrimes	    cmd++;
4354Srgrimes	}
4364Srgrimes}
4377090Sbde#endif
4384Srgrimes
43933296Sbde/*
44033296Sbde * At least one non-optional command must be implemented using
44133296Sbde * DB_COMMAND() so that db_cmd_set gets created.  Here is one.
44233296Sbde */
44333296SbdeDB_COMMAND(panic, db_panic)
4446204Sphk{
4457170Sdg	panic("from debugger");
4466204Sphk}
4476204Sphk
4486204Sphkvoid
4494Srgrimesdb_command_loop()
4504Srgrimes{
4514Srgrimes	/*
4524Srgrimes	 * Initialize 'prev' and 'next' to dot.
4534Srgrimes	 */
4544Srgrimes	db_prev = db_dot;
4554Srgrimes	db_next = db_dot;
4564Srgrimes
4574Srgrimes	db_cmd_loop_done = 0;
4584Srgrimes	while (!db_cmd_loop_done) {
4594Srgrimes
4604Srgrimes	    (void) setjmp(db_jmpbuf);
4614Srgrimes	    if (db_print_position() != 0)
4624Srgrimes		db_printf("\n");
4634Srgrimes
4644Srgrimes	    db_printf("db> ");
4654Srgrimes	    (void) db_read_line();
4664Srgrimes
46718296Sbde	    db_command(&db_last_command, db_command_table,
46878161Speter		       SET_BEGIN(db_cmd_set), SET_LIMIT(db_cmd_set));
4694Srgrimes	}
4704Srgrimes}
4714Srgrimes
4724Srgrimesvoid
4734Srgrimesdb_error(s)
4744Srgrimes	char *s;
4754Srgrimes{
4764Srgrimes	if (s)
47779884Skris	    db_printf("%s", s);
4784Srgrimes	db_flush_lex();
4794Srgrimes	longjmp(db_jmpbuf, 1);
4804Srgrimes}
4814Srgrimes
4824Srgrimes
4834Srgrimes/*
4844Srgrimes * Call random function:
4854Srgrimes * !expr(arg,arg,arg)
4864Srgrimes */
48712515Sphkstatic void
48810348Sbdedb_fncall(dummy1, dummy2, dummy3, dummy4)
48910348Sbde	db_expr_t	dummy1;
49010348Sbde	boolean_t	dummy2;
49110348Sbde	db_expr_t	dummy3;
49210348Sbde	char *		dummy4;
4934Srgrimes{
4944Srgrimes	db_expr_t	fn_addr;
49512473Sbde#define	MAXARGS		11	/* XXX only 10 are passed */
4964Srgrimes	db_expr_t	args[MAXARGS];
4974Srgrimes	int		nargs = 0;
4984Srgrimes	db_expr_t	retval;
49912473Sbde	typedef db_expr_t fcn_10args_t __P((db_expr_t, db_expr_t, db_expr_t,
50012473Sbde					    db_expr_t, db_expr_t, db_expr_t,
50112473Sbde					    db_expr_t, db_expr_t, db_expr_t,
50212473Sbde					    db_expr_t));
50312473Sbde	fcn_10args_t	*func;
5044Srgrimes	int		t;
5054Srgrimes
5064Srgrimes	if (!db_expression(&fn_addr)) {
5074Srgrimes	    db_printf("Bad function\n");
5084Srgrimes	    db_flush_lex();
5094Srgrimes	    return;
5104Srgrimes	}
51112473Sbde	func = (fcn_10args_t *)fn_addr;	/* XXX */
5124Srgrimes
5134Srgrimes	t = db_read_token();
5144Srgrimes	if (t == tLPAREN) {
5154Srgrimes	    if (db_expression(&args[0])) {
5164Srgrimes		nargs++;
5174Srgrimes		while ((t = db_read_token()) == tCOMMA) {
5184Srgrimes		    if (nargs == MAXARGS) {
5194Srgrimes			db_printf("Too many arguments\n");
5204Srgrimes			db_flush_lex();
5214Srgrimes			return;
5224Srgrimes		    }
5234Srgrimes		    if (!db_expression(&args[nargs])) {
5244Srgrimes			db_printf("Argument missing\n");
5254Srgrimes			db_flush_lex();
5264Srgrimes			return;
5274Srgrimes		    }
5284Srgrimes		    nargs++;
5294Srgrimes		}
5304Srgrimes		db_unread_token(t);
5314Srgrimes	    }
5324Srgrimes	    if (db_read_token() != tRPAREN) {
5334Srgrimes		db_printf("?\n");
5344Srgrimes		db_flush_lex();
5354Srgrimes		return;
5364Srgrimes	    }
5374Srgrimes	}
5384Srgrimes	db_skip_to_eol();
5394Srgrimes
5404Srgrimes	while (nargs < MAXARGS) {
5414Srgrimes	    args[nargs++] = 0;
5424Srgrimes	}
5434Srgrimes
5444Srgrimes	retval = (*func)(args[0], args[1], args[2], args[3], args[4],
5454Srgrimes			 args[5], args[6], args[7], args[8], args[9] );
54648407Speter	db_printf("%#lr\n", (long)retval);
5474Srgrimes}
54817848Spst
54917848Spst/* Enter GDB remote protocol debugger on the next trap. */
55017848Spst
55146783Sphkdev_t	   gdbdev = NODEV;
55246783Sphkcn_getc_t *gdb_getc;
55346783Sphkcn_putc_t *gdb_putc;
55446658Smckusick
55517848Spststatic void
55617848Spstdb_gdb (dummy1, dummy2, dummy3, dummy4)
55717848Spst	db_expr_t	dummy1;
55817848Spst	boolean_t	dummy2;
55917848Spst	db_expr_t	dummy3;
56017848Spst	char *		dummy4;
56117848Spst{
56246658Smckusick
56346783Sphk	if (gdbdev == NODEV) {
56446658Smckusick		db_printf("No gdb port enabled. Set flag 0x80 on desired port\n");
56546658Smckusick		db_printf("in your configuration file (currently sio only).\n");
56646658Smckusick		return;
56746658Smckusick	}
56817848Spst	boothowto ^= RB_GDB;
56917848Spst
57017848Spst	db_printf("Next trap will enter %s\n",
57117848Spst		   boothowto & RB_GDB ? "GDB remote protocol mode"
57217848Spst				      : "DDB debugger");
57317848Spst}
57485944Speter
57585944Speterstatic void
57685944Speterdb_reset(dummy1, dummy2, dummy3, dummy4)
57785944Speter	db_expr_t	dummy1;
57885944Speter	boolean_t	dummy2;
57985944Speter	db_expr_t	dummy3;
58085944Speter	char *		dummy4;
58185944Speter{
58285944Speter
58385944Speter	cpu_reset();
58485944Speter}
585