|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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 [email protected]
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: */
60: #include <cpus.h>
61: #include <dipc.h>
62: #include <dipc_timer.h>
63: #include <xkmachkernel.h>
64: #include <norma_vm.h>
65: #ifdef AT386
66: #include <norma_scsi.h>
67: #endif /* AT386 */
68:
69: #include <mach/boolean.h>
70: #include <string.h>
71: #include <machine/db_machdep.h>
72:
73: #if defined(__alpha)
74: # include <kdebug.h>
75: # if KDEBUG
76: # include <machine/kdebug.h>
77: # endif
78: #endif /* defined(__alpha) */
79:
80: #include <ddb/db_lex.h>
81: #include <ddb/db_output.h>
82: #include <ddb/db_break.h>
83: #include <ddb/db_command.h>
84: #include <ddb/db_cond.h>
85: #include <ddb/db_examine.h>
86: #include <ddb/db_expr.h>
87: #include <ppc/db_low_trace.h>
88: #include <ddb/db_macro.h>
89: #include <ddb/db_print.h>
90: #include <ddb/db_run.h>
91: #include <ddb/db_task_thread.h>
92: #include <ddb/db_variables.h>
93: #include <ddb/db_watch.h>
94: #include <ddb/db_write_cmd.h>
95: #include <ddb/tr.h>
96:
97: #include <machine/setjmp.h>
98: #include <kern/thread.h>
99:
100: #include <kern/misc_protos.h>
101: #include <vm/vm_print.h>
102: #include <ipc/ipc_print.h>
103: #include <kern/kern_print.h>
104: #include <machine/db_machdep.h> /* For db_stack_trace_cmd(). */
105: #include <kern/zalloc.h> /* For db_show_one_zone, db_show_all_zones. */
106: #include <kern/lock.h> /* For db_show_all_slocks(). */
107:
108: #if DIPC_TIMER
109: #include <dipc/dipc_timer.h>
110: #endif /* DIPC_TIMER */
111:
112: #if NORMA_VM
113: #include <xmm/xmm_obj.h>
114: #endif /* NORMA_VM */
115:
116: /*
117: * Exported global variables
118: */
119: boolean_t db_cmd_loop_done;
120: jmp_buf_t *db_recover = 0;
121: db_addr_t db_dot;
122: db_addr_t db_last_addr;
123: db_addr_t db_prev;
124: db_addr_t db_next;
125:
126: /*
127: * if 'ed' style: 'dot' is set at start of last item printed,
128: * and '+' points to next line.
129: * Otherwise: 'dot' points to next item, '..' points to last.
130: */
131: boolean_t db_ed_style = TRUE;
132:
133: /*
134: * Results of command search.
135: */
136: #define CMD_UNIQUE 0
137: #define CMD_FOUND 1
138: #define CMD_NONE 2
139: #define CMD_AMBIGUOUS 3
140: #define CMD_HELP 4
141:
142: /* Prototypes for functions local to this file. XXX -- should be static!
143: */
144:
145: void db_command(
146: struct db_command **last_cmdp, /* IN_OUT */
147: db_expr_t *last_countp, /* IN_OUT */
148: char *last_modifp, /* IN_OUT */
149: struct db_command *cmd_table);
150:
151: void db_help_cmd(void);
152:
153: void db_output_prompt(void);
154:
155: void db_fncall(void);
156:
157: void db_cmd_list(struct db_command *table);
158:
159: int db_cmd_search(
160: char * name,
161: struct db_command * table,
162: struct db_command ** cmdp); /* out */
163:
164: void db_command_list(
165: struct db_command **last_cmdp, /* IN_OUT */
166: db_expr_t *last_countp, /* IN_OUT */
167: char *last_modifp, /* IN_OUT */
168: struct db_command *cmd_table);
169:
170:
171:
172: /*
173: * Search for command prefix.
174: */
175: int
176: db_cmd_search(
177: char * name,
178: struct db_command * table,
179: struct db_command ** cmdp) /* out */
180: {
181: struct db_command *cmd;
182: int result = CMD_NONE;
183:
184: for (cmd = table; cmd->name != 0; cmd++) {
185: register char *lp;
186: register char *rp;
187: register int c;
188:
189: lp = name;
190: rp = cmd->name;
191: while ((c = *lp) == *rp) {
192: if (c == 0) {
193: /* complete match */
194: *cmdp = cmd;
195: return (CMD_UNIQUE);
196: }
197: lp++;
198: rp++;
199: }
200: if (c == 0) {
201: /* end of name, not end of command -
202: partial match */
203: if (result == CMD_FOUND) {
204: result = CMD_AMBIGUOUS;
205: /* but keep looking for a full match -
206: this lets us match single letters */
207: }
208: else {
209: *cmdp = cmd;
210: result = CMD_FOUND;
211: }
212: }
213: }
214: if (result == CMD_NONE) {
215: /* check for 'help' */
216: if (!strncmp(name, "help", strlen(name)))
217: result = CMD_HELP;
218: }
219: return (result);
220: }
221:
222: void
223: db_cmd_list(struct db_command *table)
224: {
225: register struct db_command *new;
226: register struct db_command *old;
227: register struct db_command *cur;
228: unsigned int l;
229: unsigned int len;
230:
231: len = 1;
232: for (cur = table; cur->name != 0; cur++)
233: if ((l = strlen(cur->name)) >= len)
234: len = l + 1;
235:
236: old = (struct db_command *)0;
237: for (;;) {
238: new = (struct db_command *)0;
239: for (cur = table; cur->name != 0; cur++)
240: if ((new == (struct db_command *)0 ||
241: strcmp(cur->name, new->name) < 0) &&
242: (old == (struct db_command *)0 ||
243: strcmp(cur->name, old->name) > 0))
244: new = cur;
245: if (new == (struct db_command *)0)
246: return;
247: db_reserve_output_position(len);
248: db_printf("%-*s", len, new->name);
249: old = new;
250: }
251: }
252:
253: void
254: db_command(
255: struct db_command **last_cmdp, /* IN_OUT */
256: db_expr_t *last_countp, /* IN_OUT */
257: char *last_modifp, /* IN_OUT */
258: struct db_command *cmd_table)
259: {
260: struct db_command *cmd;
261: int t;
262: char modif[TOK_STRING_SIZE];
263: char *modifp = &modif[0];
264: db_expr_t addr, count;
265: boolean_t have_addr;
266: int result;
267:
268: t = db_read_token();
269: if (t == tEOL || t == tSEMI_COLON) {
270: /* empty line repeats last command, at 'next' */
271: cmd = *last_cmdp;
272: count = *last_countp;
273: modifp = last_modifp;
274: addr = (db_expr_t)db_next;
275: have_addr = FALSE;
276: if (t == tSEMI_COLON)
277: db_unread_token(t);
278: }
279: else if (t == tEXCL) {
280: db_fncall();
281: return;
282: }
283: else if (t != tIDENT) {
284: db_printf("?\n");
285: db_flush_lex();
286: return;
287: }
288: else {
289: /*
290: * Search for command
291: */
292: while (cmd_table) {
293: result = db_cmd_search(db_tok_string,
294: cmd_table,
295: &cmd);
296: switch (result) {
297: case CMD_NONE:
298: if (db_exec_macro(db_tok_string) == 0)
299: return;
300: db_printf("No such command \"%s\"\n", db_tok_string);
301: db_flush_lex();
302: return;
303: case CMD_AMBIGUOUS:
304: db_printf("Ambiguous\n");
305: db_flush_lex();
306: return;
307: case CMD_HELP:
308: db_cmd_list(cmd_table);
309: db_flush_lex();
310: return;
311: default:
312: break;
313: }
314: if ((cmd_table = cmd->more) != 0) {
315: t = db_read_token();
316: if (t != tIDENT) {
317: db_cmd_list(cmd_table);
318: db_flush_lex();
319: return;
320: }
321: }
322: }
323:
324: if ((cmd->flag & CS_OWN) == 0) {
325: /*
326: * Standard syntax:
327: * command [/modifier] [addr] [,count]
328: */
329: t = db_read_token();
330: if (t == tSLASH) {
331: t = db_read_token();
332: if (t != tIDENT) {
333: db_printf("Bad modifier \"/%s\"\n", db_tok_string);
334: db_flush_lex();
335: return;
336: }
337: strcpy(modif, db_tok_string);
338: }
339: else {
340: db_unread_token(t);
341: modif[0] = '\0';
342: }
343:
344: if (db_expression(&addr)) {
345: db_dot = (db_addr_t) addr;
346: db_last_addr = db_dot;
347: have_addr = TRUE;
348: }
349: else {
350: addr = (db_expr_t) db_dot;
351: have_addr = FALSE;
352: }
353: t = db_read_token();
354: if (t == tCOMMA) {
355: if (!db_expression(&count)) {
356: db_printf("Count missing after ','\n");
357: db_flush_lex();
358: return;
359: }
360: }
361: else {
362: db_unread_token(t);
363: count = -1;
364: }
365: }
366: }
367: if (cmd != 0) {
368: /*
369: * Execute the command.
370: */
371: (*cmd->fcn)(addr, have_addr, count, modifp);
372:
373: if (cmd->flag & CS_SET_DOT) {
374: /*
375: * If command changes dot, set dot to
376: * previous address displayed (if 'ed' style).
377: */
378: if (db_ed_style) {
379: db_dot = db_prev;
380: }
381: else {
382: db_dot = db_next;
383: }
384: }
385: else {
386: /*
387: * If command does not change dot,
388: * set 'next' location to be the same.
389: */
390: db_next = db_dot;
391: }
392: }
393: *last_cmdp = cmd;
394: *last_countp = count;
395: strcpy(last_modifp, modifp);
396: }
397:
398: void
399: db_command_list(
400: struct db_command **last_cmdp, /* IN_OUT */
401: db_expr_t *last_countp, /* IN_OUT */
402: char *last_modifp, /* IN_OUT */
403: struct db_command *cmd_table)
404: {
405: do {
406: db_command(last_cmdp, last_countp, last_modifp, cmd_table);
407: db_skip_to_eol();
408: } while (db_read_token() == tSEMI_COLON && db_cmd_loop_done == 0);
409: }
410:
411:
412: extern void db_system_stats(void);
413:
414: #if XKMACHKERNEL
415: extern void db_show_net_memory(void);
416:
417: struct db_command db_show_net_cmds[] = {
418: { "memory", (db_func)db_show_net_memory, 0, 0 },
419: };
420: #endif /* XKMACHKERNEL */
421:
422: #if DIPC
423: extern void db_dipc_stats(void), db_dipc_memory(void),
424: db_dipc_port_deads(void), db_dipc_port_table(void),
425: db_dipc_msg_progress(void), db_dipc_special_ports(void),
426: db_dipc_port_table_proxies(void),
427: db_dipc_port_table_principals(void), db_dipc_port_get(void);
428:
429: extern void db_show_kkt_handle(void), db_show_kkt_request(void),
430: db_show_kkt_channel(void), db_show_kkt(void),
431: db_show_kkt_node_map(void);
432: #if PARAGON860
433: extern void db_show_kkt_transmit(void), db_show_kkt_transport(void);
434: #endif /* PARAGON860 */
435: #if NORMA_SCSI
436: extern void db_show_kkt_node(void), db_show_kkt_msg(void),
437: db_show_kkt_event(void);
438: #endif /* NORMA_SCSI */
439:
440: struct db_command db_dipc_port_cmds[] = {
441: { "dead", (db_func)db_dipc_port_deads, 0, 0 },
442: { "principals", (db_func)db_dipc_port_table_principals, 0, 0 },
443: { "proxies", (db_func)db_dipc_port_table_proxies, 0, 0 },
444: { "special", (db_func)db_dipc_special_ports, 0, 0 },
445: { "table", (db_func)db_dipc_port_table, 0, 0 },
446: { "uid", (db_func)db_dipc_port_get, 0, 0 },
447: { (char *)0 }
448: };
449:
450: struct db_command db_dipc_cmds[] = {
451: { "port", 0, 0, db_dipc_port_cmds },
452: { "memory", (db_func)db_dipc_memory, 0, 0 },
453: { "message_progress",(db_func)db_dipc_msg_progress, 0, 0 },
454: { "mp", (db_func)db_dipc_msg_progress, 0, 0 },
455: { "stats", (db_func)db_dipc_stats, 0, 0 },
456: { (char *)0 }
457: };
458:
459: struct db_command db_show_kkt_cmds[] = {
460: { "handle", (db_func)db_show_kkt_handle, 0, 0 },
461: { "request", (db_func)db_show_kkt_request, 0, 0 },
462: { "channel", (db_func)db_show_kkt_channel, 0, 0 },
463: { "stats", (db_func)db_show_kkt, 0, 0 },
464: { "map", (db_func)db_show_kkt_node_map, 0, 0 },
465: #if PARAGON860
466: { "transmit", (db_func)db_show_kkt_transmit, 0, 0 },
467: { "transport", (db_func)db_show_kkt_transport, 0, 0 },
468: #endif /* PARAGON860 */
469: #if NORMA_SCSI
470: { "node", (db_func)db_show_kkt_node, 0, 0 },
471: { "msg", (db_func)db_show_kkt_msg, 0, 0 },
472: { "event", (db_func)db_show_kkt_event, 0, 0 },
473: #endif /* NORMA_SCSI */
474: { (char *)0 }
475: };
476: #endif /*DIPC*/
477:
478: struct db_command db_show_all_cmds[] = {
479: #if USLOCK_DEBUG
480: { "slocks", (db_func) db_show_all_slocks, 0, 0 },
481: #endif /* USLOCK_DEBUG */
482: #if DIPC_TIMER
483: { "timers", (db_func)db_timer_print, 0, 0 },
484: #endif /* DIPC_TIMER */
485: { "acts", db_show_all_acts, 0, 0 },
486: { "spaces", db_show_all_spaces, 0, 0 },
487: { "tasks", db_show_all_acts, 0, 0 },
488: /* temporary alias for sanity preservation */
489: { "threads", db_show_all_acts, 0, 0 },
490: { "zones", db_show_all_zones, 0, 0 },
491: { "vmtask", db_show_all_task_vm, 0, 0 },
492: { (char *)0 }
493: };
494:
495: /* XXX */
496:
497: extern void db_show_thread_log(void);
498: extern void db_show_one_lock(lock_t*);
499: extern void db_show_etap_log(db_expr_t, int, db_expr_t, char *);
500:
501: struct db_command db_show_cmds[] = {
502: { "all", 0, 0, db_show_all_cmds },
503: #if DIPC
504: { "dipc", 0, 0, db_dipc_cmds },
505: { "kkt", 0, 0, db_show_kkt_cmds },
506: #endif /* DIPC */
507: #if XKMACHKERNEL
508: { "net", 0, 0, db_show_net_cmds },
509: #endif /* XKMACHKERNEL */
510: { "registers", db_show_regs, 0, 0 },
511: { "variables", (db_func) db_show_variable, CS_OWN, 0 },
512: { "breaks", (db_func) db_listbreak_cmd, 0, 0 },
513: { "watches", (db_func) db_listwatch_cmd, 0, 0 },
514: { "task", db_show_one_task, 0, 0 },
515: { "act", db_show_one_act, 0, 0 },
516: { "shuttle", db_show_shuttle, 0, 0 },
517: #if 0
518: { "thread", db_show_one_thread, 0, 0 },
519: #endif
520: { "vmtask", db_show_one_task_vm, 0, 0 },
521: { "macro", (db_func) db_show_macro, CS_OWN, 0 },
522: { "runq", (db_func) db_show_runq, 0, 0 },
523: { "map", (db_func) vm_map_print, 0, 0 },
524: { "object", (db_func) vm_object_print, 0, 0 },
525: { "page", (db_func) vm_page_print, 0, 0 },
526: { "copy", (db_func) vm_map_copy_print, 0, 0 },
527: { "port", (db_func) ipc_port_print, 0, 0 },
528: { "pset", (db_func) ipc_pset_print, 0, 0 },
529: { "kmsg", (db_func) ipc_kmsg_print, 0, 0 },
530: { "msg", (db_func) ipc_msg_print, 0, 0 },
531: { "ipc_port", db_show_port_id, 0, 0 },
532: { "lock", (db_func)db_show_one_lock, 0, 0 },
533: #if NORMA_VM
534: { "xmm_obj", (db_func) xmm_obj_print, 0, 0 },
535: { "xmm_reply", (db_func) xmm_reply_print, 0, 0 },
536: #endif /* NORMA_VM */
537: #if TRACE_BUFFER
538: { "tr", db_show_tr, 0, 0 },
539: #endif /* TRACE_BUFFER */
540: { "space", db_show_one_space, 0, 0 },
541: { "system", (db_func) db_system_stats, 0, 0 },
542: #if DIPC_TIMER
543: { "timer", (db_func)db_show_one_timer, 0, 0 },
544: #endif /* DIPC_TIMER */
545: { "zone", db_show_one_zone, 0, 0 },
546: { "simple_lock", db_show_one_simple_lock, 0, 0 },
547: #if !NORMA_IPC
548: { "mutex", db_show_one_mutex, 0, 0 },
549: #endif /* !NORMA_IPC */
550: { "thread_log", (db_func)db_show_thread_log, 0, 0 },
551: { "subsystem", db_show_subsystem, 0, 0 },
552: { "shuttle", db_show_shuttle, 0, 0 },
553: { "etap_log", db_show_etap_log, 0, 0 },
554: { (char *)0, }
555: };
556:
557: #if NCPUS > 1
558: #define db_switch_cpu kdb_on
559: extern void db_switch_cpu(int);
560: #endif /* NCPUS > 1 */
561:
562: struct db_command db_command_table[] = {
563: #if DB_MACHINE_COMMANDS
564:
565: /* this must be the first entry, if it exists */
566: { "machine", 0, 0, 0 },
567: #endif
568: { "print", (db_func) db_print_cmd, CS_OWN, 0 },
569: { "examine", db_examine_cmd, CS_MORE|CS_SET_DOT, 0 },
570: { "x", db_examine_cmd, CS_MORE|CS_SET_DOT, 0 },
571: { "xf", db_examine_forward, CS_SET_DOT, 0 },
572: { "xb", db_examine_backward, CS_SET_DOT, 0 },
573: { "search", (db_func) db_search_cmd, CS_OWN|CS_SET_DOT, 0 },
574: { "set", (db_func) db_set_cmd, CS_OWN, 0 },
575: { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
576: { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
577: { "delete", (db_func) db_delete_cmd, CS_OWN, 0 },
578: { "d", (db_func) db_delete_cmd, CS_OWN, 0 },
579: { "break", db_breakpoint_cmd, CS_MORE, 0 },
580: { "dwatch", db_deletewatch_cmd, CS_MORE, 0 },
581: { "watch", db_watchpoint_cmd, CS_MORE, 0 },
582: { "step", db_single_step_cmd, 0, 0 },
583: { "s", db_single_step_cmd, 0, 0 },
584: { "continue", db_continue_cmd, 0, 0 },
585: { "c", db_continue_cmd, 0, 0 },
586: { "gdb", db_continue_gdb, 0, 0 },
587: { "until", db_trace_until_call_cmd, 0, 0 },
588:
589: /* As per request of DNoveck, CR1550, leave this disabled */
590: #if 0 /* until CR1440 is fixed, to avoid toe-stubbing */
591: { "next", db_trace_until_matching_cmd, 0, 0 },
592: #endif
593: { "match", db_trace_until_matching_cmd, 0 , 0 },
594: { "trace", db_stack_trace_cmd, 0, 0 },
595: { "cond", (db_func) db_cond_cmd, CS_OWN, 0 },
596: { "call", (db_func) db_fncall, CS_OWN, 0 },
597: { "macro", (db_func) db_def_macro_cmd, CS_OWN, 0 },
598: { "dmacro", (db_func) db_del_macro_cmd, CS_OWN, 0 },
599: { "show", 0, 0, db_show_cmds },
600: #if NCPUS > 1
601: { "cpu", (db_func) db_switch_cpu, 0, 0 },
602: #endif /* NCPUS > 1 */
603: { "reboot", (db_func) db_reboot, 0, 0 },
604: #if defined(__ppc__)
605: { "lt", db_low_trace, CS_MORE|CS_SET_DOT, 0 },
606: { "dl", db_display_long, CS_MORE|CS_SET_DOT, 0 },
607: { "dr", db_display_real, CS_MORE|CS_SET_DOT, 0 },
608: { "dv", db_display_virtual, CS_MORE|CS_SET_DOT, 0 },
609: { "dm", db_display_mappings, CS_MORE|CS_SET_DOT, 0 },
610: { "dp", db_display_phys, CS_MORE|CS_SET_DOT, 0 },
611: { "ds", db_display_save, CS_MORE|CS_SET_DOT, 0 },
612: { "dx", db_display_xregs, CS_MORE|CS_SET_DOT, 0 },
613: #endif
614: { (char *)0, }
615: };
616:
617: /* this function should be called to install the machine dependent
618: commands. It should be called before the debugger is enabled */
619: void db_machine_commands_install(struct db_command *ptr)
620: {
621: db_command_table[0].more = ptr;
622: return;
623: }
624:
625:
626: struct db_command *db_last_command = 0;
627: db_expr_t db_last_count = 0;
628: char db_last_modifier[TOK_STRING_SIZE] = { '\0' };
629:
630: void
631: db_help_cmd(void)
632: {
633: struct db_command *cmd = db_command_table;
634:
635: while (cmd->name != 0) {
636: db_printf("%-12s", cmd->name);
637: db_end_line();
638: cmd++;
639: }
640: }
641:
642: int (*ddb_display)(void);
643:
644: void
645: db_command_loop(void)
646: {
647: jmp_buf_t db_jmpbuf;
648: jmp_buf_t *prev = db_recover;
649: extern int db_output_line;
650: extern int db_macro_level;
651: extern int db_indent;
652:
653: /*
654: * Initialize 'prev' and 'next' to dot.
655: */
656: db_prev = db_dot;
657: db_next = db_dot;
658:
659: if (ddb_display)
660: (*ddb_display)();
661:
662: db_cmd_loop_done = 0;
663: while (!db_cmd_loop_done) {
664: (void) _setjmp(db_recover = &db_jmpbuf);
665: db_macro_level = 0;
666: if (db_print_position() != 0)
667: db_printf("\n");
668: db_output_line = 0;
669: db_indent = 0;
670: db_reset_more();
671: db_output_prompt();
672:
673: (void) db_read_line("!!");
674: db_command_list(&db_last_command, &db_last_count,
675: db_last_modifier, db_command_table);
676: }
677:
678: db_recover = prev;
679: }
680:
681: boolean_t
682: db_exec_cmd_nest(
683: char *cmd,
684: int size)
685: {
686: struct db_lex_context lex_context;
687:
688: db_cmd_loop_done = 0;
689: if (cmd) {
690: db_save_lex_context(&lex_context);
691: db_switch_input(cmd, size);
692: }
693: db_command_list(&db_last_command, &db_last_count,
694: db_last_modifier, db_command_table);
695: if (cmd)
696: db_restore_lex_context(&lex_context);
697: return(db_cmd_loop_done == 0);
698: }
699:
700: void
701: db_error(char *s)
702: {
703: extern int db_macro_level;
704:
705: #if defined(__alpha)
706: # if KDEBUG
707: extern boolean_t kdebug_mode;
708: if (kdebug_mode) {
709: if (s) kprintf(DBG_DEBUG, s);
710: return;
711: }
712: # endif /* KDEBUG */
713: #endif /* defined(__alpha) */
714:
715: db_macro_level = 0;
716: if (db_recover) {
717: if (s > (char *)1)
718: db_printf(s);
719: db_flush_lex();
720: _longjmp(db_recover, (s == (char *)1) ? 2 : 1);
721: }
722: else
723: {
724: if (s > (char *)1)
725: db_printf(s);
726: panic("db_error");
727: }
728: }
729:
730:
731: /*
732: * Call random function:
733: * !expr(arg,arg,arg)
734: */
735: void
736: db_fncall(void)
737: {
738: db_expr_t fn_addr;
739: #define MAXARGS 11
740: db_expr_t args[MAXARGS];
741: int nargs = 0;
742: db_expr_t retval;
743: db_expr_t (*func)(db_expr_t, ...);
744: int t;
745:
746: if (!db_expression(&fn_addr)) {
747: db_printf("Bad function \"%s\"\n", db_tok_string);
748: db_flush_lex();
749: return;
750: }
751: func = (db_expr_t (*) (db_expr_t, ...)) fn_addr;
752:
753: t = db_read_token();
754: if (t == tLPAREN) {
755: if (db_expression(&args[0])) {
756: nargs++;
757: while ((t = db_read_token()) == tCOMMA) {
758: if (nargs == MAXARGS) {
759: db_printf("Too many arguments\n");
760: db_flush_lex();
761: return;
762: }
763: if (!db_expression(&args[nargs])) {
764: db_printf("Argument missing\n");
765: db_flush_lex();
766: return;
767: }
768: nargs++;
769: }
770: db_unread_token(t);
771: }
772: if (db_read_token() != tRPAREN) {
773: db_printf("?\n");
774: db_flush_lex();
775: return;
776: }
777: }
778: while (nargs < MAXARGS) {
779: args[nargs++] = 0;
780: }
781:
782: retval = (*func)(args[0], args[1], args[2], args[3], args[4],
783: args[5], args[6], args[7], args[8], args[9] );
784: db_printf(" %#n\n", retval);
785: }
786:
787: boolean_t
788: db_option(
789: char *modif,
790: int option)
791: {
792: register char *p;
793:
794: for (p = modif; *p; p++)
795: if (*p == option)
796: return(TRUE);
797: return(FALSE);
798: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.