Annotation of Net2/ddb/db_command.c, revision 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.