The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_command.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1991 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 "AS IS"
   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 Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        db_command.c,v $
   29  * Revision 2.22  93/03/09  10:53:31  danner
   30  *      String protos.
   31  *      [93/03/07            af]
   32  * 
   33  * Revision 2.21  93/02/01  09:55:01  danner
   34  *      Removed unused (and incorrect) decl of db_machine_cmds.
   35  *      [93/01/25            jfriedl]
   36  * 
   37  * Revision 2.20  93/01/14  17:24:43  danner
   38  *      64bit cleanup.
   39  *      [92/11/30            af]
   40  * 
   41  * Revision 2.19  92/08/03  17:30:46  jfriedl
   42  *      removed silly prototypes
   43  *      [92/08/02            jfriedl]
   44  * 
   45  * Revision 2.18  92/05/21  17:06:32  jfriedl
   46  *      Cleanup to quiet gcc warnings.
   47  *      [92/05/16            jfriedl]
   48  * 
   49  * Revision 2.17  92/03/10  16:25:07  jsb
   50  *      Added show pset, show all vuids.
   51  *      [92/02/20  10:52:22  jsb]
   52  *      NORMA_VM: added show xmm_obj, show xmm_reply.
   53  *      [92/01/21  18:13:32  jsb]
   54  * 
   55  *      NORMA_IPC: added show all uids, proxies, principals.
   56  *      [92/01/16  21:25:38  jsb]
   57  * 
   58  *      Added show copy, show packet, show pcs.
   59  *      [92/01/13  10:13:50  jsb]
   60  * 
   61  * Revision 2.16  91/10/09  15:58:27  af
   62  *      Revision 2.15.1.1  91/10/05  13:05:19  jeffreyh
   63  *      Added compound, macro, and conditional command support.
   64  *      Added "xf" and "xb" command to examine forward and backward.
   65  *      Added last command execution with "!!".
   66  *      Added "show task" command.
   67  *      Added "ipc_port" command to print all IPC ports in a task.
   68  *      Added dot address and default thread indicator in prompt.
   69  *      Changed error messages to output more information.
   70  *      Moved "skip_to_eol()" to db_lex.c.
   71  *      [91/08/29            tak]
   72  * 
   73  * Revision 2.15  91/08/24  11:55:24  af
   74  *      Added optional funcall at ddb entry: similar to GDB's
   75  *      "display"s in spirit.
   76  *      [91/08/02  02:42:11  af]
   77  * 
   78  * Revision 2.14  91/08/03  18:17:16  jsb
   79  *      Added `show kmsg' and `show msg'.
   80  *      Replaced NORMA_BOOT conditionals with NORMA_IPC.
   81  *      Use _node_self instead of node_self() for prompt,
   82  *      since node_self() will panic if _node_self not intialized.
   83  *      [91/07/24  22:48:48  jsb]
   84  * 
   85  * Revision 2.13  91/07/11  11:00:32  danner
   86  *      Copyright Fixes
   87  * 
   88  * Revision 2.12  91/07/09  23:15:42  danner
   89  *      Modified the command loop to include the cpu number in the
   90  *       command prompt on multicpu machines, and node number in norma
   91  *            systems.
   92  *      [91/04/12            danner]
   93  *
   94  * Revision 2.11  91/07/01  08:24:04  jsb
   95  *      Added support for 'show all slocks'.
   96  *      [91/06/29  15:59:01  jsb]
   97  * 
   98  * Revision 2.10  91/06/17  15:43:46  jsb
   99  *      Renamed NORMA conditionals.
  100  *      [91/06/17  09:57:51  jsb]
  101  * 
  102  *      Moved struct command definition to db_command.h, added include of
  103  *       db_command.h, renamed struct command to struct db_command. All
  104  *       in support of machine dependpent command extensions to db. 
  105  *      [91/03/12            danner]
  106  * 
  107  * Revision 2.9  91/06/06  17:03:47  jsb
  108  *      NORMA support: prompt includes node number, e.g., db4>.
  109  *      [91/05/25  10:47:35  jsb]
  110  * 
  111  * Revision 2.8  91/05/14  15:32:51  mrt
  112  *      Correcting copyright
  113  * 
  114  * Revision 2.7  91/03/16  14:42:30  rpd
  115  *      Added db_recover.
  116  *      [91/01/13            rpd]
  117  * 
  118  * Revision 2.6  91/02/05  17:06:10  mrt
  119  *      Changed to new Mach copyright
  120  *      [91/01/31  16:17:18  mrt]
  121  * 
  122  * Revision 2.5  91/01/08  17:31:54  rpd
  123  *      Forward reference for db_fncall();
  124  *      [91/01/04  12:35:17  rvb]
  125  * 
  126  *      Add call as a synonym for ! and match for next
  127  *      [91/01/04  12:14:48  rvb]
  128  * 
  129  * Revision 2.4  90/11/07  16:49:15  rpd
  130  *      Added search.
  131  *      [90/11/06            rpd]
  132  * 
  133  * Revision 2.3  90/10/25  14:43:45  rwd
  134  *      Changed db_fncall to print the result unsigned.
  135  *      [90/10/19            rpd]
  136  * 
  137  *      Added CS_MORE to db_watchpoint_cmd.
  138  *      [90/10/17            rpd]
  139  *      Added watchpoint commands: watch, dwatch, show watches.
  140  *      [90/10/16            rpd]
  141  * 
  142  * Revision 2.2  90/08/27  21:50:10  dbg
  143  *      Remove 'listbreaks' - use 'show breaks' instead.  Change 'show
  144  *      threads' to 'show all threads' to avoid clash with 'show thread'.
  145  *      Set 'dot' here from db_prev or db_next, depending on 'db_ed_style'
  146  *      flag and syntax table.
  147  *      [90/08/22            dbg]
  148  *      Reduce lint.
  149  *      [90/08/07            dbg]
  150  *      Created.
  151  *      [90/07/25            dbg]
  152  * 
  153  */
  154 /*
  155  *      Author: David B. Golub, Carnegie Mellon University
  156  *      Date:   7/90
  157  */
  158 
  159 /*
  160  * Command dispatcher.
  161  */
  162 #include <cpus.h>
  163 #include <norma_ipc.h>
  164 #include <norma_vm.h>
  165 
  166 #include <mach/boolean.h>
  167 #include <kern/strings.h>
  168 #include <machine/db_machdep.h>
  169 
  170 #include <ddb/db_lex.h>
  171 #include <ddb/db_output.h>
  172 #include <ddb/db_command.h>
  173 #include <ddb/db_task_thread.h>
  174 
  175 #include <machine/setjmp.h>
  176 #include <kern/thread.h>
  177 #include <ipc/ipc_pset.h> /* 4proto */
  178 #include <ipc/ipc_port.h> /* 4proto */
  179 
  180 
  181 
  182 /*
  183  * Exported global variables
  184  */
  185 boolean_t       db_cmd_loop_done;
  186 jmp_buf_t       *db_recover = 0;
  187 db_addr_t       db_dot;
  188 db_addr_t       db_last_addr;
  189 db_addr_t       db_prev;
  190 db_addr_t       db_next;
  191 
  192 /*
  193  * if 'ed' style: 'dot' is set at start of last item printed,
  194  * and '+' points to next line.
  195  * Otherwise: 'dot' points to next item, '..' points to last.
  196  */
  197 boolean_t       db_ed_style = TRUE;
  198 
  199 /*
  200  * Results of command search.
  201  */
  202 #define CMD_UNIQUE      0
  203 #define CMD_FOUND       1
  204 #define CMD_NONE        2
  205 #define CMD_AMBIGUOUS   3
  206 #define CMD_HELP        4
  207 
  208 /*
  209  * Search for command prefix.
  210  */
  211 int
  212 db_cmd_search(name, table, cmdp)
  213         char *          name;
  214         struct db_command       *table;
  215         struct db_command       **cmdp; /* out */
  216 {
  217         struct db_command       *cmd;
  218         int             result = CMD_NONE;
  219 
  220         for (cmd = table; cmd->name != 0; cmd++) {
  221             register char *lp;
  222             register char *rp;
  223             register int  c;
  224 
  225             lp = name;
  226             rp = cmd->name;
  227             while ((c = *lp) == *rp) {
  228                 if (c == 0) {
  229                     /* complete match */
  230                     *cmdp = cmd;
  231                     return (CMD_UNIQUE);
  232                 }
  233                 lp++;
  234                 rp++;
  235             }
  236             if (c == 0) {
  237                 /* end of name, not end of command -
  238                    partial match */
  239                 if (result == CMD_FOUND) {
  240                     result = CMD_AMBIGUOUS;
  241                     /* but keep looking for a full match -
  242                        this lets us match single letters */
  243                 }
  244                 else {
  245                     *cmdp = cmd;
  246                     result = CMD_FOUND;
  247                 }
  248             }
  249         }
  250         if (result == CMD_NONE) {
  251             /* check for 'help' */
  252             if (!strncmp(name, "help", strlen(name)))
  253                 result = CMD_HELP;
  254         }
  255         return (result);
  256 }
  257 
  258 void
  259 db_cmd_list(table)
  260         struct db_command *table;
  261 {
  262         register struct db_command *cmd;
  263 
  264         for (cmd = table; cmd->name != 0; cmd++) {
  265             db_printf("%-12s", cmd->name);
  266             db_end_line();
  267         }
  268 }
  269 
  270 void
  271 db_command(last_cmdp, cmd_table)
  272         struct db_command       **last_cmdp;    /* IN_OUT */
  273         struct db_command       *cmd_table;
  274 {
  275         struct db_command       *cmd;
  276         int             t;
  277         char            modif[TOK_STRING_SIZE];
  278         db_expr_t       addr, count;
  279         boolean_t       have_addr = FALSE;
  280         int             result;
  281 
  282         t = db_read_token();
  283         if (t == tEOL || t == tSEMI_COLON) {
  284             /* empty line repeats last command, at 'next' */
  285             cmd = *last_cmdp;
  286             addr = (db_expr_t)db_next;
  287             have_addr = FALSE;
  288             count = 1;
  289             modif[0]  = '\0';
  290             if (t == tSEMI_COLON)
  291                 db_unread_token(t);
  292         }
  293         else if (t == tEXCL) {
  294             void db_fncall();
  295             db_fncall();
  296             return;
  297         }
  298         else if (t != tIDENT) {
  299             db_printf("?\n");
  300             db_flush_lex();
  301             return;
  302         }
  303         else {
  304             /*
  305              * Search for command
  306              */
  307             while (cmd_table) {
  308                 result = db_cmd_search(db_tok_string,
  309                                        cmd_table,
  310                                        &cmd);
  311                 switch (result) {
  312                     case CMD_NONE:
  313                         if (db_exec_macro(db_tok_string) == 0)
  314                             return;
  315                         db_printf("No such command \"%s\"\n", db_tok_string);
  316                         db_flush_lex();
  317                         return;
  318                     case CMD_AMBIGUOUS:
  319                         db_printf("Ambiguous\n");
  320                         db_flush_lex();
  321                         return;
  322                     case CMD_HELP:
  323                         db_cmd_list(cmd_table);
  324                         db_flush_lex();
  325                         return;
  326                     default:
  327                         break;
  328                 }
  329                 if ((cmd_table = cmd->more) != 0) {
  330                     t = db_read_token();
  331                     if (t != tIDENT) {
  332                         db_cmd_list(cmd_table);
  333                         db_flush_lex();
  334                         return;
  335                     }
  336                 }
  337             }
  338 
  339             if ((cmd->flag & CS_OWN) == 0) {
  340                 /*
  341                  * Standard syntax:
  342                  * command [/modifier] [addr] [,count]
  343                  */
  344                 t = db_read_token();
  345                 if (t == tSLASH) {
  346                     t = db_read_token();
  347                     if (t != tIDENT) {
  348                         db_printf("Bad modifier \"/%s\"\n", db_tok_string);
  349                         db_flush_lex();
  350                         return;
  351                     }
  352                     db_strcpy(modif, db_tok_string);
  353                 }
  354                 else {
  355                     db_unread_token(t);
  356                     modif[0] = '\0';
  357                 }
  358 
  359                 if (db_expression(&addr)) {
  360                     db_dot = (db_addr_t) addr;
  361                     db_last_addr = db_dot;
  362                     have_addr = TRUE;
  363                 }
  364                 else {
  365                     addr = (db_expr_t) db_dot;
  366                     have_addr = FALSE;
  367                 }
  368                 t = db_read_token();
  369                 if (t == tCOMMA) {
  370                     if (!db_expression(&count)) {
  371                         db_printf("Count missing after ','\n");
  372                         db_flush_lex();
  373                         return;
  374                     }
  375                 }
  376                 else {
  377                     db_unread_token(t);
  378                     count = -1;
  379                 }
  380             }
  381         }
  382         *last_cmdp = cmd;
  383         if (cmd != 0) {
  384             /*
  385              * Execute the command.
  386              */
  387             (*cmd->fcn)(addr, have_addr, count, modif);
  388 
  389             if (cmd->flag & CS_SET_DOT) {
  390                 /*
  391                  * If command changes dot, set dot to
  392                  * previous address displayed (if 'ed' style).
  393                  */
  394                 if (db_ed_style) {
  395                     db_dot = db_prev;
  396                 }
  397                 else {
  398                     db_dot = db_next;
  399                 }
  400             }
  401             else {
  402                 /*
  403                  * If command does not change dot,
  404                  * set 'next' location to be the same.
  405                  */
  406                 db_next = db_dot;
  407             }
  408         }
  409 }
  410 
  411 void
  412 db_command_list(last_cmdp, cmd_table)
  413         struct db_command       **last_cmdp;    /* IN_OUT */
  414         struct db_command       *cmd_table;
  415 {
  416         void db_skip_to_eol();
  417 
  418         do {
  419             db_command(last_cmdp, cmd_table);
  420             db_skip_to_eol();
  421         } while (db_read_token() == tSEMI_COLON && db_cmd_loop_done == 0);
  422 }
  423 
  424 /*
  425  * 'show' commands
  426  */
  427 extern void     db_listbreak_cmd();
  428 extern void     db_listwatch_cmd();
  429 extern void     db_show_regs(), db_show_one_thread(), db_show_one_task();
  430 extern void     db_show_all_threads();
  431 extern void     db_show_macro();
  432 extern void     vm_map_print(), vm_object_print(), vm_page_print();
  433 extern void     vm_map_copy_print();
  434 extern void     ipc_port_print(), ipc_pset_print(), db_show_all_slocks();
  435 extern void     ipc_kmsg_print(), ipc_msg_print();
  436 extern void     db_show_port_id();
  437 void            db_show_help();
  438 #if     NORMA_IPC
  439 extern void     netipc_packet_print(), netipc_pcs_print(), db_show_all_uids();
  440 extern void     db_show_all_proxies(), db_show_all_principals();
  441 extern void     db_show_all_uids_verbose();
  442 #endif  NORMA_IPC
  443 #if     NORMA_VM
  444 extern void     xmm_obj_print(), xmm_reply_print();
  445 #endif  NORMA_VM
  446 
  447 struct db_command db_show_all_cmds[] = {
  448         { "threads",    db_show_all_threads,    0,      0 },
  449         { "slocks",     db_show_all_slocks,     0,      0 },
  450 #if     NORMA_IPC
  451         { "uids",       db_show_all_uids,       0,      0 },
  452         { "proxies",    db_show_all_proxies,    0,      0 },
  453         { "principals", db_show_all_principals, 0,      0 },
  454         { "vuids",      db_show_all_uids_verbose, 0,    0 },
  455 #endif  NORMA_IPC
  456         { (char *)0 }
  457 };
  458 
  459 struct db_command db_show_cmds[] = {
  460         { "all",        0,                      0,      db_show_all_cmds },
  461         { "registers",  db_show_regs,           0,      0 },
  462         { "breaks",     db_listbreak_cmd,       0,      0 },
  463         { "watches",    db_listwatch_cmd,       0,      0 },
  464         { "thread",     db_show_one_thread,     0,      0 },
  465         { "task",       db_show_one_task,       0,      0 },
  466         { "macro",      db_show_macro,          CS_OWN, 0 },
  467         { "map",        vm_map_print,           0,      0 },
  468         { "object",     vm_object_print,        0,      0 },
  469         { "page",       vm_page_print,          0,      0 },
  470         { "copy",       vm_map_copy_print,      0,      0 },
  471         { "port",       ipc_port_print,         0,      0 },
  472         { "pset",       ipc_pset_print,         0,      0 },
  473         { "kmsg",       ipc_kmsg_print,         0,      0 },
  474         { "msg",        ipc_msg_print,          0,      0 },
  475         { "ipc_port",   db_show_port_id,        0,      0 },
  476 #if     NORMA_IPC
  477         { "packet",     netipc_packet_print,    0,      0 },
  478         { "pcs",        netipc_pcs_print,       0,      0 },
  479 #endif  NORMA_IPC
  480 #if     NORMA_VM
  481         { "xmm_obj",    xmm_obj_print,          0,      0 },
  482         { "xmm_reply",  xmm_reply_print,        0,      0 },
  483 #endif  NORMA_VM
  484         { (char *)0, }
  485 };
  486 
  487 extern void     db_print_cmd(), db_examine_cmd(), db_set_cmd();
  488 extern void     db_examine_forward(), db_examine_backward();
  489 extern void     db_search_cmd();
  490 extern void     db_write_cmd();
  491 extern void     db_delete_cmd(), db_breakpoint_cmd();
  492 extern void     db_deletewatch_cmd(), db_watchpoint_cmd();
  493 extern void     db_single_step_cmd(), db_trace_until_call_cmd(),
  494                 db_trace_until_matching_cmd(), db_continue_cmd();
  495 extern void     db_stack_trace_cmd(), db_cond_cmd();
  496 void            db_help_cmd();
  497 void            db_def_macro_cmd(), db_del_macro_cmd();
  498 void            db_fncall();
  499 
  500 struct db_command db_command_table[] = {
  501 #ifdef DB_MACHINE_COMMANDS
  502   /* this must be the first entry, if it exists */
  503         { "machine",    0,                      0,              0},
  504 #endif
  505         { "print",      db_print_cmd,           CS_OWN,         0 },
  506         { "examine",    db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
  507         { "x",          db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
  508         { "xf",         db_examine_forward,     CS_SET_DOT,     0 },
  509         { "xb",         db_examine_backward,    CS_SET_DOT,     0 },
  510         { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, 0 },
  511         { "set",        db_set_cmd,             CS_OWN,         0 },
  512         { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
  513         { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
  514         { "delete",     db_delete_cmd,          CS_OWN,         0 },
  515         { "d",          db_delete_cmd,          CS_OWN,         0 },
  516         { "break",      db_breakpoint_cmd,      CS_MORE,        0 },
  517         { "dwatch",     db_deletewatch_cmd,     CS_MORE,        0 },
  518         { "watch",      db_watchpoint_cmd,      CS_MORE,        0 },
  519         { "step",       db_single_step_cmd,     0,              0 },
  520         { "s",          db_single_step_cmd,     0,              0 },
  521         { "continue",   db_continue_cmd,        0,              0 },
  522         { "c",          db_continue_cmd,        0,              0 },
  523         { "until",      db_trace_until_call_cmd,0,              0 },
  524         { "next",       db_trace_until_matching_cmd,0,          0 },
  525         { "match",      db_trace_until_matching_cmd,0,          0 },
  526         { "trace",      db_stack_trace_cmd,     0,              0 },
  527         { "cond",       db_cond_cmd,            CS_OWN,         0 },
  528         { "call",       db_fncall,              CS_OWN,         0 },
  529         { "macro",      db_def_macro_cmd,       CS_OWN,         0 },
  530         { "dmacro",     db_del_macro_cmd,       CS_OWN,         0 },
  531         { "show",       0,                      0,      db_show_cmds },
  532         { (char *)0, }
  533 };
  534 
  535 #ifdef DB_MACHINE_COMMANDS
  536 
  537 /* this function should be called to install the machine dependent
  538    commands. It should be called before the debugger is enabled  */
  539 void db_machine_commands_install(ptr)
  540 struct db_command *ptr;
  541 {
  542   db_command_table[0].more = ptr;
  543   return;
  544 }
  545 
  546 #endif
  547 
  548 
  549 struct db_command       *db_last_command = 0;
  550 
  551 void
  552 db_help_cmd()
  553 {
  554         struct db_command *cmd = db_command_table;
  555 
  556         while (cmd->name != 0) {
  557             db_printf("%-12s", cmd->name);
  558             db_end_line();
  559             cmd++;
  560         }
  561 }
  562 
  563 int     (*ddb_display)();
  564 
  565 void
  566 db_command_loop()
  567 {
  568         jmp_buf_t db_jmpbuf;
  569         jmp_buf_t *prev = db_recover;
  570         extern int db_output_line;
  571         extern int db_macro_level;
  572 #if     NORMA_IPC
  573         extern int _node_self;  /* node_self() may not be callable yet */
  574 #endif  NORMA_IPC
  575 
  576         /*
  577          * Initialize 'prev' and 'next' to dot.
  578          */
  579         db_prev = db_dot;
  580         db_next = db_dot;
  581 
  582         if (ddb_display)
  583                 (*ddb_display)();
  584 
  585         db_cmd_loop_done = 0;
  586         while (!db_cmd_loop_done) {
  587             (void) _setjmp(db_recover = &db_jmpbuf);
  588             db_macro_level = 0;
  589             if (db_print_position() != 0)
  590                 db_printf("\n");
  591             db_output_line = 0;
  592             db_printf("db%s", (db_default_thread)? "t": "");
  593 #if     NORMA_IPC
  594             db_printf("%d", _node_self);
  595 #endif
  596 #if     NCPUS > 1
  597             db_printf("{%d}", cpu_number());
  598 #endif
  599             db_printf("> ");
  600 
  601             (void) db_read_line("!!");
  602             db_command_list(&db_last_command, db_command_table);
  603         }
  604 
  605         db_recover = prev;
  606 }
  607 
  608 boolean_t
  609 db_exec_cmd_nest(cmd, size)
  610         char *cmd;
  611         int  size;
  612 {
  613         struct db_lex_context lex_context;
  614 
  615         db_cmd_loop_done = 0;
  616         if (cmd) {
  617             db_save_lex_context(&lex_context);
  618             db_switch_input(cmd, size /**OLD, &lex_context OLD**/);
  619         }
  620         db_command_list(&db_last_command, db_command_table);
  621         if (cmd)
  622             db_restore_lex_context(&lex_context);
  623         return(db_cmd_loop_done == 0);
  624 }
  625 
  626 #ifdef __GNUC__
  627 extern __volatile__ void _longjmp();
  628 #endif
  629 
  630 void db_error(s)
  631         char *s;
  632 {
  633         extern int db_macro_level;
  634 
  635         db_macro_level = 0;
  636         if (db_recover) {
  637             if (s)
  638                 db_printf(s);
  639             db_flush_lex();
  640             _longjmp(db_recover, 1);
  641         }
  642         else
  643         {
  644             if (s)
  645                 db_printf(s);
  646             panic("db_error");
  647         }
  648 }
  649 
  650 /*
  651  * Call random function:
  652  * !expr(arg,arg,arg)
  653  */
  654 void
  655 db_fncall()
  656 {
  657         db_expr_t       fn_addr;
  658 #define MAXARGS         11
  659         db_expr_t       args[MAXARGS];
  660         int             nargs = 0;
  661         db_expr_t       retval;
  662         db_expr_t       (*func)();
  663         int             t;
  664 
  665         if (!db_expression(&fn_addr)) {
  666             db_printf("Bad function \"%s\"\n", db_tok_string);
  667             db_flush_lex();
  668             return;
  669         }
  670         func = (db_expr_t (*) ()) fn_addr;
  671 
  672         t = db_read_token();
  673         if (t == tLPAREN) {
  674             if (db_expression(&args[0])) {
  675                 nargs++;
  676                 while ((t = db_read_token()) == tCOMMA) {
  677                     if (nargs == MAXARGS) {
  678                         db_printf("Too many arguments\n");
  679                         db_flush_lex();
  680                         return;
  681                     }
  682                     if (!db_expression(&args[nargs])) {
  683                         db_printf("Argument missing\n");
  684                         db_flush_lex();
  685                         return;
  686                     }
  687                     nargs++;
  688                 }
  689                 db_unread_token(t);
  690             }
  691             if (db_read_token() != tRPAREN) {
  692                 db_printf("?\n");
  693                 db_flush_lex();
  694                 return;
  695             }
  696         }
  697         while (nargs < MAXARGS) {
  698             args[nargs++] = 0;
  699         }
  700 
  701         retval = (*func)(args[0], args[1], args[2], args[3], args[4],
  702                          args[5], args[6], args[7], args[8], args[9] );
  703         db_printf(" %#N\n", retval);
  704 }
  705 
  706 boolean_t
  707 db_option(modif, option)
  708         char    *modif;
  709         int     option;
  710 {
  711         register char *p;
  712 
  713         for (p = modif; *p; p++)
  714             if (*p == option)
  715                 return(TRUE);
  716         return(FALSE);
  717 }

Cache object: 6ff1fd20e50303c7970692bc0a25408f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.