]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/db/expr.c
mothra: never snarf the "Go:" box
[plan9front.git] / sys / src / cmd / db / expr.c
1 /*
2  *
3  *      debugger
4  *
5  */
6
7 #include "defs.h"
8 #include "fns.h"
9
10 static long     round(long, long);
11
12 extern  ADDR    ditto;
13 uvlong  expv;
14
15 static WORD
16 ascval(void)
17 {
18         Rune r;
19
20         if (readchar() == 0)
21                 return (0);
22         r = lastc;
23         while(quotchar())       /*discard chars to ending quote */
24                 ;
25         return((WORD) r);
26 }
27
28 /*
29  * read a floating point number
30  * the result must fit in a WORD
31  */
32
33 static WORD
34 fpin(char *buf)
35 {
36         union {
37                 WORD w;
38                 float f;
39         } x;
40
41         x.f = atof(buf);
42         return (x.w);
43 }
44
45 WORD
46 defval(WORD w)
47 {
48         if (expr(0))
49                 return (expv);
50         else
51                 return (w);
52 }
53
54 expr(int a)
55 {       /* term | term dyadic expr |  */
56         int     rc;
57         WORD    lhs;
58
59         rdc();
60         reread();
61         rc=term(a);
62         while (rc) {
63                 lhs = expv;
64                 switch ((int)readchar()) {
65
66                 case '+':
67                         term(a|1);
68                         expv += lhs;
69                         break;
70
71                 case '-':
72                         term(a|1);
73                         expv = lhs - expv;
74                         break;
75
76                 case '#':
77                         term(a|1);
78                         expv = round(lhs,expv);
79                         break;
80
81                 case '*':
82                         term(a|1);
83                         expv *= lhs;
84                         break;
85
86                 case '%':
87                         term(a|1);
88                         if(expv != 0)
89                                 expv = lhs/expv;
90                         else{
91                                 if(lhs)
92                                         expv = 1;
93                                 else
94                                         expv = 0;
95                         }
96                         break;
97
98                 case '&':
99                         term(a|1);
100                         expv &= lhs;
101                         break;
102
103                 case '|':
104                         term(a|1);
105                         expv |= lhs;
106                         break;
107
108                 case ')':
109                         if ((a&2)==0)
110                                 error("unexpected `)'");
111
112                 default:
113                         reread();
114                         return(rc);
115                 }
116         }
117         return(rc);
118 }
119
120 term(int a)
121 {       /* item | monadic item | (expr) | */
122         ADDR e;
123
124         switch ((int)readchar()) {
125
126         case '*':
127                 term(a|1);
128                 if (geta(cormap, expv, &e) < 0)
129                         error("%r");
130                 expv = e;
131                 return(1);
132
133         case '@':
134                 term(a|1);
135                 if (geta(symmap, expv, &e) < 0)
136                         error("%r");
137                 expv = e;
138                 return(1);
139
140         case '-':
141                 term(a|1);
142                 expv = -expv;
143                 return(1);
144
145         case '~':
146                 term(a|1);
147                 expv = ~expv;
148                 return(1);
149
150         case '(':
151                 expr(2);
152                 if (readchar()!=')')
153                         error("syntax error: `)' expected");
154                 return(1);
155
156         default:
157                 reread();
158                 return(item(a));
159         }
160 }
161
162 item(int a)
163 {       /* name [ . local ] | number | . | ^  | <register | 'x | | */
164         char    *base;
165         char    savc;
166         uvlong e;
167         Symbol s;
168         char gsym[MAXSYM], lsym[MAXSYM];
169
170         readchar();
171         if (isfileref()) {
172                 readfname(gsym);
173                 rdc();                  /* skip white space */
174                 if (lastc == ':') {     /* it better be */
175                         rdc();          /* skip white space */
176                         if (!getnum(readchar))
177                                 error("bad number");
178                         if (expv == 0)
179                                 expv = 1;       /* file begins at line 1 */
180                         expv = file2pc(gsym, expv);
181                         if (expv == -1)
182                                 error("%r");
183                         return 1;
184                 }
185                 error("bad file location");
186         } else if (symchar(0)) {        
187                 readsym(gsym);
188                 if (lastc=='.') {
189                         readchar();     /* ugh */
190                         if (lastc == '.') {
191                                 lsym[0] = '.';
192                                 readchar();
193                                 readsym(lsym+1);
194                         } else if (symchar(0)) {
195                                 readsym(lsym);
196                         } else
197                                 lsym[0] = 0;
198                         if (localaddr(cormap, gsym, lsym, &e, rget) < 0)
199                                 error("%r");
200                         expv = e;
201                 }
202                 else {
203                         if (lookup(0, gsym, &s) == 0)
204                                 error("symbol not found");
205                         expv = s.value;
206                 }
207                 reread();
208         } else if (getnum(readchar)) {
209                 ;
210         } else if (lastc=='.') {        
211                 readchar();
212                 if (!symchar(0) && lastc != '.') {
213                         expv = dot;
214                 } else {
215                         if (findsym(rget(cormap, mach->pc), CTEXT, &s) == 0)
216                                 error("no current function");
217                         if (lastc == '.') {
218                                 lsym[0] = '.';
219                                 readchar();
220                                 readsym(lsym+1);
221                         } else
222                                 readsym(lsym);
223                         if (localaddr(cormap, s.name, lsym, &e, rget) < 0)
224                                 error("%r");
225                         expv = e;
226                 }       
227                 reread();
228         } else if (lastc=='"') {
229                 expv=ditto;
230         } else if (lastc=='+') {
231                 expv=inkdot(dotinc);
232         } else if (lastc=='^') {
233                 expv=inkdot(-dotinc);
234         } else if (lastc=='<') {
235                 savc=rdc();
236                 base = regname(savc);
237                 expv = rget(cormap, base);
238         }
239         else if (lastc=='\'')
240                 expv = ascval();
241         else if (a)
242                 error("address expected");
243         else {  
244                 reread();
245                 return(0);
246         }
247         return(1);
248 }
249
250 #define MAXBASE 16
251
252 /* service routines for expression reading */
253 getnum(int (*rdf)(void))
254 {
255         char *cp;
256         int base, d;
257         BOOL fpnum;
258         char num[MAXLIN];
259
260         base = 0;
261         fpnum = FALSE;
262         if (lastc == '#') {
263                 base = 16;
264                 (*rdf)();
265         }
266         if (convdig(lastc) >= MAXBASE)
267                 return (0);
268         if (lastc == '0')
269                 switch ((*rdf)()) {
270                 case 'x':
271                 case 'X':
272                         base = 16;
273                         (*rdf)();
274                         break;
275
276                 case 't':
277                 case 'T':
278                         base = 10;
279                         (*rdf)();
280                         break;
281
282                 case 'o':
283                 case 'O':
284                         base = 8;
285                         (*rdf)();
286                         break;
287                 default:
288                         if (base == 0)
289                                 base = 8;
290                         break;
291                 }
292         if (base == 0)
293                 base = 10;
294         expv = 0;
295         for (cp = num, *cp = lastc; ;(*rdf)()) {
296                 if ((d = convdig(lastc)) < base) {
297                         expv *= base;
298                         expv += d;
299                         *cp++ = lastc;
300                 }
301                 else if (lastc == '.') {
302                         fpnum = TRUE;
303                         *cp++ = lastc;
304                 } else {
305                         reread();
306                         break;
307                 }
308         }
309         if (fpnum)
310                 expv = fpin(num);
311         return (1);
312 }
313
314 void
315 readsym(char *isymbol)
316 {
317         char    *p;
318         Rune r;
319
320         p = isymbol;
321         do {
322                 if (p < &isymbol[MAXSYM-UTFmax-1]){
323                         r = lastc;
324                         p += runetochar(p, &r);
325                 }
326                 readchar();
327         } while (symchar(1));
328         *p = 0;
329 }
330
331 void
332 readfname(char *filename)
333 {
334         char    *p;
335         Rune    c;
336
337         /* snarf chars until un-escaped char in terminal char set */
338         p = filename;
339         do {
340                 if ((c = lastc) != '\\' && p < &filename[MAXSYM-UTFmax-1])
341                         p += runetochar(p, &c);
342                 readchar();
343         } while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
344         *p = 0;
345         reread();
346 }
347
348 convdig(int c)
349 {
350         if (isdigit(c))
351                 return(c-'0');
352         else if (!isxdigit(c))
353                 return(MAXBASE);
354         else if (isupper(c))
355                 return(c-'A'+10);
356         else
357                 return(c-'a'+10);
358 }
359
360 symchar(int dig)
361 {
362         if (lastc=='\\') {
363                 readchar();
364                 return(TRUE);
365         }
366         return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc));
367 }
368
369 static long
370 round(long a, long b)
371 {
372         long w;
373
374         w = (a/b)*b;
375         if (a!=w)
376                 w += b;
377         return(w);
378 }