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

Cache object: a858bdc88ee6058365c11659ee91cf28


[ 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.