do_comm.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. /* $Header$ */
  2. /* Implementation of the do_ routines */
  3. #include <stdio.h>
  4. #include <assert.h>
  5. #include <alloc.h>
  6. #include "operator.h"
  7. #include "position.h"
  8. #include "tree.h"
  9. #include "idf.h"
  10. #include "Lpars.h"
  11. #include "type.h"
  12. #include "expr.h"
  13. #include "symbol.h"
  14. #include "scope.h"
  15. #include "file.h"
  16. #include "message.h"
  17. extern FILE *db_out;
  18. extern t_lineno listline, currline;
  19. extern int stop_reason;
  20. extern int interrupted;
  21. p_tree print_command;
  22. /* ------------------------------------------------------------- */
  23. /* implementation of the help command */
  24. do_help(p)
  25. p_tree p;
  26. {
  27. p = p->t_args[0];
  28. if (p && p->t_idf) switch(p->t_idf->id_reserved) {
  29. case HELP:
  30. fputs("help [ <commandname> ]\n", db_out);
  31. fputs("? [ <commandname> ]\n", db_out);
  32. fputs(" Print a command summary, or some more help on <commandname>.\n", db_out);
  33. return;
  34. case LIST:
  35. fputs("list [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
  36. fputs("l [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
  37. fputs(" List lines from the current source file, starting with either\n", db_out);
  38. fputs(" line <start> or some lines before the first statement of <func> or\n", db_out);
  39. fputs(" the current line. Either list <cnt> lines or <wsize> lines,\n", db_out);
  40. fputs(" except when a range is given.\n", db_out);
  41. fputs(" <wsize> is the last <cnt> given, or 10.\n", db_out);
  42. return;
  43. case XFILE:
  44. fputs("file [ <name> ]\n", db_out);
  45. fputs(" Print the name of the current source file, or change the\n", db_out);
  46. fputs(" current source file to <name>.\n", db_out);
  47. return;
  48. case RUN:
  49. fputs("run [ <args> ] [ < <infile> ] [ > <outfile> ]\n", db_out);
  50. fputs(" Start executing debuggee with command line arguments <args> and\n", db_out);
  51. fputs(" possible redirection of standard input and/or standard output.\n", db_out);
  52. return;
  53. case RERUN:
  54. fputs("rerun\n", db_out);
  55. fputs(" repeats the last run command.\n", db_out);
  56. return;
  57. case STOP:
  58. fputs("stop [ <pos> ] [ if <cond> ]\n", db_out);
  59. fputs(" Stop execution when position <pos> is reached, and then when\n", db_out);
  60. fputs(" <cond> becomes true. If no <pos> is given, stop when <cond>\n", db_out);
  61. fputs(" becomes true. If no <cond> is given, stop when <pos> is reached.\n", db_out);
  62. fputs(" Either a position or a condition (or both) must be given.\n", db_out);
  63. return;
  64. case WHEN:
  65. fputs("when [ <pos> ] [ if <cond> ] { <command> [ ; <command> ] ... } \n", db_out);
  66. fputs(" Execute the <command>s when position <pos> is reached, and then when\n", db_out);
  67. fputs(" <cond> becomes true. If no <pos> is given, do this when <cond>\n", db_out);
  68. fputs(" becomes true. If no <cond> is given, do this when <pos> is reached.\n", db_out);
  69. fputs(" Either a position or a condition (or both) must be given.\n", db_out);
  70. return;
  71. case CONT:
  72. fputs("cont [ <cnt> ] [ at <line> ]\n", db_out);
  73. fputs("c [ <cnt> ] [ at <line> ]\n", db_out);
  74. fputs(" Continue execution, skipping <cnt> or 1 breakpoints;a\n", db_out);
  75. fputs(" if <line> is given, continue at <line>.\n", db_out);
  76. return;
  77. case STEP:
  78. case NEXT:
  79. fputs("step [ <cnt> ]\n", db_out);
  80. fputs("s [ <cnt> ]\n", db_out);
  81. fputs("next [ <cnt> ]\n", db_out);
  82. fputs("n [ <cnt> ]\n", db_out);
  83. fputs(" Execute the next <cnt> or 1 source line(s).\n", db_out);
  84. fputs(" Step (s) steps into function-calls.\n", db_out);
  85. fputs(" Next (n) steps past function-calls.\n", db_out);
  86. return;
  87. case WHERE:
  88. fputs("where [ <cnt> ]\n", db_out);
  89. fputs("w [ <cnt> ]\n", db_out);
  90. fputs(" List all, or the top <cnt> or the bottom -<cnt> active functions.\n", db_out);
  91. return;
  92. case STATUS:
  93. fputs("status\n", db_out);
  94. fputs(" display active traces, stops, whens, displays, and dumps.\n", db_out);
  95. return;
  96. case DELETE:
  97. fputs("delete [ <num> [ , <num> ] ... ]\n", db_out);
  98. fputs("d [ <num> [ , <num> ] ...] \n", db_out);
  99. fputs(" Remove the command(s) corresponding to <num> (as displayed by 'status').\n", db_out);
  100. fputs(" If no <num> is given, remove the current stopping point.\n", db_out);
  101. return;
  102. case SET:
  103. fputs("set <desig> to <exp>\n", db_out);
  104. fputs(" Assign the value of <exp> to <desig>.\n", db_out);
  105. return;
  106. case PRINT:
  107. fputs("print <exp> [ , <exp> ] ...\n", db_out);
  108. fputs("p <exp> [ , <exp> ] ...\n", db_out);
  109. fputs(" Print the value of each <exp>.\n", db_out);
  110. return;
  111. case DISPLAY:
  112. fputs("display <exp> [ , <exp> ] ...\n", db_out);
  113. fputs(" Print the value of each <exp> whenever the debuggee stops.\n", db_out);
  114. return;
  115. case DUMP:
  116. fputs("dump\n", db_out);
  117. fputs(" Saves the state of the debuggee; it can be restored with the restore command.\n", db_out);
  118. return;
  119. case RESTORE:
  120. fputs("restore [ <num> ]\n", db_out);
  121. fputs("r [ <num> ]\n", db_out);
  122. fputs(" Restore the state of the dump associated with <num>,\n", db_out);
  123. fputs(" or restore the state of the last dump.\n", db_out);
  124. return;
  125. case TRACE:
  126. fputs("trace [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
  127. fputs("t [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
  128. fputs(" Without args, display each source line before execution.\n", db_out);
  129. fputs(" In addition, display <exp> in the on-clause.\n", db_out);
  130. fputs(" If <pos> is given and indicates a function, only display\n", db_out);
  131. fputs(" tracing information while executing this function.\n", db_out);
  132. fputs(" If it indicates a line number, only display tracing information\n", db_out);
  133. fputs(" whenever the source line is reached.\n", db_out);
  134. fputs(" If <cond> is given, only display tracing info when it evaluates to non-zero.\n", db_out);
  135. return;
  136. case FIND:
  137. fputs("find <name>\n", db_out);
  138. fputs(" Prints the fully qualified name of all symbols matching <name>.\n", db_out);
  139. return;
  140. case WHICH:
  141. fputs("which <name>\n", db_out);
  142. fputs(" Prints the fully qualified name of <name>.\n", db_out);
  143. return;
  144. case DISABLE:
  145. fputs("disable [ <num> [ , <num> ] ... ]\n", db_out);
  146. fputs(" Disable the command(s) corresponding to <num> (as displayed by 'status').\n", db_out);
  147. fputs(" If no <num> is given, disable the current stopping point.\n", db_out);
  148. return;
  149. case ENABLE:
  150. fputs("enable [ <num> [ , <num> ] ... ]\n", db_out);
  151. fputs(" Enable the command(s) corresponding to <num> (as displayed by 'status'.)\n", db_out);
  152. fputs(" If no <num> is given, enable the current stopping point (not effective).\n", db_out);
  153. return;
  154. }
  155. fputs("cont [ <cnt> ] [ at <line> ]\n", db_out);
  156. fputs("delete [ <num> [ , <num> ] ... ]\n", db_out);
  157. fputs("disable [ <num> [ , <num> ] ... ]\n", db_out);
  158. fputs("display <exp> [ , <exp> ] ...\n", db_out);
  159. fputs("dump\n", db_out);
  160. fputs("enable [ <num> [ , <num> ] ... ]\n", db_out);
  161. fputs("file [ <name> ]\n", db_out);
  162. fputs("find <name>\n", db_out);
  163. fputs("help [ <commandname> ]\n", db_out);
  164. fputs("list [ <start> | <func> ] [ , <cnt> | - [ <end> ] ]\n", db_out);
  165. fputs("next [ <cnt> ]\n", db_out);
  166. fputs("print <exp> [ , <exp> ] ...\n", db_out);
  167. fputs("rerun\n", db_out);
  168. fputs("restore <num>\n", db_out);
  169. fputs("run [ <args> ] [ < <infile> ] [ > <outfile> ]\n", db_out);
  170. fputs("set <desig> to <exp>\n", db_out);
  171. fputs("status\n", db_out);
  172. fputs("step [ <cnt> ]\n", db_out);
  173. fputs("stop [ <pos> ] [ if <cond> ]\n", db_out);
  174. fputs("trace [ on <exp> ] [ <pos> ] [ if <cond> ]\n", db_out);
  175. fputs("when [ <pos> ] [ if <cond> ] { <command> [ ; <command> ] ... } \n", db_out);
  176. fputs("where [ <cnt> ]\n", db_out);
  177. fputs("which <name>\n", db_out);
  178. }
  179. /* ------------------------------------------------------------- */
  180. /* implementation of dump/restore commands */
  181. extern p_tree get_from_item_list();
  182. extern t_addr get_dump();
  183. struct dump {
  184. char *globals, *stack;
  185. struct message_hdr mglobal, mstack;
  186. struct dump *next;
  187. };
  188. static struct dump *last_dump;
  189. do_dump(p)
  190. p_tree p;
  191. {
  192. struct dump *d = (struct dump *) malloc(sizeof(struct dump));
  193. if (! d) {
  194. error("could not allocate enough memory");
  195. return;
  196. }
  197. p->t_address = get_dump(&d->mglobal, &d->globals, &d->mstack, &d->stack);
  198. if (! p->t_address) {
  199. free((char *) d);
  200. return;
  201. }
  202. p->t_args[0] = (struct tree *) d;
  203. add_to_item_list(p);
  204. d->next = last_dump;
  205. last_dump = d;
  206. }
  207. do_restore(p)
  208. p_tree p;
  209. {
  210. struct dump *d;
  211. if (p->t_args[0]) {
  212. p = get_from_item_list((int) p->t_args[0]->t_ival);
  213. if (!p || p->t_oper != OP_DUMP) {
  214. error("no such dump");
  215. return;
  216. }
  217. d = (struct dump *) p->t_args[0];
  218. }
  219. else d = last_dump;
  220. if (! d) {
  221. error("no dumps");
  222. return;
  223. }
  224. if (! put_dump(&d->mglobal, d->globals, &d->mstack, d->stack)) {
  225. }
  226. perform_items();
  227. }
  228. free_dump(p)
  229. p_tree p;
  230. {
  231. struct dump *d = (struct dump *) p->t_args[0];
  232. free(d->globals);
  233. free(d->stack);
  234. if (d == last_dump) last_dump = d->next;
  235. else {
  236. register struct dump *d1 = last_dump;
  237. while (d1->next != d) d1 = d1->next;
  238. d1->next = d->next;
  239. }
  240. free((char *) d);
  241. }
  242. /* ------------------------------------------------------------- */
  243. /* implementation of the find command */
  244. do_find(p)
  245. p_tree p;
  246. {
  247. /* Print all identifications of p->t_args[0]. */
  248. register p_symbol s;
  249. p_tree arg;
  250. p = p->t_args[0];
  251. switch(p->t_oper) {
  252. case OP_NAME:
  253. s = p->t_idf->id_def;
  254. while (s) {
  255. pr_sym(s);
  256. s = s->sy_next;
  257. }
  258. break;
  259. case OP_SELECT:
  260. arg = p->t_args[1];
  261. assert(arg->t_oper == OP_NAME);
  262. s = arg->t_idf->id_def;
  263. while (s) {
  264. if (consistent(p, s->sy_scope)) {
  265. pr_sym(s);
  266. }
  267. s = s->sy_next;
  268. }
  269. break;
  270. default:
  271. assert(0);
  272. }
  273. }
  274. /* ------------------------------------------------------------- */
  275. /* implementation of the which command */
  276. do_which(p)
  277. p_tree p;
  278. {
  279. p_symbol sym = identify(p->t_args[0], 0xffff);
  280. if ( sym) pr_sym(sym);
  281. }
  282. /* ------------------------------------------------------------- */
  283. /* implementation of the list command */
  284. extern t_addr get_addr_from_node();
  285. do_list(p)
  286. p_tree p;
  287. {
  288. int l1, l2;
  289. static int wsize = 10;
  290. if (p->t_args[1]) {
  291. l2 = p->t_args[1]->t_ival;
  292. if (l2 >= 0) {
  293. if (l2 == 0) l2 = 1;
  294. wsize = l2;
  295. }
  296. }
  297. else l2 = wsize;
  298. if (! p->t_args[0]) {
  299. l1 = listline;
  300. if (! l1) {
  301. listline = currline - (wsize/2);
  302. l1 = listline;
  303. }
  304. }
  305. else {
  306. if (p->t_args[0]->t_oper == OP_AT) {
  307. l1 = p->t_args[0]->t_lino;
  308. if (p->t_args[0]->t_filename) {
  309. newfile(str2idf(p->t_args[0]->t_filename, 0));
  310. }
  311. }
  312. else {
  313. t_addr a = get_addr_from_node(p->t_args[0]);
  314. p_position pos;
  315. p_symbol oldlistfile = listfile;
  316. if (a == ILL_ADDR) {
  317. return;
  318. }
  319. pos = get_position_from_addr(a);
  320. newfile(str2idf(pos->filename, 1));
  321. if (listfile != oldlistfile) {
  322. warning("switching to file %s", listfile->sy_idf->id_text);
  323. }
  324. l1 = pos->lineno - (l2 > 0 ? l2 : wsize)/2;
  325. if (l1 < 1) l1 = 1;
  326. }
  327. }
  328. if (listfile) {
  329. if (l2 < 0) {
  330. l2 = -l2;
  331. if (l1 > l2) l2 = 1;
  332. else l2 -= l1 - 1;
  333. }
  334. lines(listfile->sy_file, l1, l2);
  335. listline = l1 + l2;
  336. }
  337. else error("no current file");
  338. }
  339. /* ------------------------------------------------------------- */
  340. /* implementation of the file command */
  341. do_file(p)
  342. p_tree p;
  343. {
  344. FILE *f;
  345. if (p->t_args[0]) {
  346. if (! strcmp(p->t_args[0]->t_str, "?")) {
  347. register p_symbol sym = PervasiveScope->sc_symbs;
  348. while (sym) {
  349. if (sym->sy_class == FILESYM) {
  350. fprintf(db_out, "%s\n", sym->sy_idf->id_text);
  351. }
  352. sym = sym->sy_prev_sc;
  353. }
  354. return;
  355. }
  356. if ((f = fopen(p->t_args[0]->t_str, "r")) == NULL) {
  357. error("could not open %s", p->t_args[0]->t_str);
  358. return;
  359. }
  360. fclose(f);
  361. newfile(p->t_args[0]->t_idf);
  362. }
  363. else if (listfile) fprintf(db_out, "%s\n", listfile->sy_idf->id_text);
  364. else error("no current file");
  365. }
  366. /* ------------------------------------------------------------- */
  367. /* implementation of stop/when command */
  368. setstop(p, kind)
  369. p_tree p;
  370. int kind;
  371. {
  372. t_addr a = get_addr_from_node(p->t_args[0]);
  373. if (a == ILL_ADDR) return 0;
  374. p->t_address = a;
  375. if (a != NO_ADDR) {
  376. if (! set_or_clear_breakpoint(a, kind)) {
  377. return 0;
  378. }
  379. }
  380. return 1;
  381. }
  382. do_stop(p)
  383. p_tree p;
  384. {
  385. if (! setstop(p, M_SETBP)) {
  386. return;
  387. }
  388. add_to_item_list(p);
  389. }
  390. /* ------------------------------------------------------------- */
  391. /* implementation of the trace command */
  392. settrace(p, kind)
  393. p_tree p;
  394. int kind;
  395. {
  396. t_addr a, e;
  397. a = get_addr_from_node(p->t_args[0]);
  398. if (a == NO_ADDR) return 1;
  399. if (a == ILL_ADDR) return 0;
  400. if (p->t_args[0]->t_oper == OP_AT) {
  401. e = a;
  402. p->t_address = a;
  403. }
  404. else {
  405. p_scope sc = get_next_scope_from_addr(a+1);
  406. if (sc) e = sc->sc_start - 1;
  407. else e = 0xffffffff;
  408. }
  409. return set_or_clear_trace(a, e, kind);
  410. }
  411. do_trace(p)
  412. p_tree p;
  413. {
  414. p->t_address = NO_ADDR;
  415. if (! settrace(p, M_SETTRACE)) {
  416. return;
  417. }
  418. add_to_item_list(p);
  419. }
  420. /* ------------------------------------------------------------- */
  421. /* implementation of the enable/disable commands */
  422. static
  423. able(p, kind)
  424. p_tree p;
  425. int kind;
  426. {
  427. if (!p) {
  428. if (stop_reason) {
  429. able_item(stop_reason, kind);
  430. }
  431. else {
  432. error("no current stopping point");
  433. }
  434. return;
  435. }
  436. switch(p->t_oper) {
  437. case OP_LINK:
  438. able(p->t_args[0], kind);
  439. able(p->t_args[1], kind);
  440. break;
  441. case OP_INTEGER:
  442. able_item((int)p->t_ival, kind);
  443. break;
  444. default:
  445. assert(0);
  446. }
  447. }
  448. do_enable(p)
  449. p_tree p;
  450. {
  451. able(p->t_args[0], 0);
  452. }
  453. do_disable(p)
  454. p_tree p;
  455. {
  456. able(p->t_args[0], 1);
  457. }
  458. /* ------------------------------------------------------------- */
  459. /* implementation of the cont command */
  460. do_continue(p)
  461. p_tree p;
  462. {
  463. int count;
  464. if (p) {
  465. count = p->t_args[0]->t_ival;
  466. if (p->t_args[1]) {
  467. t_addr a = get_addr_from_position(&(p->t_args[1]->t_pos));
  468. p_scope sc = get_scope_from_addr(a);
  469. if (a == ILL_ADDR || base_scope(sc) != base_scope(CurrentScope)) {
  470. error("cannot continue at line %d",
  471. p->t_args[1]->t_lino);
  472. return;
  473. }
  474. if (! set_pc(a)) {
  475. return;
  476. }
  477. }
  478. }
  479. else count = 1;
  480. while (count--) {
  481. if (! send_cont(count==0)) {
  482. break;
  483. }
  484. }
  485. if (count > 0) {
  486. fprintf(db_out, "Only %d breakpoints skipped\n",
  487. p->t_args[0]->t_ival - count);
  488. }
  489. }
  490. /* ------------------------------------------------------------- */
  491. /* implementation of the step command */
  492. do_step(p)
  493. p_tree p;
  494. {
  495. p = p->t_args[0];
  496. if (! singlestep(M_SETSS, p ? p->t_ival : 1L)) {
  497. }
  498. }
  499. /* ------------------------------------------------------------- */
  500. /* implementation of the next command */
  501. do_next(p)
  502. p_tree p;
  503. {
  504. p = p->t_args[0];
  505. if (! singlestep(M_SETSSF, p? p->t_ival : 1L)) {
  506. }
  507. }
  508. extern t_addr *get_EM_regs();
  509. /* ------------------------------------------------------------- */
  510. /* implementation of the regs command (temporarily) */
  511. do_regs(p)
  512. p_tree p;
  513. {
  514. t_addr *buf;
  515. int n = 0;
  516. p = p->t_args[0];
  517. if (p) n = p->t_ival;
  518. if (! (buf = get_EM_regs(n))) {
  519. return;
  520. }
  521. fprintf(db_out, "EM registers %d levels back:\n", n);
  522. fprintf(db_out, "\tLocalBase =\t0x%lx\n\tArgumentBase =\t0x%lx\n",
  523. (long) buf[0], (long) buf[1]);
  524. fprintf(db_out, "\tProgramCounter=\t0x%lx\n\tHeapPointer = \t0x%lx\n",
  525. (long) buf[2],
  526. (long) buf[3]);
  527. fprintf(db_out, "\tStackPointer =\t0x%lx\n", (long) buf[4]);
  528. }
  529. /* ------------------------------------------------------------- */
  530. /* implementation of the where command */
  531. /*ARGSUSED*/
  532. do_where(p)
  533. p_tree p;
  534. {
  535. int i = 0;
  536. unsigned int cnt;
  537. unsigned int maxcnt = 0xffff;
  538. p_scope sc;
  539. t_addr *buf;
  540. t_addr PC;
  541. p = p->t_args[0];
  542. if (p && p->t_ival < 0) {
  543. for (;;) {
  544. buf = get_EM_regs(i++);
  545. if (! buf || ! buf[1]) break;
  546. PC = buf[2];
  547. sc = base_scope(get_scope_from_addr(PC));
  548. if (! sc || sc->sc_start > PC) break;
  549. if (interrupted) return;
  550. }
  551. i--;
  552. maxcnt = - p->t_ival;
  553. i -= maxcnt;
  554. if (i < 0) i = 0;
  555. }
  556. else if (p) maxcnt = p->t_ival;
  557. for (cnt = maxcnt; cnt != 0; cnt--) {
  558. t_addr AB;
  559. if (interrupted) return;
  560. if (! (buf = get_EM_regs(i++))) break;
  561. AB = buf[1];
  562. PC = buf[2];
  563. if (! AB) break;
  564. sc = base_scope(get_scope_from_addr(PC));
  565. if (! sc || sc->sc_start > PC) break;
  566. fprintf(db_out, "%s(", sc->sc_definedby->sy_idf->id_text);
  567. print_params(sc->sc_definedby->sy_type, AB, has_static_link(sc));
  568. fputs(") ", db_out);
  569. print_position(PC, 0);
  570. fputs("\n", db_out);
  571. }
  572. }
  573. /* ------------------------------------------------------------- */
  574. /* implementation of the delete command */
  575. extern p_tree remove_from_item_list();
  576. do_delete(p)
  577. p_tree p;
  578. {
  579. switch(p->t_oper) {
  580. case OP_DELETE:
  581. if (! p->t_args[0]) {
  582. if (stop_reason) {
  583. remove_from_item_list(stop_reason);
  584. stop_reason = 0;
  585. }
  586. else {
  587. error("no current stopping point");
  588. }
  589. }
  590. else do_delete(p->t_args[0]);
  591. break;
  592. case OP_LINK:
  593. do_delete(p->t_args[0]);
  594. do_delete(p->t_args[1]);
  595. break;
  596. case OP_INTEGER:
  597. p = remove_from_item_list((int) p->t_ival);
  598. if (p) switch(p->t_oper) {
  599. case OP_WHEN:
  600. case OP_STOP:
  601. setstop(p, M_CLRBP);
  602. break;
  603. case OP_TRACE:
  604. settrace(p, M_CLRTRACE);
  605. break;
  606. case OP_DUMP:
  607. free_dump(p);
  608. }
  609. freenode(p);
  610. break;
  611. default:
  612. assert(0);
  613. }
  614. }
  615. /* ------------------------------------------------------------- */
  616. /* implementation of the print command */
  617. do_print(p)
  618. p_tree p;
  619. {
  620. char *buf = 0;
  621. char *format = 0;
  622. long size;
  623. p_type tp;
  624. switch(p->t_oper) {
  625. case OP_PRINT:
  626. if (p->t_args[0] == 0) {
  627. p = print_command;
  628. if (p == 0) {
  629. error("no previous print command");
  630. break;
  631. }
  632. }
  633. else if (p != print_command) {
  634. /* freenode(print_command); No, could be in when-list */
  635. print_command = p;
  636. }
  637. /* fall through */
  638. case OP_DISPLAY:
  639. do_print(p->t_args[0]);
  640. break;
  641. case OP_LINK:
  642. do_print(p->t_args[0]);
  643. do_print(p->t_args[1]);
  644. break;
  645. default:
  646. if (interrupted || ! eval_expr(p, &buf, &size, &tp)) return;
  647. print_node(p, 0);
  648. fputs(" = ", db_out);
  649. if (p->t_oper == OP_FORMAT) {
  650. format = p->t_args[1]->t_str;
  651. }
  652. print_val(tp, size, buf, 0, 0, format);
  653. if (buf) free(buf);
  654. fputs("\n", db_out);
  655. break;
  656. }
  657. }
  658. /* ------------------------------------------------------------- */
  659. /* implementation of the set command */
  660. do_set(p)
  661. p_tree p;
  662. {
  663. char *buf = 0;
  664. long size, size2;
  665. p_type tp, tp2;
  666. t_addr a;
  667. if (interrupted || ! eval_desig(p->t_args[0], &a, &size, &tp) ||
  668. ! eval_expr(p->t_args[1], &buf, &size2, &tp2) ||
  669. ! convert(&buf, &size2, &tp2, tp, size)) {
  670. if (buf) free(buf);
  671. return;
  672. }
  673. if (interrupted) {
  674. free(buf);
  675. return;
  676. }
  677. set_bytes(size, buf, a);
  678. free(buf);
  679. }