]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
91447636 | 2 | * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. |
1c79356b A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
37839358 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
1c79356b | 11 | * |
37839358 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
37839358 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
1c79356b A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * @OSF_COPYRIGHT@ | |
24 | */ | |
25 | /* | |
26 | * Mach Operating System | |
27 | * Copyright (c) 1991 Carnegie Mellon University | |
28 | * All Rights Reserved. | |
29 | * | |
30 | * Permission to use, copy, modify and distribute this software and its | |
31 | * documentation is hereby granted, provided that both the copyright | |
32 | * notice and this permission notice appear in all copies of the | |
33 | * software, derivative works or modified versions, and any portions | |
34 | * thereof, and that both notices appear in supporting documentation. | |
35 | * | |
36 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
37 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
38 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
39 | * | |
40 | * Carnegie Mellon requests users of this software to return to | |
41 | * | |
42 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
43 | * School of Computer Science | |
44 | * Carnegie Mellon University | |
45 | * Pittsburgh PA 15213-3890 | |
46 | * | |
47 | * any improvements or extensions that they make and grant Carnegie Mellon | |
48 | * the rights to redistribute these changes. | |
49 | */ | |
50 | /* | |
51 | */ | |
52 | /* | |
53 | * Author: David B. Golub, Carnegie Mellon University | |
54 | * Date: 7/90 | |
55 | */ | |
56 | ||
57 | /* | |
58 | * Command dispatcher. | |
59 | */ | |
1c79356b A |
60 | #include <norma_vm.h> |
61 | #ifdef AT386 | |
62 | #include <norma_scsi.h> | |
63 | #endif /* AT386 */ | |
64 | ||
65 | #include <mach/boolean.h> | |
66 | #include <string.h> | |
67 | #include <machine/db_machdep.h> | |
68 | ||
69 | #if defined(__alpha) | |
70 | # include <kdebug.h> | |
71 | # if KDEBUG | |
72 | # include <machine/kdebug.h> | |
73 | # endif | |
74 | #endif /* defined(__alpha) */ | |
75 | ||
76 | #include <ddb/db_lex.h> | |
77 | #include <ddb/db_output.h> | |
78 | #include <ddb/db_break.h> | |
79 | #include <ddb/db_command.h> | |
80 | #include <ddb/db_cond.h> | |
81 | #include <ddb/db_examine.h> | |
82 | #include <ddb/db_expr.h> | |
83 | #include <ppc/db_low_trace.h> | |
84 | #include <ddb/db_macro.h> | |
85 | #include <ddb/db_print.h> | |
86 | #include <ddb/db_run.h> | |
87 | #include <ddb/db_task_thread.h> | |
88 | #include <ddb/db_variables.h> | |
89 | #include <ddb/db_watch.h> | |
90 | #include <ddb/db_write_cmd.h> | |
91 | #include <ddb/tr.h> | |
92 | ||
93 | #include <machine/setjmp.h> | |
94 | #include <kern/thread.h> | |
95 | ||
96 | #include <kern/misc_protos.h> | |
97 | #include <vm/vm_print.h> | |
98 | #include <ipc/ipc_print.h> | |
99 | #include <kern/kern_print.h> | |
100 | #include <machine/db_machdep.h> /* For db_stack_trace_cmd(). */ | |
101 | #include <kern/zalloc.h> /* For db_show_one_zone, db_show_all_zones. */ | |
102 | #include <kern/lock.h> /* For db_show_all_slocks(). */ | |
103 | ||
104 | #if NORMA_VM | |
105 | #include <xmm/xmm_obj.h> | |
106 | #endif /* NORMA_VM */ | |
107 | ||
108 | /* | |
109 | * Exported global variables | |
110 | */ | |
111 | boolean_t db_cmd_loop_done; | |
112 | jmp_buf_t *db_recover = 0; | |
113 | db_addr_t db_dot; | |
114 | db_addr_t db_last_addr; | |
115 | db_addr_t db_prev; | |
116 | db_addr_t db_next; | |
117 | ||
118 | /* | |
119 | * if 'ed' style: 'dot' is set at start of last item printed, | |
120 | * and '+' points to next line. | |
121 | * Otherwise: 'dot' points to next item, '..' points to last. | |
122 | */ | |
123 | boolean_t db_ed_style = TRUE; | |
124 | ||
125 | /* | |
126 | * Results of command search. | |
127 | */ | |
128 | #define CMD_UNIQUE 0 | |
129 | #define CMD_FOUND 1 | |
130 | #define CMD_NONE 2 | |
131 | #define CMD_AMBIGUOUS 3 | |
132 | #define CMD_HELP 4 | |
133 | ||
134 | /* Prototypes for functions local to this file. XXX -- should be static! | |
135 | */ | |
136 | ||
137 | void db_command( | |
138 | struct db_command **last_cmdp, /* IN_OUT */ | |
139 | db_expr_t *last_countp, /* IN_OUT */ | |
140 | char *last_modifp, /* IN_OUT */ | |
141 | struct db_command *cmd_table); | |
142 | ||
143 | void db_help_cmd(void); | |
144 | ||
145 | void db_output_prompt(void); | |
146 | ||
147 | void db_fncall(void); | |
148 | ||
149 | void db_cmd_list(struct db_command *table); | |
150 | ||
151 | int db_cmd_search( | |
152 | char * name, | |
153 | struct db_command * table, | |
154 | struct db_command ** cmdp); /* out */ | |
155 | ||
156 | void db_command_list( | |
157 | struct db_command **last_cmdp, /* IN_OUT */ | |
158 | db_expr_t *last_countp, /* IN_OUT */ | |
159 | char *last_modifp, /* IN_OUT */ | |
160 | struct db_command *cmd_table); | |
161 | ||
162 | ||
163 | ||
164 | /* | |
165 | * Search for command prefix. | |
166 | */ | |
167 | int | |
168 | db_cmd_search( | |
169 | char * name, | |
170 | struct db_command * table, | |
171 | struct db_command ** cmdp) /* out */ | |
172 | { | |
173 | struct db_command *cmd; | |
174 | int result = CMD_NONE; | |
175 | ||
176 | for (cmd = table; cmd->name != 0; cmd++) { | |
177 | register char *lp; | |
178 | register char *rp; | |
179 | register int c; | |
180 | ||
181 | lp = name; | |
182 | rp = cmd->name; | |
183 | while ((c = *lp) == *rp) { | |
184 | if (c == 0) { | |
185 | /* complete match */ | |
186 | *cmdp = cmd; | |
187 | return (CMD_UNIQUE); | |
188 | } | |
189 | lp++; | |
190 | rp++; | |
191 | } | |
192 | if (c == 0) { | |
193 | /* end of name, not end of command - | |
194 | partial match */ | |
195 | if (result == CMD_FOUND) { | |
196 | result = CMD_AMBIGUOUS; | |
197 | /* but keep looking for a full match - | |
198 | this lets us match single letters */ | |
199 | } | |
200 | else { | |
201 | *cmdp = cmd; | |
202 | result = CMD_FOUND; | |
203 | } | |
204 | } | |
205 | } | |
206 | if (result == CMD_NONE) { | |
207 | /* check for 'help' */ | |
208 | if (!strncmp(name, "help", strlen(name))) | |
209 | result = CMD_HELP; | |
210 | } | |
211 | return (result); | |
212 | } | |
213 | ||
214 | void | |
215 | db_cmd_list(struct db_command *table) | |
216 | { | |
217 | register struct db_command *new; | |
218 | register struct db_command *old; | |
219 | register struct db_command *cur; | |
220 | unsigned int l; | |
221 | unsigned int len; | |
222 | ||
223 | len = 1; | |
224 | for (cur = table; cur->name != 0; cur++) | |
225 | if ((l = strlen(cur->name)) >= len) | |
226 | len = l + 1; | |
227 | ||
228 | old = (struct db_command *)0; | |
229 | for (;;) { | |
230 | new = (struct db_command *)0; | |
231 | for (cur = table; cur->name != 0; cur++) | |
232 | if ((new == (struct db_command *)0 || | |
233 | strcmp(cur->name, new->name) < 0) && | |
234 | (old == (struct db_command *)0 || | |
235 | strcmp(cur->name, old->name) > 0)) | |
236 | new = cur; | |
237 | if (new == (struct db_command *)0) | |
238 | return; | |
239 | db_reserve_output_position(len); | |
240 | db_printf("%-*s", len, new->name); | |
241 | old = new; | |
242 | } | |
243 | } | |
244 | ||
245 | void | |
246 | db_command( | |
247 | struct db_command **last_cmdp, /* IN_OUT */ | |
248 | db_expr_t *last_countp, /* IN_OUT */ | |
249 | char *last_modifp, /* IN_OUT */ | |
250 | struct db_command *cmd_table) | |
251 | { | |
252 | struct db_command *cmd; | |
253 | int t; | |
254 | char modif[TOK_STRING_SIZE]; | |
255 | char *modifp = &modif[0]; | |
256 | db_expr_t addr, count; | |
257 | boolean_t have_addr; | |
258 | int result; | |
259 | ||
260 | t = db_read_token(); | |
261 | if (t == tEOL || t == tSEMI_COLON) { | |
262 | /* empty line repeats last command, at 'next' */ | |
263 | cmd = *last_cmdp; | |
264 | count = *last_countp; | |
265 | modifp = last_modifp; | |
266 | addr = (db_expr_t)db_next; | |
267 | have_addr = FALSE; | |
268 | if (t == tSEMI_COLON) | |
269 | db_unread_token(t); | |
270 | } | |
271 | else if (t == tEXCL) { | |
272 | db_fncall(); | |
273 | return; | |
274 | } | |
275 | else if (t != tIDENT) { | |
276 | db_printf("?\n"); | |
277 | db_flush_lex(); | |
278 | return; | |
279 | } | |
280 | else { | |
281 | /* | |
282 | * Search for command | |
283 | */ | |
284 | while (cmd_table) { | |
285 | result = db_cmd_search(db_tok_string, | |
286 | cmd_table, | |
287 | &cmd); | |
288 | switch (result) { | |
289 | case CMD_NONE: | |
290 | if (db_exec_macro(db_tok_string) == 0) | |
291 | return; | |
292 | db_printf("No such command \"%s\"\n", db_tok_string); | |
293 | db_flush_lex(); | |
294 | return; | |
295 | case CMD_AMBIGUOUS: | |
296 | db_printf("Ambiguous\n"); | |
297 | db_flush_lex(); | |
298 | return; | |
299 | case CMD_HELP: | |
300 | db_cmd_list(cmd_table); | |
301 | db_flush_lex(); | |
302 | return; | |
303 | default: | |
304 | break; | |
305 | } | |
306 | if ((cmd_table = cmd->more) != 0) { | |
307 | t = db_read_token(); | |
308 | if (t != tIDENT) { | |
309 | db_cmd_list(cmd_table); | |
310 | db_flush_lex(); | |
311 | return; | |
312 | } | |
313 | } | |
314 | } | |
315 | ||
316 | if ((cmd->flag & CS_OWN) == 0) { | |
317 | /* | |
318 | * Standard syntax: | |
319 | * command [/modifier] [addr] [,count] | |
320 | */ | |
321 | t = db_read_token(); | |
322 | if (t == tSLASH) { | |
323 | t = db_read_token(); | |
324 | if (t != tIDENT) { | |
325 | db_printf("Bad modifier \"/%s\"\n", db_tok_string); | |
326 | db_flush_lex(); | |
327 | return; | |
328 | } | |
329 | strcpy(modif, db_tok_string); | |
330 | } | |
331 | else { | |
332 | db_unread_token(t); | |
333 | modif[0] = '\0'; | |
334 | } | |
335 | ||
336 | if (db_expression(&addr)) { | |
337 | db_dot = (db_addr_t) addr; | |
338 | db_last_addr = db_dot; | |
339 | have_addr = TRUE; | |
340 | } | |
341 | else { | |
342 | addr = (db_expr_t) db_dot; | |
343 | have_addr = FALSE; | |
344 | } | |
345 | t = db_read_token(); | |
346 | if (t == tCOMMA) { | |
347 | if (!db_expression(&count)) { | |
348 | db_printf("Count missing after ','\n"); | |
349 | db_flush_lex(); | |
350 | return; | |
351 | } | |
352 | } | |
353 | else { | |
354 | db_unread_token(t); | |
355 | count = -1; | |
356 | } | |
357 | } | |
358 | } | |
359 | if (cmd != 0) { | |
360 | /* | |
361 | * Execute the command. | |
362 | */ | |
363 | (*cmd->fcn)(addr, have_addr, count, modifp); | |
364 | ||
365 | if (cmd->flag & CS_SET_DOT) { | |
366 | /* | |
367 | * If command changes dot, set dot to | |
368 | * previous address displayed (if 'ed' style). | |
369 | */ | |
370 | if (db_ed_style) { | |
371 | db_dot = db_prev; | |
372 | } | |
373 | else { | |
374 | db_dot = db_next; | |
375 | } | |
376 | } | |
377 | else { | |
378 | /* | |
379 | * If command does not change dot, | |
380 | * set 'next' location to be the same. | |
381 | */ | |
382 | db_next = db_dot; | |
383 | } | |
384 | } | |
385 | *last_cmdp = cmd; | |
386 | *last_countp = count; | |
387 | strcpy(last_modifp, modifp); | |
388 | } | |
389 | ||
390 | void | |
391 | db_command_list( | |
392 | struct db_command **last_cmdp, /* IN_OUT */ | |
393 | db_expr_t *last_countp, /* IN_OUT */ | |
394 | char *last_modifp, /* IN_OUT */ | |
395 | struct db_command *cmd_table) | |
396 | { | |
397 | do { | |
398 | db_command(last_cmdp, last_countp, last_modifp, cmd_table); | |
399 | db_skip_to_eol(); | |
400 | } while (db_read_token() == tSEMI_COLON && db_cmd_loop_done == 0); | |
401 | } | |
402 | ||
403 | ||
404 | extern void db_system_stats(void); | |
405 | ||
406 | struct db_command db_show_all_cmds[] = { | |
1c79356b A |
407 | { "acts", db_show_all_acts, 0, 0 }, |
408 | { "spaces", db_show_all_spaces, 0, 0 }, | |
409 | { "tasks", db_show_all_acts, 0, 0 }, | |
410 | /* temporary alias for sanity preservation */ | |
411 | { "threads", db_show_all_acts, 0, 0 }, | |
412 | { "zones", db_show_all_zones, 0, 0 }, | |
413 | { "vmtask", db_show_all_task_vm, 0, 0 }, | |
414 | { (char *)0 } | |
415 | }; | |
416 | ||
417 | /* XXX */ | |
418 | ||
419 | extern void db_show_thread_log(void); | |
420 | extern void db_show_one_lock(lock_t*); | |
421 | extern void db_show_etap_log(db_expr_t, int, db_expr_t, char *); | |
422 | ||
423 | struct db_command db_show_cmds[] = { | |
424 | { "all", 0, 0, db_show_all_cmds }, | |
425 | { "registers", db_show_regs, 0, 0 }, | |
426 | { "variables", (db_func) db_show_variable, CS_OWN, 0 }, | |
427 | { "breaks", (db_func) db_listbreak_cmd, 0, 0 }, | |
428 | { "watches", (db_func) db_listwatch_cmd, 0, 0 }, | |
429 | { "task", db_show_one_task, 0, 0 }, | |
430 | { "act", db_show_one_act, 0, 0 }, | |
431 | { "shuttle", db_show_shuttle, 0, 0 }, | |
432 | #if 0 | |
433 | { "thread", db_show_one_thread, 0, 0 }, | |
434 | #endif | |
435 | { "vmtask", db_show_one_task_vm, 0, 0 }, | |
436 | { "macro", (db_func) db_show_macro, CS_OWN, 0 }, | |
437 | { "runq", (db_func) db_show_runq, 0, 0 }, | |
438 | { "map", (db_func) vm_map_print, 0, 0 }, | |
439 | { "object", (db_func) vm_object_print, 0, 0 }, | |
440 | { "page", (db_func) vm_page_print, 0, 0 }, | |
441 | { "copy", (db_func) vm_map_copy_print, 0, 0 }, | |
442 | { "port", (db_func) ipc_port_print, 0, 0 }, | |
443 | { "pset", (db_func) ipc_pset_print, 0, 0 }, | |
444 | { "kmsg", (db_func) ipc_kmsg_print, 0, 0 }, | |
445 | { "msg", (db_func) ipc_msg_print, 0, 0 }, | |
446 | { "ipc_port", db_show_port_id, 0, 0 }, | |
1c79356b A |
447 | #if NORMA_VM |
448 | { "xmm_obj", (db_func) xmm_obj_print, 0, 0 }, | |
449 | { "xmm_reply", (db_func) xmm_reply_print, 0, 0 }, | |
450 | #endif /* NORMA_VM */ | |
451 | #if TRACE_BUFFER | |
452 | { "tr", db_show_tr, 0, 0 }, | |
453 | #endif /* TRACE_BUFFER */ | |
454 | { "space", db_show_one_space, 0, 0 }, | |
455 | { "system", (db_func) db_system_stats, 0, 0 }, | |
456 | { "zone", db_show_one_zone, 0, 0 }, | |
91447636 A |
457 | { "lock", (db_func)db_show_one_lock, 0, 0 }, |
458 | { "mutex_lock", (db_func)db_show_one_mutex, 0, 0 }, | |
459 | { "simple_lock", (db_func)db_show_one_simple_lock, 0, 0 }, | |
1c79356b | 460 | { "thread_log", (db_func)db_show_thread_log, 0, 0 }, |
1c79356b | 461 | { "shuttle", db_show_shuttle, 0, 0 }, |
1c79356b A |
462 | { (char *)0, } |
463 | }; | |
464 | ||
1c79356b A |
465 | #define db_switch_cpu kdb_on |
466 | extern void db_switch_cpu(int); | |
1c79356b A |
467 | |
468 | struct db_command db_command_table[] = { | |
469 | #if DB_MACHINE_COMMANDS | |
470 | ||
471 | /* this must be the first entry, if it exists */ | |
472 | { "machine", 0, 0, 0 }, | |
473 | #endif | |
474 | { "print", (db_func) db_print_cmd, CS_OWN, 0 }, | |
475 | { "examine", db_examine_cmd, CS_MORE|CS_SET_DOT, 0 }, | |
476 | { "x", db_examine_cmd, CS_MORE|CS_SET_DOT, 0 }, | |
477 | { "xf", db_examine_forward, CS_SET_DOT, 0 }, | |
478 | { "xb", db_examine_backward, CS_SET_DOT, 0 }, | |
479 | { "search", (db_func) db_search_cmd, CS_OWN|CS_SET_DOT, 0 }, | |
480 | { "set", (db_func) db_set_cmd, CS_OWN, 0 }, | |
481 | { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, | |
482 | { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, | |
483 | { "delete", (db_func) db_delete_cmd, CS_OWN, 0 }, | |
484 | { "d", (db_func) db_delete_cmd, CS_OWN, 0 }, | |
485 | { "break", db_breakpoint_cmd, CS_MORE, 0 }, | |
486 | { "dwatch", db_deletewatch_cmd, CS_MORE, 0 }, | |
487 | { "watch", db_watchpoint_cmd, CS_MORE, 0 }, | |
488 | { "step", db_single_step_cmd, 0, 0 }, | |
489 | { "s", db_single_step_cmd, 0, 0 }, | |
490 | { "continue", db_continue_cmd, 0, 0 }, | |
491 | { "c", db_continue_cmd, 0, 0 }, | |
492 | { "gdb", db_continue_gdb, 0, 0 }, | |
493 | { "until", db_trace_until_call_cmd, 0, 0 }, | |
494 | ||
495 | /* As per request of DNoveck, CR1550, leave this disabled */ | |
496 | #if 0 /* until CR1440 is fixed, to avoid toe-stubbing */ | |
497 | { "next", db_trace_until_matching_cmd, 0, 0 }, | |
498 | #endif | |
499 | { "match", db_trace_until_matching_cmd, 0 , 0 }, | |
500 | { "trace", db_stack_trace_cmd, 0, 0 }, | |
501 | { "cond", (db_func) db_cond_cmd, CS_OWN, 0 }, | |
502 | { "call", (db_func) db_fncall, CS_OWN, 0 }, | |
503 | { "macro", (db_func) db_def_macro_cmd, CS_OWN, 0 }, | |
504 | { "dmacro", (db_func) db_del_macro_cmd, CS_OWN, 0 }, | |
505 | { "show", 0, 0, db_show_cmds }, | |
1c79356b | 506 | { "cpu", (db_func) db_switch_cpu, 0, 0 }, |
1c79356b A |
507 | { "reboot", (db_func) db_reboot, 0, 0 }, |
508 | #if defined(__ppc__) | |
509 | { "lt", db_low_trace, CS_MORE|CS_SET_DOT, 0 }, | |
510 | { "dl", db_display_long, CS_MORE|CS_SET_DOT, 0 }, | |
55e303ae | 511 | { "dc", db_display_char, CS_MORE|CS_SET_DOT, 0 }, |
1c79356b A |
512 | { "dr", db_display_real, CS_MORE|CS_SET_DOT, 0 }, |
513 | { "dv", db_display_virtual, CS_MORE|CS_SET_DOT, 0 }, | |
514 | { "dm", db_display_mappings, CS_MORE|CS_SET_DOT, 0 }, | |
55e303ae | 515 | { "dh", db_display_hash, CS_MORE|CS_SET_DOT, 0 }, |
1c79356b | 516 | { "dp", db_display_pmap, CS_MORE, 0 }, |
55e303ae | 517 | { "di", db_display_iokit, CS_MORE, 0 }, |
1c79356b A |
518 | { "ds", db_display_save, CS_MORE|CS_SET_DOT, 0 }, |
519 | { "dx", db_display_xregs, CS_MORE|CS_SET_DOT, 0 }, | |
520 | { "dk", db_display_kmod, CS_MORE, 0 }, | |
521 | { "gs", db_gsnoop, CS_MORE, 0 }, | |
55e303ae A |
522 | { "cm", db_check_mappings, CS_MORE, 0 }, |
523 | { "cp", db_check_pmaps, CS_MORE, 0 }, | |
1c79356b A |
524 | #endif |
525 | { (char *)0, } | |
526 | }; | |
527 | ||
528 | /* this function should be called to install the machine dependent | |
529 | commands. It should be called before the debugger is enabled */ | |
530 | void db_machine_commands_install(struct db_command *ptr) | |
531 | { | |
532 | db_command_table[0].more = ptr; | |
533 | return; | |
534 | } | |
535 | ||
536 | ||
537 | struct db_command *db_last_command = 0; | |
538 | db_expr_t db_last_count = 0; | |
539 | char db_last_modifier[TOK_STRING_SIZE] = { '\0' }; | |
540 | ||
541 | void | |
542 | db_help_cmd(void) | |
543 | { | |
544 | struct db_command *cmd = db_command_table; | |
545 | ||
546 | while (cmd->name != 0) { | |
547 | db_printf("%-12s", cmd->name); | |
548 | db_end_line(); | |
549 | cmd++; | |
550 | } | |
551 | } | |
552 | ||
553 | int (*ddb_display)(void); | |
554 | ||
555 | void | |
556 | db_command_loop(void) | |
557 | { | |
558 | jmp_buf_t db_jmpbuf; | |
559 | jmp_buf_t *prev = db_recover; | |
560 | extern int db_output_line; | |
561 | extern int db_macro_level; | |
562 | extern int db_indent; | |
563 | ||
564 | /* | |
565 | * Initialize 'prev' and 'next' to dot. | |
566 | */ | |
567 | db_prev = db_dot; | |
568 | db_next = db_dot; | |
569 | ||
570 | if (ddb_display) | |
571 | (*ddb_display)(); | |
572 | ||
573 | db_cmd_loop_done = 0; | |
574 | while (!db_cmd_loop_done) { | |
575 | (void) _setjmp(db_recover = &db_jmpbuf); | |
576 | db_macro_level = 0; | |
577 | if (db_print_position() != 0) | |
578 | db_printf("\n"); | |
579 | db_output_line = 0; | |
580 | db_indent = 0; | |
581 | db_reset_more(); | |
582 | db_output_prompt(); | |
583 | ||
584 | (void) db_read_line("!!"); | |
585 | db_command_list(&db_last_command, &db_last_count, | |
586 | db_last_modifier, db_command_table); | |
587 | } | |
588 | ||
589 | db_recover = prev; | |
590 | } | |
591 | ||
592 | boolean_t | |
593 | db_exec_cmd_nest( | |
91447636 A |
594 | const char *cmd, |
595 | int size) | |
1c79356b A |
596 | { |
597 | struct db_lex_context lex_context; | |
598 | ||
599 | db_cmd_loop_done = 0; | |
600 | if (cmd) { | |
601 | db_save_lex_context(&lex_context); | |
602 | db_switch_input(cmd, size); | |
603 | } | |
604 | db_command_list(&db_last_command, &db_last_count, | |
605 | db_last_modifier, db_command_table); | |
606 | if (cmd) | |
607 | db_restore_lex_context(&lex_context); | |
608 | return(db_cmd_loop_done == 0); | |
609 | } | |
610 | ||
611 | void | |
91447636 | 612 | db_error(const char *s) |
1c79356b A |
613 | { |
614 | extern int db_macro_level; | |
615 | ||
1c79356b A |
616 | db_macro_level = 0; |
617 | if (db_recover) { | |
618 | if (s > (char *)1) | |
619 | db_printf(s); | |
620 | db_flush_lex(); | |
621 | _longjmp(db_recover, (s == (char *)1) ? 2 : 1); | |
622 | } | |
623 | else | |
624 | { | |
625 | if (s > (char *)1) | |
626 | db_printf(s); | |
627 | panic("db_error"); | |
628 | } | |
629 | } | |
630 | ||
631 | ||
632 | /* | |
633 | * Call random function: | |
634 | * !expr(arg,arg,arg) | |
635 | */ | |
636 | void | |
637 | db_fncall(void) | |
638 | { | |
639 | db_expr_t fn_addr; | |
640 | #define MAXARGS 11 | |
55e303ae A |
641 | uint32_t args[MAXARGS]; |
642 | db_expr_t argwork; | |
1c79356b | 643 | int nargs = 0; |
55e303ae A |
644 | uint32_t retval; |
645 | uint32_t (*func)(uint32_t, ...); | |
1c79356b A |
646 | int t; |
647 | ||
648 | if (!db_expression(&fn_addr)) { | |
649 | db_printf("Bad function \"%s\"\n", db_tok_string); | |
650 | db_flush_lex(); | |
651 | return; | |
652 | } | |
55e303ae | 653 | func = (uint32_t (*) (uint32_t, ...)) fn_addr; |
1c79356b A |
654 | |
655 | t = db_read_token(); | |
656 | if (t == tLPAREN) { | |
55e303ae A |
657 | if (db_expression(&argwork)) { |
658 | args[nargs] = (uint32_t)argwork; | |
659 | nargs++; | |
660 | while ((t = db_read_token()) == tCOMMA) { | |
661 | if (nargs == MAXARGS) { | |
662 | db_printf("Too many arguments\n"); | |
663 | db_flush_lex(); | |
664 | return; | |
665 | } | |
666 | if (!db_expression(&argwork)) { | |
667 | db_printf("Argument missing\n"); | |
668 | db_flush_lex(); | |
669 | return; | |
670 | } | |
671 | args[nargs] = (uint32_t)argwork; | |
672 | nargs++; | |
673 | } | |
674 | db_unread_token(t); | |
de355530 A |
675 | } |
676 | if (db_read_token() != tRPAREN) { | |
55e303ae A |
677 | db_printf("?\n"); |
678 | db_flush_lex(); | |
679 | return; | |
1c79356b A |
680 | } |
681 | } | |
682 | while (nargs < MAXARGS) { | |
683 | args[nargs++] = 0; | |
684 | } | |
685 | ||
686 | retval = (*func)(args[0], args[1], args[2], args[3], args[4], | |
687 | args[5], args[6], args[7], args[8], args[9] ); | |
688 | db_printf(" %#n\n", retval); | |
689 | } | |
690 | ||
691 | boolean_t | |
692 | db_option( | |
91447636 A |
693 | const char *modif, |
694 | int option) | |
1c79356b A |
695 | { |
696 | register char *p; | |
697 | ||
698 | for (p = modif; *p; p++) | |
699 | if (*p == option) | |
700 | return(TRUE); | |
701 | return(FALSE); | |
702 | } |