Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

/*
 *
 *      debugger
 *
 */

#include "defs.h"
#include "fns.h"

static long     round(long, long);

extern  ADDR    ditto;
uvlong  expv;

static WORD
ascval(void)
{
        Rune r;

        if (readchar() == 0)
                return (0);
        r = lastc;
        while(quotchar())       /*discard chars to ending quote */
                ;
        return((WORD) r);
}

/*
 * read a floating point number
 * the result must fit in a WORD
 */

static WORD
fpin(char *buf)
{
        union {
                WORD w;
                float f;
        } x;

        x.f = atof(buf);
        return (x.w);
}

WORD
defval(WORD w)
{
        if (expr(0))
                return (expv);
        else
                return (w);
}

expr(int a)
{       /* term | term dyadic expr |  */
        int     rc;
        WORD    lhs;

        rdc();
        reread();
        rc=term(a);
        while (rc) {
                lhs = expv;
                switch ((int)readchar()) {

                case '+':
                        term(a|1);
                        expv += lhs;
                        break;

                case '-':
                        term(a|1);
                        expv = lhs - expv;
                        break;

                case '#':
                        term(a|1);
                        expv = round(lhs,expv);
                        break;

                case '*':
                        term(a|1);
                        expv *= lhs;
                        break;

                case '%':
                        term(a|1);
                        if(expv != 0)
                                expv = lhs/expv;
                        else{
                                if(lhs)
                                        expv = 1;
                                else
                                        expv = 0;
                        }
                        break;

                case '&':
                        term(a|1);
                        expv &= lhs;
                        break;

                case '|':
                        term(a|1);
                        expv |= lhs;
                        break;

                case ')':
                        if ((a&2)==0)
                                error("unexpected `)'");

                default:
                        reread();
                        return(rc);
                }
        }
        return(rc);
}

term(int a)
{       /* item | monadic item | (expr) | */
        ADDR e;

        switch ((int)readchar()) {

        case '*':
                term(a|1);
                if (geta(cormap, expv, &e) < 0)
                        error("%r");
                expv = e;
                return(1);

        case '@':
                term(a|1);
                if (geta(symmap, expv, &e) < 0)
                        error("%r");
                expv = e;
                return(1);

        case '-':
                term(a|1);
                expv = -expv;
                return(1);

        case '~':
                term(a|1);
                expv = ~expv;
                return(1);

        case '(':
                expr(2);
                if (readchar()!=')')
                        error("syntax error: `)' expected");
                return(1);

        default:
                reread();
                return(item(a));
        }
}

item(int a)
{       /* name [ . local ] | number | . | ^  | <register | 'x | | */
        char    *base;
        char    savc;
        uvlong e;
        Symbol s;
        char gsym[MAXSYM], lsym[MAXSYM];

        readchar();
        if (isfileref()) {
                readfname(gsym);
                rdc();                  /* skip white space */
                if (lastc == ':') {     /* it better be */
                        rdc();          /* skip white space */
                        if (!getnum(readchar))
                                error("bad number");
                        if (expv == 0)
                                expv = 1;       /* file begins at line 1 */
                        expv = file2pc(gsym, expv);
                        if (expv == -1)
                                error("%r");
                        return 1;
                }
                error("bad file location");
        } else if (symchar(0)) {        
                readsym(gsym);
                if (lastc=='.') {
                        readchar();     /* ugh */
                        if (lastc == '.') {
                                lsym[0] = '.';
                                readchar();
                                readsym(lsym+1);
                        } else if (symchar(0)) {
                                readsym(lsym);
                        } else
                                lsym[0] = 0;
                        if (localaddr(cormap, gsym, lsym, &e, rget) < 0)
                                error("%r");
                        expv = e;
                }
                else {
                        if (lookup(0, gsym, &s) == 0)
                                error("symbol not found");
                        expv = s.value;
                }
                reread();
        } else if (getnum(readchar)) {
                ;
        } else if (lastc=='.') {        
                readchar();
                if (!symchar(0) && lastc != '.') {
                        expv = dot;
                } else {
                        if (findsym(rget(cormap, mach->pc), CTEXT, &s) == 0)
                                error("no current function");
                        if (lastc == '.') {
                                lsym[0] = '.';
                                readchar();
                                readsym(lsym+1);
                        } else
                                readsym(lsym);
                        if (localaddr(cormap, s.name, lsym, &e, rget) < 0)
                                error("%r");
                        expv = e;
                }       
                reread();
        } else if (lastc=='"') {
                expv=ditto;
        } else if (lastc=='+') {
                expv=inkdot(dotinc);
        } else if (lastc=='^') {
                expv=inkdot(-dotinc);
        } else if (lastc=='<') {
                savc=rdc();
                base = regname(savc);
                expv = rget(cormap, base);
        }
        else if (lastc=='\'')
                expv = ascval();
        else if (a)
                error("address expected");
        else {  
                reread();
                return(0);
        }
        return(1);
}

#define MAXBASE 16

/* service routines for expression reading */
getnum(int (*rdf)(void))
{
        char *cp;
        int base, d;
        BOOL fpnum;
        char num[MAXLIN];

        base = 0;
        fpnum = FALSE;
        if (lastc == '#') {
                base = 16;
                (*rdf)();
        }
        if (convdig(lastc) >= MAXBASE)
                return (0);
        if (lastc == '0')
                switch ((*rdf)()) {
                case 'x':
                case 'X':
                        base = 16;
                        (*rdf)();
                        break;

                case 't':
                case 'T':
                        base = 10;
                        (*rdf)();
                        break;

                case 'o':
                case 'O':
                        base = 8;
                        (*rdf)();
                        break;
                default:
                        if (base == 0)
                                base = 8;
                        break;
                }
        if (base == 0)
                base = 10;
        expv = 0;
        for (cp = num, *cp = lastc; ;(*rdf)()) {
                if ((d = convdig(lastc)) < base) {
                        expv *= base;
                        expv += d;
                        *cp++ = lastc;
                }
                else if (lastc == '.') {
                        fpnum = TRUE;
                        *cp++ = lastc;
                } else {
                        reread();
                        break;
                }
        }
        if (fpnum)
                expv = fpin(num);
        return (1);
}

void
readsym(char *isymbol)
{
        char    *p;
        Rune r;

        p = isymbol;
        do {
                if (p < &isymbol[MAXSYM-UTFmax-1]){
                        r = lastc;
                        p += runetochar(p, &r);
                }
                readchar();
        } while (symchar(1));
        *p = 0;
}

void
readfname(char *filename)
{
        char    *p;
        Rune    c;

        /* snarf chars until un-escaped char in terminal char set */
        p = filename;
        do {
                if ((c = lastc) != '\\' && p < &filename[MAXSYM-UTFmax-1])
                        p += runetochar(p, &c);
                readchar();
        } while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
        *p = 0;
        reread();
}

convdig(int c)
{
        if (isdigit(c))
                return(c-'0');
        else if (!isxdigit(c))
                return(MAXBASE);
        else if (isupper(c))
                return(c-'A'+10);
        else
                return(c-'a'+10);
}

symchar(int dig)
{
        if (lastc=='\\') {
                readchar();
                return(TRUE);
        }
        return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc));
}

static long
round(long a, long b)
{
        long w;

        w = (a/b)*b;
        if (a!=w)
                w += b;
        return(w);
}