Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <bio.h>
#include <mach.h>
#define Extern extern
#include "sparc.h"

char    buf[128], lastcmd[128];
char    fmt = 'X';
int     width = 60;
int     inc;

ulong   expr(char*);
ulong   expr1(char*);
char*   term(char*, ulong*);

char *
nextc(char *p)
{
        while(*p && (*p == ' ' || *p == '\t') && *p != '\n')
                p++;

        if(*p == '\n')
                *p = '\0';

        return p;
}

char *
numsym(char *addr, ulong *val)
{
        char tsym[128], *t;
        static char *delim = "`'<>/\\@*|-~+-/=?\n";
        Symbol s;
        char c;

        t = tsym;
        while(c = *addr) {
                if(strchr(delim, c))
                        break;
                *t++ = c;
                addr++;
        }
        t[0] = '\0';

        if(strcmp(tsym, ".") == 0) {
                *val = dot;
                return addr;
        }

        if(lookup(0, tsym, &s))
                *val = s.value;
        else {
                if(tsym[0] == '#')
                        *val = strtoul(tsym+1, 0, 16);
                else
                        *val = strtoul(tsym, 0, 0);
        }
        return addr;
}

ulong
expr(char *addr)
{
        ulong t, t2;
        char op;

        if(*addr == '\0')
                return dot;

        addr = numsym(addr, &t);

        if(*addr == '\0')
                return t;

        addr = nextc(addr);
        op = *addr++;
        numsym(addr, &t2);
        switch(op) {
        default:
                Bprint(bioout, "expr syntax\n");
                return 0;
        case '+':
                t += t2;
                break;
        case '-':
                t -= t2;
                break;
        case '%':
                t /= t2;
                break;
        case '&':
                t &= t2;
                break;
        case '|':
                t |= t2;
                break;
        }

        return t;
}

int
buildargv(char *str, char **args, int max)
{
        int na = 0;

        while (na < max) {
                while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0')
                        str++;

                if(*str == '\0')
                        return na;

                args[na++] = str;
                while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0')
                        str++;

                if(*str == '\n')
                        *str = '\0';

                if(*str == '\0')
                        break;

                *str++ = '\0';
        }
        return na;
}

void
colon(char *addr, char *cp)
{
        int argc;
        char *argv[100];
        char tbuf[512];

        cp = nextc(cp);
        switch(*cp) {
        default:
                Bprint(bioout, "?\n");
                return;
        case 'b':
                breakpoint(addr, cp+1);
                return;

        case 'd':
                delbpt(addr);
                return;

        /* These fall through to print the stopped address */
        case 'r':
                reset();
                argc = buildargv(cp+1, argv, 100);
                initstk(argc, argv);
                count = 0;
                atbpt = 0;
                run();
                break;
        case 'c':
                count = 0;
                atbpt = 0;
                run();
                break;
        case 's':
                cp = nextc(cp+1);
                count = 0;
                if(*cp)
                        count = strtoul(cp, 0, 0);
                if(count == 0)
                        count = 1;
                atbpt = 0;
                run();
                break;
        }

        dot = reg.pc;
        Bprint(bioout, "%s at #%lux ", atbpt ? "breakpoint" : "stopped", dot);
        symoff(tbuf, sizeof(tbuf), dot, CTEXT);
        Bprint(bioout, tbuf);
        if(fmt == 'z')
                printsource(dot);

        Bprint(bioout, "\n");
}


void
dollar(char *cp)
{
        cp = nextc(cp);
        switch(*cp) {
        default:
                Bprint(bioout, "?\n");
                break;

        case 'c':
        case 'C':
                stktrace(*cp);
                break;

        case 'b':
                dobplist();
                break;

        case 'r':
                dumpreg();
                break;

        case 'R':
                dumpreg();
                /* fall through */

        case 'f':
                dumpfreg();
                break;

        case 'F':
                dumpdreg();
                break;

        case 'q':
                exits(0);
                break;

        case 'Q':
                isum();
                segsum();
                break;

        case 't':
                cp++;
                switch(*cp) {
                default:
                        Bprint(bioout, ":t[0sic]\n");
                        break;
                case '\0':
                        trace = 1;
                        break;
                case '0':
                        trace = 0;
                        sysdbg = 0;
                        calltree = 0;
                        break;
                case 's':
                        sysdbg = 1;
                        break;
                case 'i':
                        trace = 1;
                        break;
                case 'c':
                        calltree = 1;
                        break;
                }
                break;

        case 'i':
                cp++;
                switch(*cp) {
                default:
                        Bprint(bioout, "$i[isa]\n");
                        break;
                case 'i':
                        isum();
                        break;
                case 's':
                        segsum();
                        break;
                case 'a':
                        isum();
                        segsum();
                        iprofile();
                        break;
                case 'p':
                        iprofile();
                        break;
                }
        }
}

int
pfmt(char fmt, int mem, ulong val)
{
        int c, i;
        Symbol s;
        char *p, ch, str[1024];

        c = 0;
        switch(fmt) {
        default:
                Bprint(bioout, "bad modifier\n");
                return 0;
        case 'o':
                c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val);
                inc = 2;
                break;

        case 'O':
                c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
                inc = 4;
                break;

        case 'q':
                c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val);
                inc = 2;
                break;

        case 'Q':
                c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val);
                inc = 4;
                break;

        case 'd':
                c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val);
                inc = 2;
                break;


        case 'D':
                c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val);
                inc = 4;
                break;

        case 'x':
                c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val);
                inc = 2;
                break;

        case 'X':
                c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val);
                inc = 4;
                break;

        case 'u':
                c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val);
                inc = 2;
                break;

        case 'U':
                c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val);
                inc = 4;
                break;

        case 'b':
                c = Bprint(bioout, "%-3d ", (int)(mem ? getmem_b(dot) : val));
                inc = 1;
                break;

        case 'c':
                c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
                inc = 1;
                break;

        case 'C':
                ch = mem ? getmem_b(dot) : val;
                if(isprint(ch))
                        c = Bprint(bioout, "%c ", ch);
                else
                        c = Bprint(bioout, "\\x%.2x ", ch);
                inc = 1;
                break;

        case 's':
                i = 0;
                while(ch = getmem_b(dot+i))
                        str[i++] = ch;
                str[i] = '\0';
                dot += i;
                c = Bprint(bioout, "%s", str);
                inc = 0;
                break;

        case 'S':
                i = 0;
                while(ch = getmem_b(dot+i))
                        str[i++] = ch;
                str[i] = '\0';
                dot += i;
                for(p = str; *p; p++)
                        if(isprint(*p))
                                c += Bprint(bioout, "%c", *p);
                        else
                                c += Bprint(bioout, "\\x%.2ux", *p);
                inc = 0;
                break;

        case 'Y':
                p = ctime(mem ? getmem_b(dot) : val);
                p[30] = '\0';
                c = Bprint(bioout, "%s", p);
                inc = 4;
                break;

        case 'a':
                symoff(str, sizeof(str), dot, CTEXT);
                Bprint(bioout, "%s", str);
                inc = 0;
                break;

        case 'e':
                for (i = 0; globalsym(&s, i); i++)
                        Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value));
                inc = 0;
                break;

        case 'I':
        case 'i':
                inc = machdata->das(symmap, dot, fmt, str, sizeof(str));
                if (inc < 0) {
                        Bprint(bioout, "ki: %r\n");
                        return 0;
                }
                c = Bprint(bioout, "\t%s", str);
                break;

        case 'n':
                c = width+1;
                inc = 0;
                break;

        case '-':
                c = 0;
                inc = -1;
                break;

        case '+':
                c = 0;
                inc = 1;
                break;

        case '^':
                c = 0;
                if(inc > 0)
                        inc = -inc;
                break;

        case 'z':
                if (findsym(dot, CTEXT, &s))
                        Bprint(bioout, "  %s() ", s.name);
                printsource(dot);
                inc = 0;
                break;
        }
        return c;
}

void
eval(char *addr, char *p)
{
        ulong val;

        val = expr(addr);
        p = nextc(p);
        if(*p == '\0') {
                p[0] = fmt;
                p[1] = '\0';
        }
        pfmt(*p, 0, val);
        Bprint(bioout, "\n");
}

void
quesie(char *p)
{
        int c, count, i;
        char tbuf[512];

        c = 0;
        symoff(tbuf, sizeof(tbuf), dot, CTEXT);
        Bprint(bioout, "%s?\t", tbuf);

        while(*p) {
                p = nextc(p);
                if(*p == '"') {
                        for(p++; *p && *p != '"'; p++) {
                                Bputc(bioout, *p);
                                c++;
                        }
                        if(*p)
                                p++;
                        continue;
                }
                count = 0;
                while(*p >= '0' && *p <= '9')
                        count = count*10 + (*p++ - '0');
                if(count == 0)
                        count = 1;
                p = nextc(p);
                if(*p == '\0') {
                        p[0] = fmt;
                        p[1] = '\0';
                }
                for(i = 0; i < count; i++) {
                        c += pfmt(*p, 1, 0);
                        dot += inc;
                        if(c > width) {
                                Bprint(bioout, "\n");
                                symoff(tbuf, sizeof(tbuf), dot, CTEXT);
                                Bprint(bioout, "%s?\t", tbuf);
                                c = 0;
                        }
                }
                fmt = *p++;
                p = nextc(p);
        }
        Bprint(bioout, "\n");
}

void
catcher(void *a, char *msg)
{
        USED(a);
        if(strcmp(msg, "interrupt") != 0)
                noted(NDFLT);

        count = 1;
        print("ki\n");
        noted(NCONT);
}

void
setreg(char *addr, char *cp)
{
        int rn;

        dot = expr(addr);
        cp = nextc(cp);
        if(strcmp(cp, "pc") == 0) {
                reg.pc = dot;
                return;
        }
        if(strcmp(cp, "sp") == 0) {
                reg.r[1] = dot;
                return;
        }
        if(strcmp(cp, "y") == 0) {
                reg.Y = dot;
                return;
        }
        if(strcmp(cp, "psr") == 0) {
                reg.psr = dot;
                return;
        }
        if(*cp++ == 'r') {
                rn = strtoul(cp, 0, 10);
                if(rn > 0 && rn < 32) {
                        reg.r[rn] = dot;
                        return;
                }
        }
        Bprint(bioout, "bad register\n");
}

void
cmd(void)
{
        char *p, *a, *cp, *gotint;
        char addr[128];
        static char *cmdlet = ":$?/=>";
        int n, i;

        notify(catcher);

        dot = reg.pc;
        setjmp(errjmp);

        for(;;) {
                Bflush(bioout);
                p = buf;
                n = 0;
                for(;;) {
                        i = Bgetc(bin);
                        if(i < 0)
                                exits(0);
                        *p++ = i;
                        n++;
                        if(i == '\n')
                                break;
                }

                if(buf[0] == '\n')
                        strcpy(buf, lastcmd);
                else {
                        buf[n-1] = '\0';
                        strcpy(lastcmd, buf);
                }
                p = buf;
                a = addr;

                for(;;) {
                        p = nextc(p);
                        if(*p == 0 || strchr(cmdlet, *p))
                                break;
                        *a++ = *p++;
                }

                *a = '\0';
                cmdcount = 1;
                cp = strchr(addr, ',');
                if(cp != 0) {
                        if(cp[1] == '#')
                                cmdcount = strtoul(cp+2, &gotint, 16);
                        else
                                cmdcount = strtoul(cp+1, &gotint, 0);
                        *cp = '\0';
                }

                switch(*p) {
                case '$':
                        dollar(p+1);
                        break;
                case ':':
                        colon(addr, p+1);
                        break;
                case '/':
                case '?':
                        dot = expr(addr);
                        for(i = 0; i < cmdcount; i++)
                                quesie(p+1);
                        break;
                case '=':
                        eval(addr, p+1);
                        break;
                case '>':
                        setreg(addr, p+1);
                        break;
                default:
                        Bprint(bioout, "?\n");
                        break;
                }
        }
}