home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu 2008 / 2008-06-02_hobbes.nmsu.edu.zip / new / scummc-0.2.0-os2.zip / ScummC / src / scvm_dbg.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-12-18  |  18.0 KB  |  663 lines

  1. /* ScummC
  2.  * Copyright (C) 2006  Alban Bedel
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17.  *
  18.  */
  19.  
  20. /**
  21.  * @file scvm_dbg.c
  22.  * @ingroup scvm
  23.  * @brief Debugger interface
  24.  */
  25.  
  26. #include "config.h"
  27.  
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <inttypes.h>
  32. #include <errno.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #include <fcntl.h>
  36. #include <signal.h>
  37. #include <ctype.h>
  38.  
  39. #ifdef HAVE_READLINE
  40. #include <readline/readline.h>
  41. #include <readline/history.h>
  42. #endif
  43.  
  44. #include "scc_fd.h"
  45. #include "scc_util.h"
  46. #include "scc_param.h"
  47. #include "scc_cost.h"
  48. #include "scc_box.h"
  49. #include "scvm_res.h"
  50. #include "scvm_thread.h"
  51. #include "scvm.h"
  52.  
  53. typedef struct scvm_debug_cmd {
  54.   char* name, *full_name;
  55.   int (*action)(scvm_t* vm, char* arg);
  56.   void (*usage)(char* args);
  57.   struct scvm_debug_cmd* next;
  58. } scvm_debug_cmd_t;
  59.  
  60. static int dbg_interrupt = 0;
  61. static scvm_debug_cmd_t debug_cmd[];
  62.  
  63. static void dbg_interrupt_handler(int sig) {
  64.   printf("Kill debug\n");
  65.   dbg_interrupt = 1;
  66. }
  67.  
  68. static int check_interrupt(scvm_t* vm) {
  69.   return dbg_interrupt;
  70. }
  71.  
  72. static scvm_debug_cmd_t* scvm_find_debug_cmd(scvm_t* vm, char* line,
  73.                                              scvm_debug_cmd_t* cmdtable,
  74.                                              char** next_args, int* found) {
  75.   char* cmd, *args, *cmd_end_pos, cmd_end;
  76.   int i,len;
  77.   if(next_args) *next_args = NULL;
  78.   if(found) *found = 0;
  79.   if(!line)
  80.     return NULL;
  81.   for(cmd = line ; isspace(cmd[0]) ; cmd++);
  82.   if(!cmd[0])
  83.     return NULL;
  84.   for(args = cmd+1 ; args[0] && !isspace(args[0]) ; args++);
  85.   cmd_end = args[0];
  86.   cmd_end_pos = args;
  87.   if(args[0]) {
  88.     args[0] = 0;
  89.     for(args++ ; isspace(args[0]) ; args++);
  90.   }
  91.   if(!args[0])
  92.     args = NULL;
  93.   len = strlen(cmd);
  94.   for(i = 0 ; cmdtable[i].name ; i++)
  95.     if(strncmp(cmd,cmdtable[i].name,len) == 0) {
  96.       if(cmdtable[i].next) {
  97.         scvm_debug_cmd_t* next_cmd;
  98.         cmd_end_pos[0] = cmd_end;
  99.         if(!args) {
  100.           if(found && cmdtable[i].action) *found = 1;
  101.           return cmdtable+i;
  102.         }
  103.         next_cmd = scvm_find_debug_cmd(vm,args,cmdtable[i].next,next_args,found);
  104.         if(next_cmd && (!found || *found)) return next_cmd;
  105.         // not found
  106.         if(next_args) *next_args = args;
  107.         return cmdtable+i;
  108.       }
  109.       if(next_args) *next_args = args;
  110.       if(found) *found = 1;
  111.       return cmdtable+i;
  112.     }
  113.   cmd_end_pos[0] = cmd_end;
  114.   return NULL;
  115. }
  116.  
  117. /////////////// breakpoint ///////////////////////////
  118.  
  119. static void cmd_breakpoint_usage(char* args) {
  120.   printf("Usage: breakpoint [room] script [pos]\n");
  121. }
  122.  
  123.  
  124. static int cmd_breakpoint(scvm_t* vm, char* args) {
  125.   int arg[3], num, id;
  126.   int room = 0, script = 0, pos = 0;
  127.   if(!args) {
  128.     cmd_breakpoint_usage(NULL);
  129.     return 0;
  130.   }
  131.   num = sscanf(args,"%d %d %d",arg,arg+1,arg+2);
  132.   if(num == 3)
  133.     room = arg[0], script = arg[1], pos = arg[2];
  134.   else if(num == 2)
  135.     script = arg[0], pos = arg[1];
  136.   else if(num == 1)
  137.     script = arg[0];
  138.   else {
  139.     cmd_breakpoint_usage(NULL);
  140.     return 0;
  141.   }
  142.   id = scvm_add_breakpoint(vm,room,script,pos);
  143.   if(id < 0) {
  144.     printf("Failed to create breakpoint.\n");
  145.     return 0;
  146.   }
  147.   if(room)
  148.     printf("Added breakpoint %d in room %d, script %d at 0x%X\n",
  149.            id,room,script,pos);
  150.   else
  151.     printf("Added breakpoint %d in script %d at 0x%X\n",
  152.            id,script,pos);
  153.   return 1;
  154. }
  155.  
  156. /////////////// help ///////////////////////////
  157.  
  158. static void cmd_help_usage(char* args) {
  159.   printf("Usage: help [ CMD ... ]\n");
  160. }
  161.  
  162. static int cmd_help(scvm_t* vm, char* args) {
  163.   scvm_debug_cmd_t* cmdtable = debug_cmd, *cmd;
  164.   char* next_args;
  165.   int i;
  166.   if(args && (cmd = scvm_find_debug_cmd(vm,args,debug_cmd,&next_args,NULL))) {
  167.     if(cmd->next) {
  168.       // print subcmd list
  169.       printf("Usage: %s SUBCMD ...\n"
  170.              "where SUBCMD is one of:\n",cmd->full_name);
  171.       cmdtable = cmd->next;
  172.     } else if(cmd->usage) {
  173.       cmd->usage(next_args);
  174.       return 1;
  175.     } else {
  176.       printf("Command is missing a help message.\n");
  177.       return 0;
  178.     }
  179.   } else {
  180.     if(args)
  181.       printf("Unknown command: %s\n",args);
  182.     printf("Commands:\n");
  183.   }
  184.  
  185.   for(i = 0 ; cmdtable[i].name ; i++)
  186.     printf("  %-20s -\n",cmdtable[i].name);
  187.   return 1;
  188. }
  189.  
  190. /////////////// quit ///////////////////////////
  191.  
  192. static void cmd_quit_usage(char* args) {
  193.   printf("Usage: quit\n");
  194. }
  195.  
  196. static int cmd_quit(scvm_t* vm, char* args) {
  197.   // kill the vm ?
  198.   return -1;
  199. }
  200.  
  201. ///////////// show actor ///////////////////////
  202.  
  203. static void cmd_show_actor_usage(char* args) {
  204.   printf("Usage: show actor [ actor-addr ]\n");
  205. }
  206.  
  207. static int cmd_show_actor(scvm_t* vm, char* args) {
  208.   int a;
  209.   scvm_actor_t* actor;
  210.   if(args) {
  211.     if(sscanf(args,"%d",&a) != 1) {
  212.       cmd_show_actor_usage(NULL);
  213.       return 0;
  214.     }
  215.     if(a <= 0 || a >= vm->num_actor) {
  216.       printf("Invalid actor address: %d\n",a);
  217.       return 0;
  218.     }
  219.     actor = &vm->actor[a];
  220.   } else if(!vm->current_actor) {
  221.     printf("Current actor is not set.\n");
  222.     return 0;
  223.   } else
  224.     actor = vm->current_actor;
  225.  
  226.   printf("Actor %d:\n",actor->id);
  227.   printf("  Name               : %s\n",actor->name);
  228.   if(actor->costdec.cost)
  229.     printf("  Costume            : %d\n",actor->costdec.cost->id);
  230.   if(actor->costdec.anim)
  231.     printf("  Animation          : %d\n",actor->costdec.anim_id);
  232.   printf("  Room               : %d\n",actor->room);
  233.   printf("  Position           : %dx%d\n",actor->x,actor->y);
  234.   printf("  Size               : %dx%d\n",actor->width,actor->height);
  235.   printf("  Direction          : %d\n",actor->direction);
  236.   printf("  Scaling            : %dx%d\n",actor->scale_x,actor->scale_y);
  237.   printf("  Layer              : %d\n",actor->layer);
  238.   printf("  Elevation          : %d\n",actor->elevation);
  239.   printf("  Follow boxes       : %s\n",
  240.          (actor->flags & SCVM_ACTOR_IGNORE_BOXES) ? "No" : "Yes");
  241.   if(!(actor->flags & SCVM_ACTOR_IGNORE_BOXES))
  242.       printf("  Box                : %d\n",actor->box);
  243.   printf("\n");
  244.   // flags
  245.   printf("  Anim speed         : %d\n",actor->anim_speed);
  246.   printf("  Anim cycle         : %d\n",actor->anim_cycle);
  247.   printf("  Walk speed         : %dx%d\n",actor->walk_speed_x,
  248.          actor->walk_speed_y);
  249.   printf("  Walk script        : %d\n",actor->walk_script);
  250.   printf("  Walk state         : %d\n",actor->walking);
  251.   if(actor->walking) {
  252.       printf("  Walk destination   : %dx%d (box %d)\n",
  253.              actor->walk_to_x,actor->walk_to_y,actor->walk_to_box);
  254.       printf("  Walk waypoint      : %dx%d (box %d)\n",
  255.              actor->dstX,actor->dstY,actor->dst_box);
  256.   }
  257.   printf("\n");
  258.   printf("  Init frame         : %d\n",actor->init_frame);
  259.   printf("  Walk frame         : %d\n",actor->walk_frame);
  260.   printf("  Talk start frame   : %d\n",actor->talk_start_frame);
  261.   printf("  Talk end frame     : %d\n",actor->talk_end_frame);
  262.   printf("  Stand frame        : %d\n",actor->stand_frame);
  263.   printf("\n");
  264.   printf("  Talk color         : %d\n",actor->talk_color);
  265.   printf("  Talk position      : %dx%d\n",actor->talk_x,actor->talk_y);
  266.   printf("  Talk script        : %d\n",actor->talk_script);
  267.   return 1;
  268. }
  269.  
  270. ///////////// show array ///////////////////////
  271.  
  272. static void cmd_show_array_usage(char* args) {
  273.   printf("Usage: show array array-addr\n");
  274. }
  275.  
  276. static int cmd_show_array(scvm_t* vm, char* args) {
  277.   int i, a, val;
  278.   if(!args || sscanf(args,"%d",&a) != 1) {
  279.     cmd_show_array_usage(NULL);
  280.     return 0;
  281.   }
  282.   if(a <= 0 || a >= vm->num_array ||
  283.      vm->array[a].size == 0) {
  284.     printf("Invalid array address: %d\n",a);
  285.     return 0;
  286.   }
  287.  
  288.   printf("Array %d = { ",a);
  289.   for(i = 0 ; i < vm->array[a].size ; i++)
  290.     if(!scvm_read_array(vm,a,i,0,&val))
  291.       printf("%s%d",i > 0 ? ", " : "",val);
  292.   printf(" }\n");
  293.   return 1;
  294. }
  295.  
  296. ///////////// show avar ///////////////////////
  297.  
  298. static void cmd_show_avar_usage(char* args) {
  299.   printf("Usage: show avar var-addr\n");
  300. }
  301.  
  302. static int cmd_show_avar(scvm_t* vm, char* args) {
  303.   int i, var, a, val;
  304.   if(sscanf(args,"local %d",&var) == 1) {
  305.     var &= 0x3FFF;
  306.     var |= 0x4000;
  307.   } else if(sscanf(args,"%d",&var) != 1) {
  308.     cmd_show_avar_usage(NULL);
  309.     return 0;
  310.   }
  311.   if(scvm_thread_read_var(vm,vm->current_thread,var,&a)) {
  312.     printf("Invalid address: %d\n",var);
  313.     return 0;
  314.   }
  315.   if(a <= 0 || a >= vm->num_array ||
  316.      vm->array[a].size == 0) {
  317.     printf("Invalid array address: %d\n",a);
  318.     return 0;
  319.   }
  320.  
  321.   printf("Array %d = { ",a);
  322.   for(i = 0 ; i < vm->array[a].size ; i++)
  323.     if(!scvm_read_array(vm,a,i,0,&val))
  324.       printf("%s%d",i > 0 ? ", " : "",val);
  325.   printf(" }\n");
  326.   return 1;
  327. }
  328.  
  329. ///////////// show costume ////////////////////
  330. static void cmd_show_costume_usage(char* args) {
  331.   printf("Usage: show costume costume-addr\n");
  332. }
  333.  
  334. static int cmd_show_costume(scvm_t* vm, char* args) {
  335.   int id;
  336.   scc_cost_t* cost;
  337.   scc_cost_anim_t* ani;
  338.   if(!args || sscanf(args,"%d",&id) != 1) {
  339.     cmd_show_costume_usage(NULL);
  340.     return 0;
  341.   }
  342.   if(!(cost = scvm_load_res(vm,SCVM_RES_COSTUME,id)))
  343.     return 0;
  344.   printf("Costume %d:\n",cost->id);
  345.   printf("  Format              : 0x%X\n",cost->format);
  346.   printf("  Colors              : %d\n",cost->pal_size);
  347.   printf("  Anims               :");
  348.   for(ani = cost->anims ; ani ; ani = ani->next)
  349.     printf(" %d",ani->id);
  350.   printf("\n");
  351.   return 1;
  352. }
  353.  
  354. ///////////// show costume ////////////////////
  355. static void cmd_show_object_usage(char* args) {
  356.   printf("Usage: show object object-addr\n");
  357. }
  358.  
  359. static int cmd_show_object(scvm_t* vm, char* args) {
  360.   int id,n = 0;
  361.   scvm_object_t* obj;
  362.   if(!args || sscanf(args,"%d",&id) != 1) {
  363.     cmd_show_object_usage(NULL);
  364.     return 0;
  365.   }
  366.   if(!(obj = scvm_load_res(vm,SCVM_RES_OBJECT,id)))
  367.     return 0;
  368.  
  369.   printf("Object %d:\n",obj->id);
  370.   printf("  Name                : %s\n",obj->pdata->name);
  371.   printf("  Class mask          : 0x%X\n",obj->pdata->klass);
  372.   printf("  Owner               : %d\n",obj->pdata->owner);
  373.   printf("  State               : %d\n",obj->pdata->state);
  374.   printf("  Position            : %dx%d\n",obj->x,obj->y);
  375.   printf("  Size                : %dx%d\n",obj->width,obj->height);
  376.   printf("  Images              : %d\n",obj->num_image);
  377.   printf("  Z planes            : %d\n",obj->num_zplane);
  378.   printf("  Hotspots            :");
  379.   for(n = 0 ; n < obj->num_hotspot ; n++)
  380.     printf(" %dx%d",obj->hotspot[n<<1],obj->hotspot[(n<<1)+1]);
  381.   printf("\n");
  382.   if(obj->parent)
  383.     printf("  Parent              : %d\n",obj->parent->id);
  384.   printf("  Direction           : %d\n",obj->actor_dir);
  385.   printf("  Verbs               :");
  386.   for(n = 0 ; n < obj->num_verb_entries ; n++)
  387.     printf(" %d",obj->verb_entries[n<<1]);
  388.   printf("\n");
  389.   return 1;
  390. }
  391.  
  392. ///////////// show room ///////////////////////
  393.  
  394. static void cmd_show_room_usage(char* args) {
  395.   printf("Usage: show room [ room-addr ]\n");
  396. }
  397.  
  398. static int cmd_show_room(scvm_t* vm, char* args) {
  399.   int id;
  400.   scvm_room_t* room;
  401.   if(args) {
  402.     if(sscanf(args,"%d",&id) != 1) {
  403.       cmd_show_avar_usage(NULL);
  404.       return 0;
  405.     }
  406.     if(!(room = scvm_load_res(vm,SCVM_RES_ROOM,id)))
  407.       return 0;
  408.   } else if(!vm->room) {
  409.     printf("No current room.\n");
  410.     return 0;
  411.   } else
  412.     room = vm->room;
  413.  
  414.   printf("Room %d:\n",room->id);
  415.   printf("  Size                : %dx%d\n",room->width,room->height);
  416.   printf("  Z planes            : %d\n",room->num_zplane);
  417.   printf("  Palettes            : %d\n",room->num_palette);
  418.   printf("  Cycles              : %d\n",room->num_cycle);
  419.   printf("  Transparent color   : %d\n",room->trans);
  420.   printf("  Entry script        : %s\n",room->entry ? "yes" : "no");
  421.   printf("  Exit script         : %s\n",room->exit ? "yes" : "no");
  422.   printf("  Scripts             : %d\n",room->num_script);
  423.   printf("  Objects             :");
  424.   for(id = 0 ; id < room->num_object ; id++)
  425.     if(room->object[id])
  426.       printf(" %d",room->object[id]->id);
  427.   printf("\n");
  428.   return 1;
  429. }
  430.  
  431.  
  432. /////////////// show thread ///////////////////////////
  433.  
  434. static void show_thread(scvm_thread_t* t) {
  435.   printf("Thread %d\n",t->id);
  436.   printf("  State               : %s\n",scvm_thread_state_name(t->state));
  437.   if(t->parent)
  438.     printf("  Parent thread       : %d\n",t->parent->id);
  439.   if(!t->state)
  440.     return;
  441.   if(t->next_state)
  442.     printf("  Next VM state       : %s\n",scvm_state_name(t->next_state));
  443.   if(t->flags) {
  444.     char flags[1024];
  445.     scvm_thread_flags_name(t->flags,flags,sizeof(flags));
  446.     printf("  Flags               : %s\n",flags);
  447.   }
  448.   printf("  Cycle               : %d\n",t->cycle);
  449.   if(t->delay)
  450.     printf("  Delay               : %d ms\n",t->delay);
  451.   if(t->script && (t->script->id & 0x0FFF0000) == 0x0ECD0000)
  452.     printf("  Script              : %s\n",
  453.            t->script->id == 0x0ECD0000 ? "entry" : "exit");
  454.   else
  455.     printf("  Script              : %d\n",t->script ? t->script->id : -1);
  456.   printf("  Code pointer        : %d - 0x%X\n",t->code_ptr,t->code_ptr);
  457.   printf("  OP start            : %d - 0x%X\n",t->op_start,t->code_ptr);
  458. }
  459.  
  460. static void cmd_show_thread_usage(char* args) {
  461.   printf("Usage: show thread [ id ... ]\n");
  462. }
  463.  
  464. static int cmd_show_thread(scvm_t* vm, char* args) {
  465.   int t;
  466.   if(!args) {
  467.     for(t = 0 ; t < vm->num_thread ; t++)
  468.       if(vm->thread[t].state > SCVM_THREAD_STOPPED)
  469.         show_thread(&vm->thread[t]);
  470.     return 1;
  471.   }
  472.   while(1) {
  473.     char* end = args;
  474.     while(isspace(args[0])) args++;
  475.     if(!args[0]) break;
  476.     t = strtol(args,&end,0);
  477.     if(end == args)
  478.       return 0;
  479.     show_thread(&vm->thread[t]);
  480.     args = end;
  481.   }
  482.   return 1;
  483. }
  484.  
  485. /////////////// show var ///////////////////////////
  486.  
  487. static void cmd_show_var_usage(char* args) {
  488.   printf("Usage: show var [ local | bit ] var-addr\n");
  489. }
  490.  
  491. static int cmd_show_var(scvm_t* vm, char* args) {
  492.   int var,val;
  493.   if(!args) {
  494.     cmd_show_var_usage(NULL);
  495.     return 0;
  496.   }
  497.   if(sscanf(args,"local %d",&var) == 1) {
  498.     var &= 0x3FFF;
  499.     var |= 0x4000;
  500.   } else if(sscanf(args,"bit %d",&var) == 1) {
  501.     var &= 0x7FFF;
  502.     var |= 0x8000;
  503.   } else if(sscanf(args,"%d",&var) != 1) {
  504.     cmd_show_var_usage(NULL);
  505.     return 0;
  506.   }
  507.   if(scvm_thread_read_var(vm,vm->current_thread,var,&val)) {
  508.     printf("Invalid address: %d\n",var);
  509.     return 0;
  510.   }
  511.   return 1;
  512. }
  513.  
  514. /////////////// show vm ///////////////////////////
  515.  
  516. static void cmd_show_vm_usage(char* args) {
  517.   printf("Usage: show vm\n");
  518. }
  519.  
  520. static int cmd_show_vm(scvm_t* vm, char* args) {
  521.   printf("VM:\n");
  522.   printf("  Data path           : %s\n",vm->path);
  523.   printf("  Basename            : %s\n",vm->basename);
  524.   printf("  File key            : 0x%02x\n",vm->file_key);
  525.   printf("  Data files          : %d\n",vm->num_file);
  526.   printf("\n");
  527.   printf("  Global variables    : %d\n",vm->num_var);
  528.   printf("  Bit variables       : %d\n",vm->num_bitvar);
  529.   printf("  Arrays              : %d\n",vm->num_array);
  530.   printf("  Stack               : %d/%d\n",vm->stack_ptr,vm->stack_size);
  531.   printf("\n");
  532.   printf("  State               : %s\n",scvm_state_name(vm->state));
  533.   printf("  Cycle               : %d\n",vm->cycle);
  534.   if(vm->room)
  535.     printf("  Room                : %d\n",vm->room->id);
  536.   if(vm->current_thread)
  537.     printf("  Thread              : %d\n",vm->current_thread->id);
  538.   if(vm->current_actor)
  539.     printf("  Actor               : %d\n",vm->current_actor->id);
  540.   return 1;
  541. }
  542.  
  543. /////////////// show xxx ///////////////////////////
  544.  
  545. #define SHOW_CMD(name) \
  546.   { #name, "show" #name, cmd_show_##name, cmd_show_##name##_usage }
  547.  
  548. static scvm_debug_cmd_t show_cmd[] = {
  549.   SHOW_CMD(actor),
  550.   SHOW_CMD(array),
  551.   SHOW_CMD(avar),
  552.   SHOW_CMD(costume),
  553.   SHOW_CMD(object),
  554.   SHOW_CMD(room),
  555.   SHOW_CMD(thread),
  556.   SHOW_CMD(var),
  557.   SHOW_CMD(vm),
  558.   { NULL }
  559. };
  560.  
  561.  
  562. /////////////// thread ///////////////////////////
  563.  
  564. static void cmd_thread_usage(char* args) {
  565.   printf("Usage: thread [ id ]\n");
  566. }
  567.  
  568. static int cmd_thread(scvm_t* vm, char* args) {
  569.   if(!args) {
  570.     if(!vm->current_thread) {
  571.       printf("No thread is currently scheduled.\n");
  572.       return 0;
  573.     }
  574.     printf("Current thread is %d.\n",vm->current_thread->id);
  575.     return 1;
  576.   }
  577.   // TODO: switch thread
  578.   return 0;
  579. }
  580.  
  581.  
  582. /////////////// run ///////////////////////////
  583.  
  584. static void cmd_run_usage(char* args) {
  585.   printf("Usage: run [ boot-param ]\n");
  586. }
  587.  
  588. static int cmd_run(scvm_t* vm, char* args) {
  589.   sig_t oldsig;
  590.   // todo: reset the vm
  591.   dbg_interrupt = 0;
  592.   oldsig = signal(SIGINT,dbg_interrupt_handler);
  593.   scvm_run(vm);
  594.   signal(SIGINT,oldsig);
  595.   return 1;
  596. }
  597.  
  598. ////////////////// root commands /////////////////////
  599.  
  600. #define DBG_CMD(name) \
  601.   { #name, #name, cmd_##name, cmd_##name##_usage }
  602. #define DBG_SUBCMD(name) \
  603.   { #name, #name, NULL, NULL, name##_cmd }
  604.  
  605. static scvm_debug_cmd_t debug_cmd[] = {
  606.   DBG_CMD(breakpoint),
  607.   DBG_CMD(help),
  608.   DBG_CMD(quit),
  609.   DBG_CMD(run),
  610.   DBG_SUBCMD(show),
  611.   DBG_CMD(thread),
  612.   { NULL }
  613. };
  614.  
  615. #ifndef HAVE_READLINE
  616. char* readline(const char* prompt) {
  617.     char* line = malloc(512);
  618.     printf("%s",prompt);
  619.     if(!fgets(line,512,stdin)) {
  620.         free(line);
  621.         return NULL;
  622.     }
  623.     return line;
  624. }
  625.  
  626. void add_history(const char* line) {
  627. }
  628. #endif
  629.  
  630. int scvm_debugger(scvm_t* vm) {
  631.   char* line = NULL, *ptr, *args;
  632.   scvm_debug_cmd_t* cmd;
  633.   int r = 1, found;
  634.  
  635.   if(!vm->dbg)
  636.     vm->dbg = calloc(1,sizeof(scvm_debug_t));
  637.  
  638.   vm->dbg->check_interrupt = check_interrupt;
  639.  
  640.   do {
  641.     if(line) free(line);
  642.     if(!(line = readline("(scvm) ")))
  643.       continue;
  644.     for(ptr = line ; isspace(ptr[0]) ; ptr++);
  645.     if(!ptr[0]) continue;
  646.     add_history(ptr);
  647.     cmd = scvm_find_debug_cmd(vm,ptr,debug_cmd,&args,&found);
  648.     if(!found) {
  649.       if(cmd) {
  650.         if(args)
  651.           printf("Unknown command: %s\n",ptr);
  652.         else
  653.           printf("Incomplete command: %s\n",ptr);
  654.       }
  655.       cmd_help(vm,ptr);
  656.       r = 0;
  657.       continue;
  658.     }
  659.     r = cmd->action(vm,args);
  660.   } while(r >= 0);
  661.   return r;
  662. }
  663.