130296Ssam /*
230296Ssam * Copyright (c) 1986 Regents of the University of California.
330296Ssam * All rights reserved. The Berkeley software License Agreement
430296Ssam * specifies the terms and conditions for redistribution.
530296Ssam *
6*41345Ssklower * @(#)kdb_expr.c 7.6 (Berkeley) 05/03/90
730296Ssam */
830107Ssam
930107Ssam #include "../kdb/defs.h"
1030107Ssam
11*41345Ssklower char *kdbBADSYM;
12*41345Ssklower char *kdbBADVAR;
13*41345Ssklower char *kdbBADKET;
14*41345Ssklower char *kdbBADSYN;
15*41345Ssklower char *kdbNOCFN;
16*41345Ssklower char *kdbNOADR;
17*41345Ssklower char *kdbBADLOC;
1830107Ssam
19*41345Ssklower ADDR kdblastframe;
20*41345Ssklower ADDR kdbsavlastf;
21*41345Ssklower ADDR kdbsavframe;
22*41345Ssklower ADDR kdbsavpc;
23*41345Ssklower ADDR kdbcallpc;
2430107Ssam
25*41345Ssklower char *kdblp;
26*41345Ssklower int kdbradix;
27*41345Ssklower char kdbisymbol[1024];
2830107Ssam
29*41345Ssklower char kdblastc, kdbpeekc;
3030107Ssam
31*41345Ssklower long kdbditto;
32*41345Ssklower long kdbexpv;
3330107Ssam
3430296Ssam static long
kdbround(a,b)35*41345Ssklower kdbround(a,b)
3630296Ssam register long a, b;
3730296Ssam {
3830296Ssam register long w;
3930296Ssam
4030296Ssam w = (a/b)*b;
4130296Ssam if (a!=w)
4230296Ssam w += b;
4330296Ssam return (w);
4430296Ssam }
4530296Ssam
4630107Ssam /* term | term dyadic expr | */
kdbexpr(a)47*41345Ssklower kdbexpr(a)
4830107Ssam {
4930107Ssam register rc;
5030107Ssam register long lhs;
5130107Ssam
52*41345Ssklower (void) kdbrdc(); kdblp--; rc=kdbterm(a);
5330107Ssam
5430107Ssam while (rc) {
55*41345Ssklower lhs = kdbexpv;
56*41345Ssklower switch ((int)kdbreadchar()) {
5730107Ssam case '+':
58*41345Ssklower (void) kdbterm(a|1); kdbexpv += lhs; break;
5930107Ssam case '-':
60*41345Ssklower (void) kdbterm(a|1); kdbexpv = lhs - kdbexpv; break;
6130107Ssam case '#':
62*41345Ssklower (void) kdbterm(a|1); kdbexpv = kdbround(lhs,kdbexpv); break;
6330107Ssam case '*':
64*41345Ssklower (void) kdbterm(a|1); kdbexpv *= lhs; break;
6530107Ssam case '%':
66*41345Ssklower (void) kdbterm(a|1); kdbexpv = lhs/kdbexpv; break;
6730107Ssam case '&':
68*41345Ssklower (void) kdbterm(a|1); kdbexpv &= lhs; break;
6930107Ssam case '|':
70*41345Ssklower (void) kdbterm(a|1); kdbexpv |= lhs; break;
7130107Ssam case ')':
7230107Ssam if ((a&2)==0)
73*41345Ssklower kdberror(kdbBADKET);
7430107Ssam default:
75*41345Ssklower kdblp--;
7630107Ssam return (rc);
7730107Ssam }
7830107Ssam }
7930107Ssam return (rc);
8030107Ssam }
8130107Ssam
8230107Ssam /* item | monadic item | (expr) | */
8330107Ssam static
kdbterm(a)84*41345Ssklower kdbterm(a)
8530107Ssam {
8630107Ssam
87*41345Ssklower switch ((int)kdbreadchar()) {
8830107Ssam case '*':
89*41345Ssklower (void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,DSP);
9030107Ssam return(1);
9130107Ssam case '@':
92*41345Ssklower (void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,ISP);
9330107Ssam return(1);
9430107Ssam case '-':
95*41345Ssklower (void) kdbterm(a|1); kdbexpv = -kdbexpv;
9630107Ssam return(1);
9730107Ssam case '~':
98*41345Ssklower (void) kdbterm(a|1); kdbexpv = ~kdbexpv;
9930107Ssam return(1);
10030107Ssam case '#':
101*41345Ssklower (void) kdbterm(a|1); kdbexpv = !kdbexpv;
10230107Ssam return(1);
10330107Ssam case '(':
104*41345Ssklower (void) kdbexpr(2);
105*41345Ssklower if (*kdblp!=')')
106*41345Ssklower kdberror(kdbBADSYN);
107*41345Ssklower kdblp++;
10830107Ssam return(1);
10930107Ssam }
110*41345Ssklower kdblp--;
111*41345Ssklower return (kdbitem(a));
11230107Ssam }
11330107Ssam
11430107Ssam /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
11530107Ssam static
kdbitem(a)116*41345Ssklower kdbitem(a)
11730107Ssam {
11830107Ssam register base, d, regptr;
11930107Ssam char savc;
12030107Ssam register long frame;
12130107Ssam register struct nlist *symp;
12230107Ssam
123*41345Ssklower (void) kdbreadchar();
124*41345Ssklower if (kdbsymchar(0)) {
125*41345Ssklower kdbreadsym();
126*41345Ssklower if (kdblastc=='.') {
127*41345Ssklower frame = kdbpcb.pcb_fp; kdblastframe = 0;
128*41345Ssklower kdbcallpc = kdbpcb.pcb_pc;
129*41345Ssklower while (!kdberrflg) {
130*41345Ssklower kdbsavpc = kdbcallpc;
131*41345Ssklower (void) kdbfindsym((long)kdbcallpc,ISYM);
132*41345Ssklower if (kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'))
13330136Ssam break;
134*41345Ssklower kdbcallpc = getprevpc(frame);
135*41345Ssklower kdblastframe = frame;
13630136Ssam frame = getprevframe(frame);
13730136Ssam if (frame == NOFRAME)
138*41345Ssklower kdberror(kdbNOCFN);
13930107Ssam }
140*41345Ssklower kdbsavlastf = kdblastframe; kdbsavframe = frame;
141*41345Ssklower (void) kdbreadchar();
142*41345Ssklower if (kdbsymchar(0))
143*41345Ssklower kdbchkloc(kdbexpv=frame);
144*41345Ssklower } else if ((symp=kdblookup(kdbisymbol))==0)
145*41345Ssklower kdberror(kdbBADSYM);
14630107Ssam else
147*41345Ssklower kdbexpv = symp->n_value;
148*41345Ssklower kdblp--;
14930136Ssam return (1);
15030136Ssam }
151*41345Ssklower if (kdbgetnum())
15230136Ssam return (1);
153*41345Ssklower switch (kdblastc) {
15430136Ssam case '.':
155*41345Ssklower (void) kdbreadchar();
156*41345Ssklower if (kdbsymchar(0)) {
157*41345Ssklower kdblastframe=kdbsavlastf; kdbcallpc=kdbsavpc;
158*41345Ssklower kdbchkloc((long)kdbsavframe);
15930107Ssam } else
160*41345Ssklower kdbexpv=kdbdot;
161*41345Ssklower kdblp--;
16230136Ssam break;
16330136Ssam case '"':
164*41345Ssklower kdbexpv=kdbditto;
16530136Ssam break;
16630136Ssam case '+':
167*41345Ssklower kdbexpv=kdbinkdot(kdbdotinc);
16830136Ssam break;
16930136Ssam case '^':
170*41345Ssklower kdbexpv=kdbinkdot(-kdbdotinc);
17130136Ssam break;
17230136Ssam case '<':
173*41345Ssklower savc=kdbrdc();
174*41345Ssklower if ((regptr=kdbgetreg(savc)) != -1)
175*41345Ssklower kdbexpv = *(int *)regptr;
176*41345Ssklower else if ((base=kdbvarchk(savc)) != -1)
177*41345Ssklower kdbexpv=kdbvar[base];
17830107Ssam else
179*41345Ssklower kdberror(kdbBADVAR);
18030136Ssam break;
18130136Ssam case '\'':
182*41345Ssklower d=4; kdbexpv=0;
183*41345Ssklower while (kdbquotchar()) {
18430107Ssam if (d--) {
185*41345Ssklower kdbexpv <<= 8;
186*41345Ssklower kdbexpv |= kdblastc;
18730107Ssam } else
188*41345Ssklower kdberror(kdbBADSYN);
18930107Ssam }
19030136Ssam break;
19130136Ssam default:
19230136Ssam if (a)
193*41345Ssklower kdberror(kdbNOADR);
194*41345Ssklower kdblp--;
19530107Ssam return(0);
19630107Ssam }
19730107Ssam return (1);
19830107Ssam }
19930107Ssam
20030107Ssam /* service routines for expression reading */
20130107Ssam static
kdbgetnum()202*41345Ssklower kdbgetnum()
20330107Ssam {
20430107Ssam register base,d,frpt;
20530107Ssam
206*41345Ssklower if (!isdigit(kdblastc))
20730107Ssam return (0);
208*41345Ssklower if ((base = kdbradix) < 0)
20930107Ssam base = -base;
210*41345Ssklower kdbexpv = 0;
211*41345Ssklower while (base>10 ? isxdigit(kdblastc) : isdigit(kdblastc)) {
21230107Ssam register m = MAXINT/base;
21330107Ssam
214*41345Ssklower if (kdbexpv>m) /* avoid overflow */
215*41345Ssklower kdbexpv = (kdbexpv-m)*base+m*base;
21630107Ssam else
217*41345Ssklower kdbexpv *= base;
218*41345Ssklower if ((d=kdbconvdig(kdblastc))>=base || d<0)
219*41345Ssklower kdberror(kdbBADSYN);
220*41345Ssklower kdbexpv += d; (void) kdbreadchar();
221*41345Ssklower if (kdbexpv==0) {
222*41345Ssklower if (kdblastc=='x' || kdblastc=='X') {
223*41345Ssklower base=16; (void) kdbreadchar();
224*41345Ssklower } else if (kdblastc=='t' || kdblastc=='T') {
225*41345Ssklower base=10; (void) kdbreadchar();
226*41345Ssklower } else if (kdblastc=='o' || kdblastc=='O') {
227*41345Ssklower base=8; (void) kdbreadchar();
22830107Ssam }
22930107Ssam }
23030107Ssam }
231*41345Ssklower if (kdblastc=='.' && (base==10 || kdbexpv==0)) {
23238199Smckusick frpt=0; base=10;
233*41345Ssklower while (isdigit(kdbreadchar())) {
23438199Smckusick if (frpt)
23538199Smckusick continue;
23638199Smckusick frpt++;
237*41345Ssklower if (kdblastc - '0' >= 5)
238*41345Ssklower kdbexpv++;
23930107Ssam }
24030107Ssam }
241*41345Ssklower kdbpeekc=kdblastc;
24230107Ssam return (1);
24330107Ssam }
24430107Ssam
24530107Ssam static
kdbreadsym()246*41345Ssklower kdbreadsym()
24730107Ssam {
24830107Ssam register char *p;
24930107Ssam
250*41345Ssklower p = kdbisymbol;
25130107Ssam do {
252*41345Ssklower if (p < &kdbisymbol[sizeof(kdbisymbol)-1])
253*41345Ssklower *p++ = kdblastc;
254*41345Ssklower (void) kdbreadchar();
255*41345Ssklower } while (kdbsymchar(1));
25630107Ssam *p++ = 0;
25730107Ssam }
25830107Ssam
25930107Ssam static
kdbconvdig(c)260*41345Ssklower kdbconvdig(c)
26130107Ssam char c;
26230107Ssam {
26330107Ssam if (isdigit(c))
26430107Ssam return (c-'0');
26530107Ssam if (isxdigit(c))
26630107Ssam return (c-'a'+10);
26730107Ssam return (-1);
26830107Ssam }
26930107Ssam
27030107Ssam static
kdbsymchar(dig)271*41345Ssklower kdbsymchar(dig)
27230107Ssam {
27330107Ssam
274*41345Ssklower if (kdblastc=='\\') {
275*41345Ssklower (void) kdbreadchar();
27630118Ssam return (1);
27730107Ssam }
278*41345Ssklower return (isalpha(kdblastc) || kdblastc=='_' || dig && isdigit(kdblastc));
27930107Ssam }
28030107Ssam
kdbvarchk(name)281*41345Ssklower kdbvarchk(name)
28230107Ssam register name;
28330107Ssam {
28430107Ssam if (isdigit(name))
28530107Ssam return (name-'0');
28630107Ssam if (isalpha(name))
28730107Ssam return ((name&037)-1+10);
28830107Ssam return (-1);
28930107Ssam }
29030107Ssam
29130107Ssam static
kdbchkloc(frame)292*41345Ssklower kdbchkloc(frame)
29330107Ssam long frame;
29430107Ssam {
29530107Ssam
296*41345Ssklower kdbreadsym();
29730107Ssam do {
298*41345Ssklower if (kdblocalsym(frame)==0)
299*41345Ssklower kdberror(kdbBADLOC);
300*41345Ssklower kdbexpv=kdblocalval;
301*41345Ssklower } while (!kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'));
30230107Ssam }
30330107Ssam
kdbeqsym(s1,s2,c)304*41345Ssklower kdbeqsym(s1, s2, c)
30530107Ssam register char *s1, *s2;
30630107Ssam {
30730107Ssam
308*41345Ssklower if (kdbstreq(s1,s2))
30930107Ssam return (1);
310*41345Ssklower if (*s1 == c && kdbstreq(s1+1, s2))
31130107Ssam return (1);
31230107Ssam return (0);
31330107Ssam }
31430107Ssam
31530107Ssam static
kdbstreq(s1,s2)316*41345Ssklower kdbstreq(s1, s2)
31730107Ssam char *s1, *s2;
31830107Ssam {
31930107Ssam
32030107Ssam while (*s1 == *s2++)
32130107Ssam if (*s1++ == '\0')
32230107Ssam return (1);
32330107Ssam return (0);
32430107Ssam }
325