Annotation of Net2/ddb/db_command.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.