expr.c 5.7 KB

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