expr.c 5.3 KB

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