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

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

unix.superglobalmegacorp.com

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