126417Ssam #ifndef lint
2*29663Ssam static char sccsid[] = "@(#)expr.c 1.2 (Berkeley) 07/25/86";
326417Ssam #endif
426417Ssam /*
526417Ssam *
626417Ssam * UNIX debugger
726417Ssam *
826417Ssam */
926417Ssam
1026417Ssam #include "defs.h"
1126417Ssam
1226417Ssam MSG BADSYM;
1326417Ssam MSG BADVAR;
1426417Ssam MSG BADKET;
1526417Ssam MSG BADSYN;
1626417Ssam MSG NOCFN;
1726417Ssam MSG NOADR;
1826417Ssam MSG BADLOC;
1926417Ssam
2026417Ssam ADDR lastframe;
2126417Ssam ADDR savlastf;
2226417Ssam ADDR savframe;
2326417Ssam ADDR savpc;
2426417Ssam ADDR callpc;
2526417Ssam
2626417Ssam
2726417Ssam
2826417Ssam CHAR *lp;
2926417Ssam INT radix;
3026417Ssam STRING errflg;
3126417Ssam ADDR localval;
3226417Ssam CHAR isymbol[1024];
3326417Ssam
3426417Ssam CHAR lastc,peekc;
3526417Ssam
3626417Ssam L_INT dot;
3726417Ssam L_INT ditto;
3826417Ssam INT dotinc;
3926417Ssam L_INT var[];
4026417Ssam L_INT expv;
4126417Ssam
4226417Ssam
4326417Ssam
4426417Ssam
expr(a)4526417Ssam expr(a)
4626417Ssam { /* term | term dyadic expr | */
4726417Ssam REG rc;
4826417Ssam REG L_INT lhs;
4926417Ssam
5026417Ssam rdc(); lp--; rc=term(a);
5126417Ssam
5226417Ssam WHILE rc
5326417Ssam DO lhs = expv;
5426417Ssam
5526417Ssam switch ((int)readchar()) {
5626417Ssam
5726417Ssam case '+':
5826417Ssam term(a|1); expv += lhs; break;
5926417Ssam
6026417Ssam case '-':
6126417Ssam term(a|1); expv = lhs - expv; break;
6226417Ssam
6326417Ssam case '#':
6426417Ssam term(a|1); expv = round(lhs,expv); break;
6526417Ssam
6626417Ssam case '*':
6726417Ssam term(a|1); expv *= lhs; break;
6826417Ssam
6926417Ssam case '%':
7026417Ssam term(a|1); expv = lhs/expv; break;
7126417Ssam
7226417Ssam case '&':
7326417Ssam term(a|1); expv &= lhs; break;
7426417Ssam
7526417Ssam case '|':
7626417Ssam term(a|1); expv |= lhs; break;
7726417Ssam
7826417Ssam case ')':
7926417Ssam IF (a&2)==0 THEN error(BADKET); FI
8026417Ssam
8126417Ssam default:
8226417Ssam lp--;
8326417Ssam return(rc);
8426417Ssam }
8526417Ssam OD
8626417Ssam return(rc);
8726417Ssam }
8826417Ssam
term(a)8926417Ssam term(a)
9026417Ssam { /* item | monadic item | (expr) | */
9126417Ssam
9226417Ssam switch ((int)readchar()) {
9326417Ssam
9426417Ssam case '*':
9526417Ssam term(a|1); expv=chkget(expv,DSP); return(1);
9626417Ssam
9726417Ssam case '@':
9826417Ssam term(a|1); expv=chkget(expv,ISP); return(1);
9926417Ssam
10026417Ssam case '-':
10126417Ssam term(a|1); expv = -expv; return(1);
10226417Ssam
10326417Ssam case '~':
10426417Ssam term(a|1); expv = ~expv; return(1);
10526417Ssam
10626417Ssam case '#':
10726417Ssam term(a|1); expv = !expv; return(1);
10826417Ssam
10926417Ssam case '(':
11026417Ssam expr(2);
11126417Ssam IF *lp!=')'
11226417Ssam THEN error(BADSYN);
11326417Ssam ELSE lp++; return(1);
11426417Ssam FI
11526417Ssam
11626417Ssam default:
11726417Ssam lp--;
11826417Ssam return(item(a));
11926417Ssam }
12026417Ssam }
12126417Ssam
item(a)12226417Ssam item(a)
12326417Ssam { /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
12426417Ssam REG base, d, regptr;
12526417Ssam CHAR savc;
12626417Ssam REG L_INT frame;
12726417Ssam register struct nlist *symp;
12826417Ssam
12926417Ssam readchar();
13026417Ssam IF symchar(0)
13126417Ssam THEN readsym();
13226417Ssam IF lastc=='.'
13326417Ssam THEN frame= *(ADDR *)(((ADDR)(&u))+FP); lastframe=0;
13426417Ssam callpc= *(ADDR *)(((ADDR)(&u))+PC);
13526417Ssam WHILE errflg==0
13626417Ssam DO savpc=callpc;
13726417Ssam findsym(callpc,ISYM);
13826417Ssam IF eqsym(cursym->n_un.n_name,isymbol,'~')
13926417Ssam THEN break;
14026417Ssam FI
14126417Ssam callpc=get(frame-8, DSP);
14226417Ssam lastframe=frame;
14326417Ssam frame=get(frame, DSP)&ALIGN;
14426417Ssam IF frame==0
14526417Ssam THEN error(NOCFN);
14626417Ssam FI
14726417Ssam OD
14826417Ssam savlastf=lastframe; savframe=frame;
14926417Ssam readchar();
15026417Ssam IF symchar(0)
15126417Ssam THEN chkloc(expv=frame);
15226417Ssam FI
15326417Ssam ELIF (symp=lookup(isymbol))==0 THEN error(BADSYM);
15426417Ssam ELSE expv = symp->n_value;
15526417Ssam FI
15626417Ssam lp--;
15726417Ssam
15826417Ssam
15926417Ssam ELIF getnum()
16026417Ssam THEN ;
16126417Ssam ELIF lastc=='.'
16226417Ssam THEN readchar();
16326417Ssam IF symchar(0)
16426417Ssam THEN lastframe=savlastf; callpc=savpc;
16526417Ssam chkloc(savframe);
16626417Ssam ELSE expv=dot;
16726417Ssam FI
16826417Ssam lp--;
16926417Ssam
17026417Ssam ELIF lastc=='"'
17126417Ssam THEN expv=ditto;
17226417Ssam
17326417Ssam ELIF lastc=='+'
17426417Ssam THEN expv=inkdot(dotinc);
17526417Ssam
17626417Ssam ELIF lastc=='^'
17726417Ssam THEN expv=inkdot(-dotinc);
17826417Ssam
17926417Ssam ELIF lastc=='<'
18026417Ssam THEN savc=rdc();
181*29663Ssam IF (regptr=getreg(savc)) != -1
18226417Ssam THEN IF kcore THEN expv = *(int *)regptr;
18326417Ssam ELSE expv= *(ADDR *)(((ADDR)(&u))+regptr); FI
18426417Ssam ELIF (base=varchk(savc)) != -1
18526417Ssam THEN expv=var[base];
18626417Ssam ELSE error(BADVAR);
18726417Ssam FI
18826417Ssam
18926417Ssam ELIF lastc=='\''
19026417Ssam THEN d=4; expv=0;
19126417Ssam WHILE quotchar()
19226417Ssam DO IF d--
19326417Ssam THEN expv <<= 8;
19426417Ssam expv |= lastc;
19526417Ssam ELSE error(BADSYN);
19626417Ssam FI
19726417Ssam OD
19826417Ssam
19926417Ssam ELIF a
20026417Ssam THEN error(NOADR);
20126417Ssam ELSE lp--; return(0);
20226417Ssam FI
20326417Ssam return(1);
20426417Ssam }
20526417Ssam
20626417Ssam /* service routines for expression reading */
getnum()20726417Ssam getnum()
20826417Ssam {
20926417Ssam REG base,d,frpt;
21026417Ssam UNION{REAL r; L_INT i;} real;
21126417Ssam IF (base = radix) < 0 THEN base = -base; FI
21226417Ssam IF isdigit(lastc)
21326417Ssam THEN expv = 0;
21426417Ssam WHILE (base>10 ? isxdigit(lastc) : isdigit(lastc))
21526417Ssam DO
21626417Ssam REG m;
21726417Ssam m = MAXINT/base;
21826417Ssam if(expv>m)
21926417Ssam /* avoid overflow */
22026417Ssam expv = (expv-m)*base+m*base;
22126417Ssam else
22226417Ssam expv *= base;
22326417Ssam IF (d=convdig(lastc))>=base ORF d<0 THEN error(BADSYN); FI
22426417Ssam expv += d; readchar();
22526417Ssam IF expv==0
22626417Ssam THEN IF (lastc=='x' ORF lastc=='X')
22726417Ssam THEN base=16; readchar();
22826417Ssam ELIF (lastc=='t' ORF lastc=='T')
22926417Ssam THEN base=10; readchar();
23026417Ssam ELIF (lastc=='o' ORF lastc=='O')
23126417Ssam THEN base=8; readchar();
23226417Ssam FI
23326417Ssam FI
23426417Ssam OD
23526417Ssam IF lastc=='.' ANDF (base==10 ORF expv==0)
23626417Ssam THEN real.r=expv; frpt=0; base=10;
23726417Ssam WHILE isdigit(readchar())
23826417Ssam DO real.r *= base; frpt++;
23926417Ssam real.r += lastc-'0';
24026417Ssam OD
24126417Ssam WHILE frpt--
24226417Ssam DO real.r /= base; OD
24326417Ssam expv = real.i;
24426417Ssam FI
24526417Ssam peekc=lastc;
24626417Ssam return(1);
24726417Ssam ELSE return(0);
24826417Ssam FI
24926417Ssam }
25026417Ssam
readsym()25126417Ssam readsym()
25226417Ssam {
25326417Ssam REG char *p;
25426417Ssam
25526417Ssam p = isymbol;
25626417Ssam REP IF p < &isymbol[sizeof(isymbol)-1]
25726417Ssam THEN *p++ = lastc;
25826417Ssam FI
25926417Ssam readchar();
26026417Ssam PER symchar(1) DONE
26126417Ssam *p++ = 0;
26226417Ssam }
26326417Ssam
convdig(c)26426417Ssam convdig(c)
26526417Ssam CHAR c;
26626417Ssam {
26726417Ssam IF isdigit(c)
26826417Ssam THEN return(c-'0');
26926417Ssam ELIF isxdigit(c)
27026417Ssam THEN return(c-'a'+10);
27126417Ssam ELSE return(-1);
27226417Ssam FI
27326417Ssam }
27426417Ssam
symchar(dig)27526417Ssam symchar(dig)
27626417Ssam {
27726417Ssam IF lastc=='\\' THEN readchar(); return(TRUE); FI
27826417Ssam return ( isalpha(lastc) ORF lastc=='_' ORF dig ANDF isdigit(lastc) );
27926417Ssam }
28026417Ssam
varchk(name)28126417Ssam varchk(name)
28226417Ssam REG name;
28326417Ssam {
28426417Ssam IF isdigit(name) THEN return(name-'0'); FI
28526417Ssam IF isalpha(name) THEN return((name&037)-1+10); FI
28626417Ssam return(-1);
28726417Ssam }
28826417Ssam
chkloc(frame)28926417Ssam chkloc(frame)
29026417Ssam L_INT frame;
29126417Ssam {
29226417Ssam readsym();
29326417Ssam REP IF localsym(frame)==0 THEN error(BADLOC); FI
29426417Ssam expv=localval;
29526417Ssam PER !eqsym(cursym->n_un.n_name,isymbol,'~') DONE
29626417Ssam }
29726417Ssam
eqsym(s1,s2,c)29826417Ssam eqsym(s1, s2, c)
29926417Ssam register char *s1, *s2;
30026417Ssam {
30126417Ssam
30226417Ssam if (!strcmp(s1,s2))
30326417Ssam return (1);
30426417Ssam if (*s1 == c && !strcmp(s1+1, s2))
30526417Ssam return (1);
30626417Ssam return (0);
30726417Ssam }
308