Deleted Added
full compact
db_command.c (2056) db_command.c (2112)
1/*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 *
1/*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 *
26 * $Id: db_command.c,v 1.5 1994/05/25 08:51:12 rgrimes Exp $
26 * $Id: db_command.c,v 1.6 1994/08/13 03:49:16 wollman Exp $
27 */
28
29/*
30 * Author: David B. Golub, Carnegie Mellon University
31 * Date: 7/90
32 */
33
34/*
35 * Command dispatcher.
36 */
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/proc.h>
40#include <ddb/ddb.h>
41
42#include <ddb/db_lex.h>
43#include <ddb/db_output.h>
44
45#include <setjmp.h>
46
47/*
48 * Exported global variables
49 */
50boolean_t db_cmd_loop_done;
51jmp_buf db_jmpbuf;
52db_addr_t db_dot;
53db_addr_t db_last_addr;
54db_addr_t db_prev;
55db_addr_t db_next;
56
57/*
58 * if 'ed' style: 'dot' is set at start of last item printed,
59 * and '+' points to next line.
60 * Otherwise: 'dot' points to next item, '..' points to last.
61 */
62boolean_t db_ed_style = TRUE;
63
64
65/*
66 * Utility routine - discard tokens through end-of-line.
67 */
68void
69db_skip_to_eol()
70{
71 int t;
72 do {
73 t = db_read_token();
74 } while (t != tEOL);
75}
76
77/*
78 * Command table
79 */
80struct command {
81 char * name; /* command name */
82 void (*fcn)(); /* function to call */
83 int flag; /* extra info: */
84#define CS_OWN 0x1 /* non-standard syntax */
85#define CS_MORE 0x2 /* standard syntax, but may have other
86 words at end */
87#define CS_SET_DOT 0x100 /* set dot after command */
88 struct command *more; /* another level of command */
89};
90
91/*
92 * Results of command search.
93 */
94#define CMD_UNIQUE 0
95#define CMD_FOUND 1
96#define CMD_NONE 2
97#define CMD_AMBIGUOUS 3
98#define CMD_HELP 4
99
100/*
101 * Search for command prefix.
102 */
103int
104db_cmd_search(name, table, cmdp)
105 char * name;
106 struct command *table;
107 struct command **cmdp; /* out */
108{
109 struct command *cmd;
110 int result = CMD_NONE;
111
112 for (cmd = table; cmd->name != 0; cmd++) {
113 register char *lp;
114 register char *rp;
115 register int c;
116
117 lp = name;
118 rp = cmd->name;
119 while ((c = *lp) == *rp) {
120 if (c == 0) {
121 /* complete match */
122 *cmdp = cmd;
123 return (CMD_UNIQUE);
124 }
125 lp++;
126 rp++;
127 }
128 if (c == 0) {
129 /* end of name, not end of command -
130 partial match */
131 if (result == CMD_FOUND) {
132 result = CMD_AMBIGUOUS;
133 /* but keep looking for a full match -
134 this lets us match single letters */
135 }
136 else {
137 *cmdp = cmd;
138 result = CMD_FOUND;
139 }
140 }
141 }
142 if (result == CMD_NONE) {
143 /* check for 'help' */
144 if (name[0] == 'h' && name[1] == 'e'
145 && name[2] == 'l' && name[3] == 'p')
146 result = CMD_HELP;
147 }
148 return (result);
149}
150
151void
152db_cmd_list(table)
153 struct command *table;
154{
155 register struct command *cmd;
156
157 for (cmd = table; cmd->name != 0; cmd++) {
158 db_printf("%-12s", cmd->name);
159 db_end_line();
160 }
161}
162
163void
164db_command(last_cmdp, cmd_table)
165 struct command **last_cmdp; /* IN_OUT */
166 struct command *cmd_table;
167{
168 struct command *cmd;
169 int t;
170 char modif[TOK_STRING_SIZE];
171 db_expr_t addr, count;
172 boolean_t have_addr = FALSE;
173 int result;
174
175 t = db_read_token();
176 if (t == tEOL) {
177 /* empty line repeats last command, at 'next' */
178 cmd = *last_cmdp;
179 addr = (db_expr_t)db_next;
180 have_addr = FALSE;
181 count = 1;
182 modif[0] = '\0';
183 }
184 else if (t == tEXCL) {
185 void db_fncall();
186 db_fncall();
187 return;
188 }
189 else if (t != tIDENT) {
190 db_printf("?\n");
191 db_flush_lex();
192 return;
193 }
194 else {
195 /*
196 * Search for command
197 */
198 while (cmd_table) {
199 result = db_cmd_search(db_tok_string,
200 cmd_table,
201 &cmd);
202 switch (result) {
203 case CMD_NONE:
204 db_printf("No such command\n");
205 db_flush_lex();
206 return;
207 case CMD_AMBIGUOUS:
208 db_printf("Ambiguous\n");
209 db_flush_lex();
210 return;
211 case CMD_HELP:
212 db_cmd_list(cmd_table);
213 db_flush_lex();
214 return;
215 default:
216 break;
217 }
218 if ((cmd_table = cmd->more) != 0) {
219 t = db_read_token();
220 if (t != tIDENT) {
221 db_cmd_list(cmd_table);
222 db_flush_lex();
223 return;
224 }
225 }
226 }
227
228 if ((cmd->flag & CS_OWN) == 0) {
229 /*
230 * Standard syntax:
231 * command [/modifier] [addr] [,count]
232 */
233 t = db_read_token();
234 if (t == tSLASH) {
235 t = db_read_token();
236 if (t != tIDENT) {
237 db_printf("Bad modifier\n");
238 db_flush_lex();
239 return;
240 }
241 db_strcpy(modif, db_tok_string);
242 }
243 else {
244 db_unread_token(t);
245 modif[0] = '\0';
246 }
247
248 if (db_expression(&addr)) {
249 db_dot = (db_addr_t) addr;
250 db_last_addr = db_dot;
251 have_addr = TRUE;
252 }
253 else {
254 addr = (db_expr_t) db_dot;
255 have_addr = FALSE;
256 }
257 t = db_read_token();
258 if (t == tCOMMA) {
259 if (!db_expression(&count)) {
260 db_printf("Count missing\n");
261 db_flush_lex();
262 return;
263 }
264 }
265 else {
266 db_unread_token(t);
267 count = -1;
268 }
269 if ((cmd->flag & CS_MORE) == 0) {
270 db_skip_to_eol();
271 }
272 }
273 }
274 *last_cmdp = cmd;
275 if (cmd != 0) {
276 /*
277 * Execute the command.
278 */
279 (*cmd->fcn)(addr, have_addr, count, modif);
280
281 if (cmd->flag & CS_SET_DOT) {
282 /*
283 * If command changes dot, set dot to
284 * previous address displayed (if 'ed' style).
285 */
286 if (db_ed_style) {
287 db_dot = db_prev;
288 }
289 else {
290 db_dot = db_next;
291 }
292 }
293 else {
294 /*
295 * If command does not change dot,
296 * set 'next' location to be the same.
297 */
298 db_next = db_dot;
299 }
300 }
301}
302
303/*
304 * 'show' commands
305 */
27 */
28
29/*
30 * Author: David B. Golub, Carnegie Mellon University
31 * Date: 7/90
32 */
33
34/*
35 * Command dispatcher.
36 */
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/proc.h>
40#include <ddb/ddb.h>
41
42#include <ddb/db_lex.h>
43#include <ddb/db_output.h>
44
45#include <setjmp.h>
46
47/*
48 * Exported global variables
49 */
50boolean_t db_cmd_loop_done;
51jmp_buf db_jmpbuf;
52db_addr_t db_dot;
53db_addr_t db_last_addr;
54db_addr_t db_prev;
55db_addr_t db_next;
56
57/*
58 * if 'ed' style: 'dot' is set at start of last item printed,
59 * and '+' points to next line.
60 * Otherwise: 'dot' points to next item, '..' points to last.
61 */
62boolean_t db_ed_style = TRUE;
63
64
65/*
66 * Utility routine - discard tokens through end-of-line.
67 */
68void
69db_skip_to_eol()
70{
71 int t;
72 do {
73 t = db_read_token();
74 } while (t != tEOL);
75}
76
77/*
78 * Command table
79 */
80struct command {
81 char * name; /* command name */
82 void (*fcn)(); /* function to call */
83 int flag; /* extra info: */
84#define CS_OWN 0x1 /* non-standard syntax */
85#define CS_MORE 0x2 /* standard syntax, but may have other
86 words at end */
87#define CS_SET_DOT 0x100 /* set dot after command */
88 struct command *more; /* another level of command */
89};
90
91/*
92 * Results of command search.
93 */
94#define CMD_UNIQUE 0
95#define CMD_FOUND 1
96#define CMD_NONE 2
97#define CMD_AMBIGUOUS 3
98#define CMD_HELP 4
99
100/*
101 * Search for command prefix.
102 */
103int
104db_cmd_search(name, table, cmdp)
105 char * name;
106 struct command *table;
107 struct command **cmdp; /* out */
108{
109 struct command *cmd;
110 int result = CMD_NONE;
111
112 for (cmd = table; cmd->name != 0; cmd++) {
113 register char *lp;
114 register char *rp;
115 register int c;
116
117 lp = name;
118 rp = cmd->name;
119 while ((c = *lp) == *rp) {
120 if (c == 0) {
121 /* complete match */
122 *cmdp = cmd;
123 return (CMD_UNIQUE);
124 }
125 lp++;
126 rp++;
127 }
128 if (c == 0) {
129 /* end of name, not end of command -
130 partial match */
131 if (result == CMD_FOUND) {
132 result = CMD_AMBIGUOUS;
133 /* but keep looking for a full match -
134 this lets us match single letters */
135 }
136 else {
137 *cmdp = cmd;
138 result = CMD_FOUND;
139 }
140 }
141 }
142 if (result == CMD_NONE) {
143 /* check for 'help' */
144 if (name[0] == 'h' && name[1] == 'e'
145 && name[2] == 'l' && name[3] == 'p')
146 result = CMD_HELP;
147 }
148 return (result);
149}
150
151void
152db_cmd_list(table)
153 struct command *table;
154{
155 register struct command *cmd;
156
157 for (cmd = table; cmd->name != 0; cmd++) {
158 db_printf("%-12s", cmd->name);
159 db_end_line();
160 }
161}
162
163void
164db_command(last_cmdp, cmd_table)
165 struct command **last_cmdp; /* IN_OUT */
166 struct command *cmd_table;
167{
168 struct command *cmd;
169 int t;
170 char modif[TOK_STRING_SIZE];
171 db_expr_t addr, count;
172 boolean_t have_addr = FALSE;
173 int result;
174
175 t = db_read_token();
176 if (t == tEOL) {
177 /* empty line repeats last command, at 'next' */
178 cmd = *last_cmdp;
179 addr = (db_expr_t)db_next;
180 have_addr = FALSE;
181 count = 1;
182 modif[0] = '\0';
183 }
184 else if (t == tEXCL) {
185 void db_fncall();
186 db_fncall();
187 return;
188 }
189 else if (t != tIDENT) {
190 db_printf("?\n");
191 db_flush_lex();
192 return;
193 }
194 else {
195 /*
196 * Search for command
197 */
198 while (cmd_table) {
199 result = db_cmd_search(db_tok_string,
200 cmd_table,
201 &cmd);
202 switch (result) {
203 case CMD_NONE:
204 db_printf("No such command\n");
205 db_flush_lex();
206 return;
207 case CMD_AMBIGUOUS:
208 db_printf("Ambiguous\n");
209 db_flush_lex();
210 return;
211 case CMD_HELP:
212 db_cmd_list(cmd_table);
213 db_flush_lex();
214 return;
215 default:
216 break;
217 }
218 if ((cmd_table = cmd->more) != 0) {
219 t = db_read_token();
220 if (t != tIDENT) {
221 db_cmd_list(cmd_table);
222 db_flush_lex();
223 return;
224 }
225 }
226 }
227
228 if ((cmd->flag & CS_OWN) == 0) {
229 /*
230 * Standard syntax:
231 * command [/modifier] [addr] [,count]
232 */
233 t = db_read_token();
234 if (t == tSLASH) {
235 t = db_read_token();
236 if (t != tIDENT) {
237 db_printf("Bad modifier\n");
238 db_flush_lex();
239 return;
240 }
241 db_strcpy(modif, db_tok_string);
242 }
243 else {
244 db_unread_token(t);
245 modif[0] = '\0';
246 }
247
248 if (db_expression(&addr)) {
249 db_dot = (db_addr_t) addr;
250 db_last_addr = db_dot;
251 have_addr = TRUE;
252 }
253 else {
254 addr = (db_expr_t) db_dot;
255 have_addr = FALSE;
256 }
257 t = db_read_token();
258 if (t == tCOMMA) {
259 if (!db_expression(&count)) {
260 db_printf("Count missing\n");
261 db_flush_lex();
262 return;
263 }
264 }
265 else {
266 db_unread_token(t);
267 count = -1;
268 }
269 if ((cmd->flag & CS_MORE) == 0) {
270 db_skip_to_eol();
271 }
272 }
273 }
274 *last_cmdp = cmd;
275 if (cmd != 0) {
276 /*
277 * Execute the command.
278 */
279 (*cmd->fcn)(addr, have_addr, count, modif);
280
281 if (cmd->flag & CS_SET_DOT) {
282 /*
283 * If command changes dot, set dot to
284 * previous address displayed (if 'ed' style).
285 */
286 if (db_ed_style) {
287 db_dot = db_prev;
288 }
289 else {
290 db_dot = db_next;
291 }
292 }
293 else {
294 /*
295 * If command does not change dot,
296 * set 'next' location to be the same.
297 */
298 db_next = db_dot;
299 }
300 }
301}
302
303/*
304 * 'show' commands
305 */
306extern void db_listbreak_cmd();
307extern void db_listwatch_cmd();
308extern void db_show_regs(), db_show_one_thread(), db_show_all_threads();
309extern void vm_map_print(), vm_object_print(), vm_page_print();
306
307extern void db_show_one_thread(), db_show_all_threads();
308extern void vm_page_print();
310/* extern void db_ps(); */
311extern void ipc_port_print();
312void db_show_help();
313
314struct command db_show_all_cmds[] = {
315#if 0
316 { "threads", db_show_all_threads, 0, 0 },
317 { "procs", db_ps, 0, 0 },
318#endif
319 { (char *)0 }
320};
321
322struct command db_show_cmds[] = {
323 { "all", 0, 0, db_show_all_cmds },
324 { "registers", db_show_regs, 0, 0 },
325 { "breaks", db_listbreak_cmd, 0, 0 },
326 { "watches", db_listwatch_cmd, 0, 0 },
327#if 0
328 { "thread", db_show_one_thread, 0, 0 },
329#endif
330 { "map", vm_map_print, 0, 0 },
331 { "object", vm_object_print, 0, 0 },
332#if 0
333 { "page", vm_page_print, 0, 0 },
334#endif
335#if 0
336 { "port", ipc_port_print, 0, 0 },
337#endif
338 { (char *)0, }
339};
340
309/* extern void db_ps(); */
310extern void ipc_port_print();
311void db_show_help();
312
313struct command db_show_all_cmds[] = {
314#if 0
315 { "threads", db_show_all_threads, 0, 0 },
316 { "procs", db_ps, 0, 0 },
317#endif
318 { (char *)0 }
319};
320
321struct command db_show_cmds[] = {
322 { "all", 0, 0, db_show_all_cmds },
323 { "registers", db_show_regs, 0, 0 },
324 { "breaks", db_listbreak_cmd, 0, 0 },
325 { "watches", db_listwatch_cmd, 0, 0 },
326#if 0
327 { "thread", db_show_one_thread, 0, 0 },
328#endif
329 { "map", vm_map_print, 0, 0 },
330 { "object", vm_object_print, 0, 0 },
331#if 0
332 { "page", vm_page_print, 0, 0 },
333#endif
334#if 0
335 { "port", ipc_port_print, 0, 0 },
336#endif
337 { (char *)0, }
338};
339
341extern void db_print_cmd(), db_examine_cmd(), db_set_cmd();
342extern void db_search_cmd();
343extern void db_write_cmd();
344extern void db_delete_cmd(), db_breakpoint_cmd();
345extern void db_deletewatch_cmd(), db_watchpoint_cmd();
346extern void db_single_step_cmd(), db_trace_until_call_cmd(),
347 db_trace_until_matching_cmd(), db_continue_cmd();
348extern void db_stack_trace_cmd();
349void db_help_cmd();
350void db_fncall();
351
352struct command db_command_table[] = {
353 { "print", db_print_cmd, 0, 0 },
354 { "examine", db_examine_cmd, CS_SET_DOT, 0 },
355 { "x", db_examine_cmd, CS_SET_DOT, 0 },
356 { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 },
357 { "set", db_set_cmd, CS_OWN, 0 },
358 { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
359 { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
360 { "delete", db_delete_cmd, 0, 0 },
361 { "d", db_delete_cmd, 0, 0 },
362 { "break", db_breakpoint_cmd, 0, 0 },
363 { "dwatch", db_deletewatch_cmd, 0, 0 },
364 { "watch", db_watchpoint_cmd, CS_MORE,0 },
365 { "step", db_single_step_cmd, 0, 0 },
366 { "s", db_single_step_cmd, 0, 0 },
367 { "continue", db_continue_cmd, 0, 0 },
368 { "c", db_continue_cmd, 0, 0 },
369 { "until", db_trace_until_call_cmd,0, 0 },
370 { "next", db_trace_until_matching_cmd,0, 0 },
371 { "match", db_trace_until_matching_cmd,0, 0 },
372 { "trace", db_stack_trace_cmd, 0, 0 },
373 { "call", db_fncall, CS_OWN, 0 },
374 { "show", 0, 0, db_show_cmds },
375#if 0
376 { "ps", db_ps, 0, 0 },
377#endif
378 { (char *)0, }
379};
380
381struct command *db_last_command = 0;
382
383void
384db_help_cmd()
385{
386 struct command *cmd = db_command_table;
387
388 while (cmd->name != 0) {
389 db_printf("%-12s", cmd->name);
390 db_end_line();
391 cmd++;
392 }
393}
394
395void
396db_command_loop()
397{
398 /*
399 * Initialize 'prev' and 'next' to dot.
400 */
401 db_prev = db_dot;
402 db_next = db_dot;
403
404 db_cmd_loop_done = 0;
405 while (!db_cmd_loop_done) {
406
407 (void) setjmp(db_jmpbuf);
408 if (db_print_position() != 0)
409 db_printf("\n");
410
411 db_printf("db> ");
412 (void) db_read_line();
413
414 db_command(&db_last_command, db_command_table);
415 }
416}
417
418void
419db_error(s)
420 char *s;
421{
422 if (s)
423 db_printf(s);
424 db_flush_lex();
425 longjmp(db_jmpbuf, 1);
426}
427
428
429/*
430 * Call random function:
431 * !expr(arg,arg,arg)
432 */
433void
434db_fncall()
435{
436 db_expr_t fn_addr;
437#define MAXARGS 11
438 db_expr_t args[MAXARGS];
439 int nargs = 0;
440 db_expr_t retval;
441 db_expr_t (*func)();
442 int t;
443
444 if (!db_expression(&fn_addr)) {
445 db_printf("Bad function\n");
446 db_flush_lex();
447 return;
448 }
449 func = (db_expr_t (*) ()) fn_addr;
450
451 t = db_read_token();
452 if (t == tLPAREN) {
453 if (db_expression(&args[0])) {
454 nargs++;
455 while ((t = db_read_token()) == tCOMMA) {
456 if (nargs == MAXARGS) {
457 db_printf("Too many arguments\n");
458 db_flush_lex();
459 return;
460 }
461 if (!db_expression(&args[nargs])) {
462 db_printf("Argument missing\n");
463 db_flush_lex();
464 return;
465 }
466 nargs++;
467 }
468 db_unread_token(t);
469 }
470 if (db_read_token() != tRPAREN) {
471 db_printf("?\n");
472 db_flush_lex();
473 return;
474 }
475 }
476 db_skip_to_eol();
477
478 while (nargs < MAXARGS) {
479 args[nargs++] = 0;
480 }
481
482 retval = (*func)(args[0], args[1], args[2], args[3], args[4],
483 args[5], args[6], args[7], args[8], args[9] );
484 db_printf("%#n\n", retval);
485}
340void db_help_cmd();
341void db_fncall();
342
343struct command db_command_table[] = {
344 { "print", db_print_cmd, 0, 0 },
345 { "examine", db_examine_cmd, CS_SET_DOT, 0 },
346 { "x", db_examine_cmd, CS_SET_DOT, 0 },
347 { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 },
348 { "set", db_set_cmd, CS_OWN, 0 },
349 { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
350 { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
351 { "delete", db_delete_cmd, 0, 0 },
352 { "d", db_delete_cmd, 0, 0 },
353 { "break", db_breakpoint_cmd, 0, 0 },
354 { "dwatch", db_deletewatch_cmd, 0, 0 },
355 { "watch", db_watchpoint_cmd, CS_MORE,0 },
356 { "step", db_single_step_cmd, 0, 0 },
357 { "s", db_single_step_cmd, 0, 0 },
358 { "continue", db_continue_cmd, 0, 0 },
359 { "c", db_continue_cmd, 0, 0 },
360 { "until", db_trace_until_call_cmd,0, 0 },
361 { "next", db_trace_until_matching_cmd,0, 0 },
362 { "match", db_trace_until_matching_cmd,0, 0 },
363 { "trace", db_stack_trace_cmd, 0, 0 },
364 { "call", db_fncall, CS_OWN, 0 },
365 { "show", 0, 0, db_show_cmds },
366#if 0
367 { "ps", db_ps, 0, 0 },
368#endif
369 { (char *)0, }
370};
371
372struct command *db_last_command = 0;
373
374void
375db_help_cmd()
376{
377 struct command *cmd = db_command_table;
378
379 while (cmd->name != 0) {
380 db_printf("%-12s", cmd->name);
381 db_end_line();
382 cmd++;
383 }
384}
385
386void
387db_command_loop()
388{
389 /*
390 * Initialize 'prev' and 'next' to dot.
391 */
392 db_prev = db_dot;
393 db_next = db_dot;
394
395 db_cmd_loop_done = 0;
396 while (!db_cmd_loop_done) {
397
398 (void) setjmp(db_jmpbuf);
399 if (db_print_position() != 0)
400 db_printf("\n");
401
402 db_printf("db> ");
403 (void) db_read_line();
404
405 db_command(&db_last_command, db_command_table);
406 }
407}
408
409void
410db_error(s)
411 char *s;
412{
413 if (s)
414 db_printf(s);
415 db_flush_lex();
416 longjmp(db_jmpbuf, 1);
417}
418
419
420/*
421 * Call random function:
422 * !expr(arg,arg,arg)
423 */
424void
425db_fncall()
426{
427 db_expr_t fn_addr;
428#define MAXARGS 11
429 db_expr_t args[MAXARGS];
430 int nargs = 0;
431 db_expr_t retval;
432 db_expr_t (*func)();
433 int t;
434
435 if (!db_expression(&fn_addr)) {
436 db_printf("Bad function\n");
437 db_flush_lex();
438 return;
439 }
440 func = (db_expr_t (*) ()) fn_addr;
441
442 t = db_read_token();
443 if (t == tLPAREN) {
444 if (db_expression(&args[0])) {
445 nargs++;
446 while ((t = db_read_token()) == tCOMMA) {
447 if (nargs == MAXARGS) {
448 db_printf("Too many arguments\n");
449 db_flush_lex();
450 return;
451 }
452 if (!db_expression(&args[nargs])) {
453 db_printf("Argument missing\n");
454 db_flush_lex();
455 return;
456 }
457 nargs++;
458 }
459 db_unread_token(t);
460 }
461 if (db_read_token() != tRPAREN) {
462 db_printf("?\n");
463 db_flush_lex();
464 return;
465 }
466 }
467 db_skip_to_eol();
468
469 while (nargs < MAXARGS) {
470 args[nargs++] = 0;
471 }
472
473 retval = (*func)(args[0], args[1], args[2], args[3], args[4],
474 args[5], args[6], args[7], args[8], args[9] );
475 db_printf("%#n\n", retval);
476}