Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

File:
1 edited

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/prototool/src/mrdb.c

    r321 r439  
    66#include <stdlib.h>
    77#include <string.h>
    8 
    9 #include "mruby.h"
    10 #include "mruby/dump.h"
    11 #include "mruby/debug.h"
    12 #include "mruby/class.h"
    13 #include "mruby/opcode.h"
    14 #include "mruby/variable.h"
     8#include <ctype.h>
     9
     10#include <mruby.h>
     11#include <mruby/dump.h>
     12#include <mruby/debug.h>
     13#include <mruby/class.h>
     14#include <mruby/opcode.h>
     15#include <mruby/variable.h>
    1516
    1617#include "mrdb.h"
    1718#include "apibreak.h"
     19#include "apilist.h"
    1820
    1921void mrdb_state_free(mrb_state *);
     
    2224static mrdb_state *_mrdb_state = NULL;
    2325
    24 struct _args
    25 {
    26         FILE *rfp;
    27         char* fname;
    28         char* srcpath;
    29         int argc;
    30         char** argv;
    31         mrb_bool mrbfile : 1;
     26struct _args {
     27  FILE *rfp;
     28  char* fname;
     29  char* srcpath;
     30  int argc;
     31  char** argv;
     32  mrb_bool mrbfile : 1;
    3233};
    3334
    34 typedef struct debug_command
    35 {
    36         const char *cmd1;
    37         const char *cmd2;
    38         uint8_t len1;
    39         uint8_t len2;
    40         uint8_t div;
    41         debug_command_id id;
    42         debug_command_func func;
     35typedef struct debug_command {
     36  const char *cmd1;
     37  const char *cmd2;
     38  uint8_t len1;
     39  uint8_t len2;
     40  uint8_t div;
     41  debug_command_id id;
     42  debug_command_func func;
    4343} debug_command;
    4444
     
    5252  {"help",      NULL,           1, 0, 1, DBGCMD_HELP,           dbgcmd_help},            /* h[elp] */
    5353  {"info",      "breakpoints",  1, 1, 1, DBGCMD_INFO_BREAK,     dbgcmd_info_break},      /* i[nfo] b[reakpoints] */
     54  {"info",      "locals",       1, 1, 0, DBGCMD_INFO_LOCAL,     dbgcmd_info_local},      /* i[nfo] l[ocals] */
     55  {"list",      NULL,           1, 0, 1, DBGCMD_LIST,           dbgcmd_list},            /* l[ist] */
    5456  {"print",     NULL,           1, 0, 0, DBGCMD_PRINT,          dbgcmd_print},           /* p[rint] */
    5557  {"quit",      NULL,           1, 0, 0, DBGCMD_QUIT,           dbgcmd_quit},            /* q[uit] */
     
    6466usage(const char *name)
    6567{
    66         static const char *const usage_msg[] = {
    67                 "switches:",
    68                 "-b           load and execute RiteBinary (mrb) file",
    69                 "-d           specify source directory",
    70                 "--version    print the version",
    71                 "--copyright  print the copyright",
    72                 NULL
    73         };
    74         const char *const *p = usage_msg;
    75 
    76         printf("Usage: %s [switches] programfile\n", name);
    77         while (*p) {
    78                 printf("  %s\n", *p++);
    79         }
     68  static const char *const usage_msg[] = {
     69  "switches:",
     70  "-b           load and execute RiteBinary (mrb) file",
     71  "-d           specify source directory",
     72  "--version    print the version",
     73  "--copyright  print the copyright",
     74  NULL
     75  };
     76  const char *const *p = usage_msg;
     77
     78  printf("Usage: %s [switches] programfile\n", name);
     79  while (*p) {
     80    printf("  %s\n", *p++);
     81  }
    8082}
    8183
     
    8385parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
    8486{
    85         char **origargv = argv;
    86         static const struct _args args_zero = { 0 };
    87 
    88         *args = args_zero;
    89 
    90         for (argc--, argv++; argc > 0; argc--, argv++) {
    91                 char *item;
    92                 if (argv[0][0] != '-') break;
    93 
    94                 item = argv[0] + 1;
    95                 switch (*item++) {
    96                 case 'b':
    97                         args->mrbfile = TRUE;
    98                         break;
    99                 case 'd':
    100                         if (item[0]) {
    101                                 goto append_srcpath;
    102                         }
    103                         else if (argc > 1) {
    104                                 argc--; argv++;
    105                                 item = argv[0];
    106                         append_srcpath:
    107                                 if (!args->srcpath) {
    108                                         size_t buflen;
    109                                         char *buf;
    110 
    111                                         buflen = strlen(item) + 1;
    112                                         buf = (char *)mrb_malloc(mrb, buflen);
    113                                         memcpy(buf, item, buflen);
    114                                         args->srcpath = buf;
    115                                 }
    116                                 else {
    117                                         size_t srcpathlen;
    118                                         size_t itemlen;
    119 
    120                                         srcpathlen = strlen(args->srcpath);
    121                                         itemlen = strlen(item);
    122                                         args->srcpath =
    123                                                 (char *)mrb_realloc(mrb, args->srcpath, srcpathlen + itemlen + 2);
    124                                         args->srcpath[srcpathlen] = '\n';
    125                                         memcpy(args->srcpath + srcpathlen + 1, item, itemlen + 1);
    126                                 }
    127                         }
    128                         else {
    129                                 printf("%s: No path specified for -d\n", *origargv);
    130                                 return EXIT_SUCCESS;
    131                         }
    132                         break;
    133                 case '-':
    134                         if (strcmp((*argv) + 2, "version") == 0) {
    135                                 mrb_show_version(mrb);
    136                                 exit(EXIT_SUCCESS);
    137                         }
    138                         else if (strcmp((*argv) + 2, "copyright") == 0) {
    139                                 mrb_show_copyright(mrb);
    140                                 exit(EXIT_SUCCESS);
    141                         }
    142                 default:
    143                         return EXIT_FAILURE;
    144                 }
    145         }
    146 
    147         if (args->rfp == NULL) {
    148                 if (*argv == NULL) {
    149                         printf("%s: Program file not specified.\n", *origargv);
    150                         return EXIT_FAILURE;
    151                 }
    152                 else {
    153                         args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
    154                         if (args->rfp == NULL) {
    155                                 printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
    156                                 return EXIT_FAILURE;
    157                         }
    158                         args->fname = argv[0];
    159                         argc--; argv++;
    160                 }
    161         }
    162         args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
    163         memcpy(args->argv, argv, (argc + 1) * sizeof(char*));
    164         args->argc = argc;
    165 
    166         return EXIT_SUCCESS;
     87  char **origargv = argv;
     88  static const struct _args args_zero = { 0 };
     89
     90  *args = args_zero;
     91
     92  for (argc--,argv++; argc > 0; argc--,argv++) {
     93    char *item;
     94    if (argv[0][0] != '-') break;
     95
     96    item = argv[0] + 1;
     97    switch (*item++) {
     98    case 'b':
     99      args->mrbfile = TRUE;
     100      break;
     101    case 'd':
     102      if (item[0]) {
     103        goto append_srcpath;
     104      }
     105      else if (argc > 1) {
     106        argc--; argv++;
     107        item = argv[0];
     108append_srcpath:
     109        if (!args->srcpath) {
     110          size_t buflen;
     111          char *buf;
     112
     113          buflen = strlen(item) + 1;
     114          buf = (char *)mrb_malloc(mrb, buflen);
     115          memcpy(buf, item, buflen);
     116          args->srcpath = buf;
     117        }
     118        else {
     119          size_t srcpathlen;
     120          size_t itemlen;
     121
     122          srcpathlen = strlen(args->srcpath);
     123          itemlen = strlen(item);
     124          args->srcpath =
     125            (char *)mrb_realloc(mrb, args->srcpath, srcpathlen + itemlen + 2);
     126          args->srcpath[srcpathlen] = '\n';
     127          memcpy(args->srcpath + srcpathlen + 1, item, itemlen + 1);
     128        }
     129      }
     130      else {
     131        printf("%s: No path specified for -d\n", *origargv);
     132        return EXIT_SUCCESS;
     133      }
     134      break;
     135    case '-':
     136      if (strcmp((*argv) + 2, "version") == 0) {
     137        mrb_show_version(mrb);
     138        exit(EXIT_SUCCESS);
     139      }
     140      else if (strcmp((*argv) + 2, "copyright") == 0) {
     141        mrb_show_copyright(mrb);
     142        exit(EXIT_SUCCESS);
     143      }
     144    default:
     145      return EXIT_FAILURE;
     146    }
     147  }
     148
     149  if (args->rfp == NULL) {
     150    if (*argv == NULL) {
     151      printf("%s: Program file not specified.\n", *origargv);
     152      return EXIT_FAILURE;
     153    }
     154    else {
     155      args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
     156      if (args->rfp == NULL) {
     157        printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
     158        return EXIT_FAILURE;
     159      }
     160      args->fname = argv[0];
     161      argc--; argv++;
     162    }
     163  }
     164  args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
     165  memcpy(args->argv, argv, (argc+1) * sizeof(char*));
     166  args->argc = argc;
     167
     168  return EXIT_SUCCESS;
    167169}
    168170
     
    170172cleanup(mrb_state *mrb, struct _args *args)
    171173{
    172         if (args->rfp)
    173                 fclose(args->rfp);
    174         if (args->srcpath)
    175                 mrb_free(mrb, args->srcpath);
    176         if (args->argv)
    177                 mrb_free(mrb, args->argv);
    178         mrdb_state_free(mrb);
    179         mrb_close(mrb);
     174  if (args->rfp)
     175    fclose(args->rfp);
     176  if (args->srcpath)
     177    mrb_free(mrb, args->srcpath);
     178  if (args->argv)
     179    mrb_free(mrb, args->argv);
     180  mrdb_state_free(mrb);
     181  mrb_close(mrb);
    180182}
    181183
     
    183185mrb_debug_context_new(mrb_state *mrb)
    184186{
    185         mrb_debug_context *dbg = (mrb_debug_context *)mrb_malloc(mrb, sizeof(mrb_debug_context));
    186 
    187         memset(dbg, 0, sizeof(mrb_debug_context));
    188 
    189         InterlockedExchange(&dbg->xm, DBG_INIT);
    190         dbg->xphase = DBG_PHASE_BEFORE_RUN;
    191         dbg->next_bpno = 1;
    192 
    193         return dbg;
     187  mrb_debug_context *dbg = (mrb_debug_context*)mrb_malloc(mrb, sizeof(mrb_debug_context));
     188
     189  memset(dbg, 0, sizeof(mrb_debug_context));
     190
     191  dbg->xm = DBG_INIT;
     192  dbg->xphase = DBG_PHASE_BEFORE_RUN;
     193  dbg->next_bpno = 1;
     194
     195  return dbg;
    194196}
    195197
     
    197199mrb_debug_context_get(mrb_state *mrb)
    198200{
    199         if (!_debug_context) {
    200                 _debug_context = mrb_debug_context_new(mrb);
    201         }
    202         return _debug_context;
     201  if (!_debug_context) {
     202    _debug_context = mrb_debug_context_new(mrb);
     203  }
     204  return _debug_context;
    203205}
    204206
     
    206208mrb_debug_context_set(mrb_debug_context *dbg)
    207209{
    208         _debug_context = dbg;
     210  _debug_context = dbg;
    209211}
    210212
     
    212214mrb_debug_context_free(mrb_state *mrb)
    213215{
    214         if (_debug_context) {
    215                 mrb_debug_delete_break_all(mrb, _debug_context);
    216                 mrb_free(mrb, _debug_context);
    217                 _debug_context = NULL;
    218         }
     216  if (_debug_context) {
     217    mrb_debug_delete_break_all(mrb, _debug_context);
     218    mrb_free(mrb, _debug_context);
     219    _debug_context = NULL;
     220  }
    219221}
    220222
     
    222224mrdb_state_new(mrb_state *mrb)
    223225{
    224         mrdb_state *mrdb = (mrdb_state *)mrb_malloc(mrb, sizeof(mrdb_state));
    225 
    226         memset(mrdb, 0, sizeof(mrdb_state));
    227 
    228         mrdb->dbg = mrb_debug_context_get(mrb);
    229         mrdb->command = (char *)mrb_malloc(mrb, MAX_COMMAND_LINE + 1);
    230         mrdb->print_no = 1;
    231 
    232         return mrdb;
     226  mrdb_state *mrdb = (mrdb_state*)mrb_malloc(mrb, sizeof(mrdb_state));
     227
     228  memset(mrdb, 0, sizeof(mrdb_state));
     229
     230  mrdb->dbg = mrb_debug_context_get(mrb);
     231  mrdb->command = (char*)mrb_malloc(mrb, MAX_COMMAND_LINE+1);
     232  mrdb->print_no = 1;
     233
     234  return mrdb;
    233235}
    234236
     
    236238mrdb_state_get(mrb_state *mrb)
    237239{
    238         if (!_mrdb_state) {
    239                 _mrdb_state = mrdb_state_new(mrb);
    240         }
    241         return _mrdb_state;
     240  if (!_mrdb_state) {
     241    _mrdb_state = mrdb_state_new(mrb);
     242  }
     243  return _mrdb_state;
    242244}
    243245
     
    245247mrdb_state_set(mrdb_state *mrdb)
    246248{
    247         _mrdb_state = mrdb;
     249  _mrdb_state = mrdb;
    248250}
    249251
     
    251253mrdb_state_free(mrb_state *mrb)
    252254{
    253         mrb_debug_context_free(mrb);
    254         if (_mrdb_state) {
    255                 mrb_free(mrb, _mrdb_state->command);
    256                 mrb_free(mrb, _mrdb_state);
    257                 _mrdb_state = NULL;
    258         }
     255  mrb_debug_context_free(mrb);
     256  if (_mrdb_state) {
     257    mrb_free(mrb, _mrdb_state->command);
     258    mrb_free(mrb, _mrdb_state);
     259    _mrdb_state = NULL;
     260  }
    259261}
    260262
     
    262264get_command(mrb_state *mrb, mrdb_state *mrdb)
    263265{
    264         int i;
    265         int c;
    266 
    267         for (i = 0; i < MAX_COMMAND_LINE; i++) {
    268                 if ((c = getchar()) == EOF || c == '\n') break;
    269                 mrdb->command[i] = c;
    270         }
    271 
    272         if (i == 0 && feof(stdin)) {
    273                 clearerr(stdin);
    274                 strlcpy(mrdb->command, "quit", MAX_COMMAND_LINE + 1);
    275                 i += sizeof("quit") - 1;
    276         }
    277 
    278         if (i == MAX_COMMAND_LINE) {
    279                 for (; (c = getchar()) != EOF && c != '\n'; i++);
    280         }
    281 
    282         if (i > MAX_COMMAND_LINE) {
    283                 printf("command line too long.\n");
    284                 i = 0; /* discard command data */
    285         }
    286         mrdb->command[i] = '\0';
    287 
    288         return mrdb->command;
     266  int i;
     267  int c;
     268
     269  for (i=0; i<MAX_COMMAND_LINE; i++) {
     270    if ((c=getchar()) == EOF || c == '\n') break;
     271    mrdb->command[i] = c;
     272  }
     273
     274  if (i == 0 && feof(stdin)) {
     275    clearerr(stdin);
     276    strcpy(mrdb->command, "quit");
     277    i += sizeof("quit") - 1;
     278  }
     279
     280  if (i == MAX_COMMAND_LINE) {
     281    for ( ; (c=getchar()) != EOF && c !='\n'; i++) ;
     282  }
     283
     284  if (i > MAX_COMMAND_LINE) {
     285    printf("command line too long.\n");
     286    i = 0; /* discard command data */
     287  }
     288  mrdb->command[i] = '\0';
     289
     290  return mrdb->command;
    289291}
    290292
     
    292294pick_out_word(mrb_state *mrb, char **pp)
    293295{
    294         char *ps;
    295 
    296         for (ps = *pp; ISBLANK(*ps); ps++);
    297         if (*ps == '\0') {
    298                 return NULL;
    299         }
    300 
    301         if (*ps == '\"' || *ps == '\'') {
    302                 *pp = strchr(ps + 1, *ps);
    303                 if (*pp) (*pp)++;
    304         }
    305         else {
    306                 *pp = strpbrk(ps, " \t");
    307         }
    308 
    309         if (!*pp) {
    310                 *pp = ps + strlen(ps);
    311         }
    312 
    313         if (**pp != '\0') {
    314                 **pp = '\0';
    315                 (*pp)++;
    316         }
    317 
    318         return ps;
     296  char *ps;
     297
     298  for (ps=*pp; ISBLANK(*ps); ps++) ;
     299  if (*ps == '\0') {
     300    return NULL;
     301  }
     302
     303  if (*ps == '\"' || *ps == '\'') {
     304    *pp = strchr(ps+1, *ps);
     305    if (*pp) (*pp)++;
     306  }
     307  else {
     308    *pp = strpbrk(ps, " \t");
     309  }
     310
     311  if (!*pp) {
     312    *pp = ps + strlen(ps);
     313  }
     314
     315  if (**pp != '\0') {
     316    **pp = '\0';
     317    (*pp)++;
     318  }
     319
     320  return ps;
    319321}
    320322
     
    322324parse_command(mrb_state *mrb, mrdb_state *mrdb, char *buf)
    323325{
    324         debug_command *cmd = NULL;
    325         char *p = buf;
    326         size_t wlen;
    327 
    328         /* get word #1 */
    329         mrdb->words[0] = pick_out_word(mrb, &p);
    330         if (!mrdb->words[0]) {
    331                 return NULL;
    332         }
    333         mrdb->wcnt = 1;
    334         /* set remain parameter */
    335         for (; *p && ISBLANK(*p); p++);
    336         if (*p) {
    337                 mrdb->words[mrdb->wcnt++] = p;
    338         }
    339 
    340         /* check word #1 */
    341         for (cmd = (debug_command*)debug_command_list; cmd->cmd1; cmd++) {
    342                 wlen = strlen(mrdb->words[0]);
    343                 if (wlen >= cmd->len1 &&
    344                         strncmp(mrdb->words[0], cmd->cmd1, wlen) == 0) {
    345                         break;
    346                 }
    347         }
    348 
    349         if (cmd->cmd2) {
    350                 if (mrdb->wcnt > 1) {
    351                         /* get word #2 */
    352                         mrdb->words[1] = pick_out_word(mrb, &p);
    353                         if (mrdb->words[1]) {
    354                                 /* update remain parameter */
    355                                 for (; *p && ISBLANK(*p); p++);
    356                                 if (*p) {
    357                                         mrdb->words[mrdb->wcnt++] = p;
    358                                 }
    359                         }
    360                 }
    361 
    362                 /* check word #1,#2 */
    363                 for (; cmd->cmd1; cmd++) {
    364                         wlen = strlen(mrdb->words[0]);
    365                         if (wlen < cmd->len1 ||
    366                                 strncmp(mrdb->words[0], cmd->cmd1, wlen)) {
    367                                 continue;
    368                         }
    369 
    370                         if (!cmd->cmd2) break;          /* word #1 only */
    371 
    372                         if (mrdb->wcnt == 1) continue;  /* word #2 not specified */
    373 
    374                         wlen = strlen(mrdb->words[1]);
    375                         if (wlen >= cmd->len2 &&
    376                                 strncmp(mrdb->words[1], cmd->cmd2, wlen) == 0) {
    377                                 break;  /* word #1 and #2 */
    378                         }
    379                 }
    380         }
    381 
    382         /* divide remain parameters */
    383         if (cmd->cmd1 && cmd->div) {
    384                 p = mrdb->words[--mrdb->wcnt];
    385                 for (; mrdb->wcnt < MAX_COMMAND_WORD; mrdb->wcnt++) {
    386                         mrdb->words[mrdb->wcnt] = pick_out_word(mrb, &p);
    387                         if (!mrdb->words[mrdb->wcnt]) {
    388                                 break;
    389                         }
    390                 }
    391         }
    392 
    393         return cmd->cmd1 ? cmd : NULL;
     326  debug_command *cmd = NULL;
     327  char *p = buf;
     328  size_t wlen;
     329
     330  /* get word #1 */
     331  mrdb->words[0] = pick_out_word(mrb, &p);
     332  if (!mrdb->words[0]) {
     333    return NULL;
     334  }
     335  mrdb->wcnt = 1;
     336  /* set remain parameter */
     337  for ( ; *p && ISBLANK(*p); p++) ;
     338  if (*p) {
     339    mrdb->words[mrdb->wcnt++] = p;
     340  }
     341
     342  /* check word #1 */
     343  for (cmd=(debug_command*)debug_command_list; cmd->cmd1; cmd++) {
     344    wlen = strlen(mrdb->words[0]);
     345    if (wlen >= cmd->len1 &&
     346        strncmp(mrdb->words[0], cmd->cmd1, wlen) == 0) {
     347      break;
     348    }
     349  }
     350
     351  if (cmd->cmd2) {
     352    if (mrdb->wcnt > 1) {
     353      /* get word #2 */
     354      mrdb->words[1] = pick_out_word(mrb, &p);
     355      if (mrdb->words[1]) {
     356        /* update remain parameter */
     357        for ( ; *p && ISBLANK(*p); p++) ;
     358        if (*p) {
     359          mrdb->words[mrdb->wcnt++] = p;
     360        }
     361      }
     362    }
     363
     364    /* check word #1,#2 */
     365    for ( ; cmd->cmd1; cmd++) {
     366      wlen = strlen(mrdb->words[0]);
     367      if (wlen < cmd->len1 ||
     368          strncmp(mrdb->words[0], cmd->cmd1, wlen)) {
     369        continue;
     370      }
     371
     372      if (!cmd->cmd2) break;          /* word #1 only */
     373
     374      if (mrdb->wcnt == 1) continue;  /* word #2 not specified */
     375
     376      wlen = strlen(mrdb->words[1]);
     377      if (wlen >= cmd->len2 &&
     378          strncmp(mrdb->words[1], cmd->cmd2, wlen) == 0) {
     379        break;  /* word #1 and #2 */
     380      }
     381    }
     382  }
     383
     384  /* divide remain parameters */
     385  if (cmd->cmd1 && cmd->div) {
     386    p = mrdb->words[--mrdb->wcnt];
     387    for ( ; mrdb->wcnt<MAX_COMMAND_WORD; mrdb->wcnt++) {
     388      mrdb->words[mrdb->wcnt] = pick_out_word(mrb, &p);
     389      if (!mrdb->words[mrdb->wcnt]) {
     390        break;
     391      }
     392    }
     393  }
     394
     395  return cmd->cmd1 ? cmd : NULL;
    394396}
    395397
     
    397399print_info_stopped_break(mrb_state *mrb, mrdb_state *mrdb)
    398400{
    399         mrb_debug_breakpoint bp;
    400         int32_t ret;
    401         uint16_t lineno;
    402         const char *file;
    403         const char *method_name;
    404         const char *class_name;
    405 
    406         ret = mrb_debug_get_break(mrb, mrdb->dbg, mrdb->dbg->stopped_bpno, &bp);
    407         if (ret == 0) {
    408                 switch (bp.type) {
    409                 case MRB_DEBUG_BPTYPE_LINE:
    410                         file = bp.point.linepoint.file;
    411                         lineno = bp.point.linepoint.lineno;
    412                         printf("Breakpoint %d, at %s:%d\n", bp.bpno, file, lineno);
    413                         break;
    414                 case MRB_DEBUG_BPTYPE_METHOD:
    415                         method_name = bp.point.methodpoint.method_name;
    416                         class_name = bp.point.methodpoint.class_name;
    417                         if (class_name == NULL) {
    418                                 printf("Breakpoint %d, %s\n", bp.bpno, method_name);
    419                         }
    420                         else {
    421                                 printf("Breakpoint %d, %s:%s\n", bp.bpno, class_name, method_name);
    422                         }
    423                         if (mrdb->dbg->isCfunc) {
    424                                 printf("Stopped before calling the C function.\n");
    425                         }
    426                         break;
    427                 default:
    428                         break;
    429                 }
    430         }
     401  mrb_debug_breakpoint bp;
     402  int32_t ret;
     403  uint16_t lineno;
     404  const char *file;
     405  const char *method_name;
     406  const char *class_name;
     407
     408  ret = mrb_debug_get_break(mrb, mrdb->dbg, mrdb->dbg->stopped_bpno, &bp);
     409  if (ret == 0) {
     410    switch(bp.type) {
     411      case MRB_DEBUG_BPTYPE_LINE:
     412        file = bp.point.linepoint.file;
     413        lineno = bp.point.linepoint.lineno;
     414        printf("Breakpoint %d, at %s:%d\n", bp.bpno, file, lineno);
     415        break;
     416      case MRB_DEBUG_BPTYPE_METHOD:
     417        method_name = bp.point.methodpoint.method_name;
     418        class_name = bp.point.methodpoint.class_name;
     419        if (class_name == NULL) {
     420          printf("Breakpoint %d, %s\n", bp.bpno, method_name);
     421        }
     422        else {
     423          printf("Breakpoint %d, %s:%s\n", bp.bpno, class_name, method_name);
     424        }
     425        if (mrdb->dbg->isCfunc) {
     426          printf("Stopped before calling the C function.\n");
     427        }
     428        break;
     429      default:
     430        break;
     431    }
     432  }
    431433}
    432434
     
    434436print_info_stopped_step_next(mrb_state *mrb, mrdb_state *mrdb)
    435437{
    436         const char* file = mrdb->dbg->prvfile;
    437         uint16_t lineno = mrdb->dbg->prvline;
    438         printf("%s:%d\n", file, lineno);
     438  const char* file = mrdb->dbg->prvfile;
     439  uint16_t lineno = mrdb->dbg->prvline;
     440  printf("%s:%d\n", file, lineno);
     441}
     442
     443static void
     444print_info_stopped_code(mrb_state *mrb, mrdb_state *mrdb)
     445{
     446  char* file = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, mrdb->dbg->prvfile);
     447  uint16_t lineno = mrdb->dbg->prvline;
     448  if (file != NULL) {
     449    mrb_debug_list(mrb, mrdb->dbg, file, lineno, lineno);
     450    mrb_free(mrb, file);
     451  }
    439452}
    440453
     
    442455print_info_stopped(mrb_state *mrb, mrdb_state *mrdb)
    443456{
    444         switch (mrdb->dbg->bm) {
    445         case BRK_BREAK:
    446                 print_info_stopped_break(mrb, mrdb);
    447                 break;
    448         case BRK_STEP:
    449         case BRK_NEXT:
    450                 print_info_stopped_step_next(mrb, mrdb);
    451                 break;
    452         default:
    453                 break;
    454         }
     457  switch(mrdb->dbg->bm) {
     458    case BRK_BREAK:
     459      print_info_stopped_break(mrb, mrdb);
     460      print_info_stopped_code(mrb, mrdb);
     461      break;
     462    case BRK_STEP:
     463    case BRK_NEXT:
     464      print_info_stopped_step_next(mrb, mrdb);
     465      print_info_stopped_code(mrb, mrdb);
     466      break;
     467    default:
     468      break;
     469  }
    455470}
    456471
     
    458473get_and_parse_command(mrb_state *mrb, mrdb_state *mrdb)
    459474{
    460         debug_command *cmd = NULL;
    461         char *p;
    462         int i;
    463 
    464         while (!cmd) {
    465                 for (p = NULL; !p || *p == '\0'; ) {
    466                         printf("(%s:%d) ", mrdb->dbg->prvfile, mrdb->dbg->prvline);
    467                         fflush(stdout);
    468                         p = get_command(mrb, mrdb);
    469                 }
    470 
    471                 cmd = parse_command(mrb, mrdb, p);
     475  debug_command *cmd = NULL;
     476  char *p;
     477  int i;
     478
     479  while (!cmd) {
     480    for (p=NULL; !p || *p=='\0'; ) {
     481      printf("(%s:%d) ", mrdb->dbg->prvfile, mrdb->dbg->prvline);
     482      fflush(stdout);
     483      p = get_command(mrb, mrdb);
     484    }
     485
     486    cmd = parse_command(mrb, mrdb, p);
    472487#ifdef _DBG_MRDB_PARSER_
    473                 for (i = 0; i < mrdb->wcnt; i++) {
    474                         printf("%d: %s\n", i, mrdb->words[i]);
    475                 }
     488    for (i=0; i<mrdb->wcnt; i++) {
     489      printf("%d: %s\n", i, mrdb->words[i]);
     490    }
    476491#endif
    477                 if (!cmd) {
    478                         printf("invalid command (");
    479                         for (i = 0; i < mrdb->wcnt; i++) {
    480                                 if (i > 0) {
    481                                         printf(" ");
    482                                 }
    483                                 printf("%s", mrdb->words[i]);
    484                         }
    485                         puts(")");
    486                 }
    487         }
    488         return cmd;
     492    if (!cmd) {
     493      printf("invalid command (");
     494      for (i=0; i<mrdb->wcnt; i++) {
     495        if (i>0) {
     496          printf(" ");
     497        }
     498        printf("%s", mrdb->words[i]);
     499      }
     500      puts(")");
     501    }
     502  }
     503  return cmd;
    489504}
    490505
    491506static int32_t
    492 check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
    493 {
    494         struct RClass* c = NULL;
    495         mrb_sym sym;
    496         int32_t bpno;
    497         mrb_bool isCfunc;
    498 
    499         mrb_debug_context *dbg = mrb_debug_context_get(mrb);
    500 
    501         isCfunc = FALSE;
    502         bpno = dbg->method_bpno;
    503         dbg->method_bpno = 0;
    504 
    505         switch (GET_OPCODE(*pc)) {
    506         case OP_SEND:
    507         case OP_SENDB:
    508                 c = mrb_class(mrb, regs[GETARG_A(*pc)]);
    509                 sym = irep->syms[GETARG_B(*pc)];
    510                 break;
    511         case OP_SUPER:
    512                 c = mrb->c->ci->target_class->super;
    513                 sym = mrb->c->ci->mid;
    514                 break;
    515         default:
    516                 sym = 0;
    517                 break;
    518         }
    519         if (sym != 0) {
    520                 dbg->method_bpno = mrb_debug_check_breakpoint_method(mrb, dbg, c, sym, &isCfunc);
    521                 if (isCfunc) {
    522                         bpno = dbg->method_bpno;
    523                         dbg->method_bpno = 0;
    524                 }
    525         }
    526         dbg->isCfunc = isCfunc;
    527         return bpno;
     507check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
     508{
     509  struct RClass* c;
     510  mrb_sym sym;
     511  int32_t bpno;
     512  mrb_bool isCfunc;
     513  struct mrb_insn_data insn;
     514
     515  mrb_debug_context *dbg = mrb_debug_context_get(mrb);
     516
     517  isCfunc = FALSE;
     518  bpno = dbg->method_bpno;
     519  dbg->method_bpno = 0;
     520
     521  insn = mrb_decode_insn(pc);
     522  switch(insn.insn) {
     523    case OP_SEND:
     524    case OP_SENDB:
     525      c = mrb_class(mrb, regs[insn.a]);
     526      sym = irep->syms[insn.b];
     527      break;
     528    case OP_SUPER:
     529      c = mrb->c->ci->target_class->super;
     530      sym = mrb->c->ci->mid;
     531      break;
     532    default:
     533      sym = 0;
     534      break;
     535  }
     536  if (sym != 0) {
     537    dbg->method_bpno = mrb_debug_check_breakpoint_method(mrb, dbg, c, sym, &isCfunc);
     538    if (isCfunc) {
     539      bpno = dbg->method_bpno;
     540      dbg->method_bpno = 0;
     541    }
     542  }
     543  dbg->isCfunc = isCfunc;
     544  return bpno;
    528545}
    529546
    530547static void
    531 mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
    532 {
    533         const char *file;
    534         int32_t line;
    535         int32_t bpno;
    536 
    537         mrb_debug_context *dbg = mrb_debug_context_get(mrb);
    538 
    539         mrb_assert(dbg);
    540 
    541         dbg->irep = irep;
    542         dbg->pc = pc;
    543         dbg->regs = regs;
    544 
    545         if (dbg->xphase == DBG_PHASE_RESTART) {
    546                 dbg->root_irep = irep;
    547                 dbg->prvfile = NULL;
    548                 dbg->prvline = 0;
    549                 dbg->prvci = NULL;
    550                 InterlockedExchange(&dbg->xm, DBG_RUN);
    551                 dbg->xphase = DBG_PHASE_RUNNING;
    552         }
    553 
    554         file = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq));
    555         line = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq));
    556 
    557         switch (dbg->xm) {
    558         case DBG_STEP:
    559                 if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
    560                         return;
    561                 }
    562                 dbg->method_bpno = 0;
    563                 dbg->bm = BRK_STEP;
    564                 break;
    565 
    566         case DBG_NEXT:
    567                 if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
    568                         return;
    569                 }
    570                 if ((intptr_t)(dbg->prvci) < (intptr_t)(mrb->c->ci)) {
    571                         return;
    572                 }
    573                 dbg->prvci = NULL;
    574                 dbg->method_bpno = 0;
    575                 dbg->bm = BRK_NEXT;
    576                 break;
    577 
    578         case DBG_RUN:
    579                 bpno = check_method_breakpoint(mrb, irep, pc, regs);
    580                 if (bpno > 0) {
    581                         dbg->stopped_bpno = bpno;
    582                         dbg->bm = BRK_BREAK;
    583                         break;
    584                 }
    585                 if (dbg->prvfile != file || dbg->prvline != line) {
    586                         bpno = mrb_debug_check_breakpoint_line(mrb, dbg, file, line);
    587                         if (bpno > 0) {
    588                                 dbg->stopped_bpno = bpno;
    589                                 dbg->bm = BRK_BREAK;
    590                                 break;
    591                         }
    592                 }
    593                 dbg->prvfile = file;
    594                 dbg->prvline = line;
    595                 return;
    596         case DBG_INIT:
    597                 dbg->root_irep = irep;
    598                 dbg->bm = BRK_INIT;
    599                 if (!file || line < 0) {
    600                         puts("Cannot get debugging information.");
    601                 }
    602                 break;
    603 
    604         default:
    605                 return;
    606         }
    607 
    608         dbg->prvfile = file;
    609         dbg->prvline = line;
    610 
    611         if (dbg->bm == BRK_BREAK && --dbg->ccnt > 0) {
    612                 return;
    613         }
    614         dbg->break_hook(mrb, dbg);
    615 
    616         dbg->xphase = DBG_PHASE_RUNNING;
     548mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
     549{
     550  const char *file;
     551  int32_t line;
     552  int32_t bpno;
     553
     554  mrb_debug_context *dbg = mrb_debug_context_get(mrb);
     555
     556  mrb_assert(dbg);
     557
     558  dbg->irep = irep;
     559  dbg->pc  = pc;
     560  dbg->regs = regs;
     561
     562  if (dbg->xphase == DBG_PHASE_RESTART) {
     563    dbg->root_irep = irep;
     564    dbg->prvfile = NULL;
     565    dbg->prvline = 0;
     566    dbg->prvci = NULL;
     567    dbg->xm = DBG_RUN;
     568    dbg->xphase = DBG_PHASE_RUNNING;
     569  }
     570
     571  file = mrb_debug_get_filename(mrb, irep, pc - irep->iseq);
     572  line = mrb_debug_get_line(mrb, irep, pc - irep->iseq);
     573
     574  switch (dbg->xm) {
     575  case DBG_STEP:
     576    if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
     577      return;
     578    }
     579    dbg->method_bpno = 0;
     580    dbg->bm = BRK_STEP;
     581    break;
     582
     583  case DBG_NEXT:
     584    if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
     585      return;
     586    }
     587    if ((intptr_t)(dbg->prvci) < (intptr_t)(mrb->c->ci)) {
     588      return;
     589    }
     590    dbg->prvci = NULL;
     591    dbg->method_bpno = 0;
     592    dbg->bm = BRK_NEXT;
     593    break;
     594
     595  case DBG_RUN:
     596    bpno = check_method_breakpoint(mrb, irep, pc, regs);
     597    if (bpno > 0) {
     598      dbg->stopped_bpno = bpno;
     599      dbg->bm = BRK_BREAK;
     600      break;
     601    }
     602    if (dbg->prvfile != file || dbg->prvline != line) {
     603      bpno = mrb_debug_check_breakpoint_line(mrb, dbg, file, line);
     604      if (bpno > 0) {
     605        dbg->stopped_bpno = bpno;
     606        dbg->bm = BRK_BREAK;
     607        break;
     608      }
     609    }
     610    dbg->prvfile = file;
     611    dbg->prvline = line;
     612    return;
     613  case DBG_INIT:
     614    dbg->root_irep = irep;
     615    dbg->bm = BRK_INIT;
     616    if (!file || line < 0) {
     617      puts("Cannot get debugging information.");
     618    }
     619    break;
     620
     621  default:
     622    return;
     623  }
     624
     625  dbg->prvfile = file;
     626  dbg->prvline = line;
     627
     628  if (dbg->bm == BRK_BREAK && --dbg->ccnt > 0) {
     629    return;
     630  }
     631  dbg->break_hook(mrb, dbg);
     632
     633  dbg->xphase = DBG_PHASE_RUNNING;
    617634}
    618635
     
    620637mrb_debug_break_hook(mrb_state *mrb, mrb_debug_context *dbg)
    621638{
    622         debug_command *cmd;
    623         dbgcmd_state st = DBGST_CONTINUE;
    624         mrdb_state *mrdb = mrdb_state_get(mrb);
    625 
    626         print_info_stopped(mrb, mrdb);
    627 
    628         while (1) {
    629                 cmd = get_and_parse_command(mrb, mrdb);
    630                 mrb_assert(cmd);
    631 
    632                 st = cmd->func(mrb, mrdb);
    633 
    634                 if ((st == DBGST_CONTINUE) || (st == DBGST_RESTART)) break;
    635         }
    636         return dbg->xm;
     639  debug_command *cmd;
     640  dbgcmd_state st = DBGST_CONTINUE;
     641  mrdb_state *mrdb = mrdb_state_get(mrb);
     642
     643  print_info_stopped(mrb, mrdb);
     644
     645  while (1) {
     646    cmd = get_and_parse_command(mrb, mrdb);
     647    mrb_assert(cmd);
     648
     649    st = cmd->func(mrb, mrdb);
     650
     651    if ((st == DBGST_CONTINUE) || (st == DBGST_RESTART)) break;
     652  }
     653  return dbg->xm;
    637654}
    638655
     
    643660        if (mrdb == NULL)
    644661                return 0;
    645         return InterlockedCompareExchange(&mrdb->dbg->xm, DBG_STEP, DBG_RUN) == DBG_RUN;
     662        long prev = mrdb->dbg->xm;
     663        if (mrdb->dbg->xm == DBG_RUN)
     664                mrdb->dbg->xm = DBG_STEP;
     665        return prev == DBG_RUN;
    646666}
    647667
     
    649669mrdb_main(int argc, char **argv)
    650670{
    651         mrb_state *mrb = mrb_open();
    652         int n = -1;
    653         struct _args args;
    654         mrb_value v;
    655         mrdb_state *mrdb;
    656         mrdb_state *mrdb_backup;
    657         mrb_debug_context* dbg_backup;
    658         debug_command *cmd;
    659 
    660 l_restart:
    661 
    662         if (mrb == NULL) {
    663                 fputs("Invalid mrb_state, exiting mruby\n", stderr);
    664                 return EXIT_FAILURE;
    665         }
    666 
    667         /* parse command parameters */
    668         n = parse_args(mrb, argc, argv, &args);
    669         if (n == EXIT_FAILURE || args.rfp == NULL) {
    670                 cleanup(mrb, &args);
    671                 usage(argv[0]);
    672                 return n;
    673         }
    674 
    675         /* initialize debugger information */
    676         mrdb = mrdb_state_get(mrb);
    677         mrb_assert(mrdb && mrdb->dbg);
    678         mrdb->srcpath = args.srcpath;
    679 
    680         if (mrdb->dbg->xm == DBG_QUIT) {
    681                 mrdb->dbg->xphase = DBG_PHASE_RESTART;
    682         }
    683         else {
    684                 mrdb->dbg->xphase = DBG_PHASE_BEFORE_RUN;
    685         }
    686         InterlockedExchange(&mrdb->dbg->xm, DBG_INIT);
    687         mrdb->dbg->ccnt = 1;
    688 
    689         /* setup hook functions */
    690         mrb->code_fetch_hook = mrb_code_fetch_hook;
    691         mrdb->dbg->break_hook = mrb_debug_break_hook;
    692 
    693         if (args.mrbfile) { /* .mrb */
    694                 v = mrb_load_irep_file(mrb, args.rfp);
    695         }
    696         else {              /* .rb */
    697                 mrbc_context *cc = mrbc_context_new(mrb);
    698                 mrbc_filename(mrb, cc, args.fname);
    699                 v = mrb_load_file_cxt(mrb, args.rfp, cc);
    700                 mrbc_context_free(mrb, cc);
    701         }
    702         if (mrdb->dbg->xm == DBG_QUIT && !mrb_undef_p(v) && mrb->exc) {
    703                 const char *classname = mrb_obj_classname(mrb, mrb_obj_value(mrb->exc));
    704                 if (!strcmp(classname, "DebuggerExit")) {
    705                         cleanup(mrb, &args);
    706                         return 0;
    707                 }
    708                 if (!strcmp(classname, "DebuggerRestart")) {
    709                         mrdb_backup = mrdb_state_get(mrb);
    710                         dbg_backup = mrb_debug_context_get(mrb);
    711 
    712                         mrdb_state_set(NULL);
    713                         mrb_debug_context_set(NULL);
    714 
    715                         cleanup(mrb, &args);
    716                         mrb = mrb_open();
    717 
    718                         mrdb_state_set(mrdb_backup);
    719                         mrb_debug_context_set(dbg_backup);
    720 
    721                         goto l_restart;
    722                 }
    723         }
    724         puts("mruby application exited.");
    725         mrdb->dbg->xphase = DBG_PHASE_AFTER_RUN;
    726         if (!mrb_undef_p(v)) {
    727                 if (mrb->exc) {
    728                         mrb_print_error(mrb);
    729                 }
    730                 else {
    731                         printf(" => ");
    732                         mrb_p(mrb, v);
    733                 }
    734         }
    735 
    736         mrdb->dbg->prvfile = "-";
    737         mrdb->dbg->prvline = 0;
    738 
    739         while (1) {
    740                 cmd = get_and_parse_command(mrb, mrdb);
    741                 mrb_assert(cmd);
    742 
    743                 if (cmd->id == DBGCMD_QUIT) {
    744                         break;
    745                 }
    746 
    747                 if (cmd->func(mrb, mrdb) == DBGST_RESTART) goto l_restart;
    748         }
    749 
    750         cleanup(mrb, &args);
    751 
    752         return 0;
    753 }
     671  mrb_state *mrb = mrb_open();
     672  int n = -1;
     673  struct _args args;
     674  mrb_value v;
     675  mrdb_state *mrdb;
     676  mrdb_state *mrdb_backup;
     677  mrb_debug_context* dbg_backup;
     678  debug_command *cmd;
     679
     680 l_restart:
     681
     682  if (mrb == NULL) {
     683    fputs("Invalid mrb_state, exiting mruby\n", stderr);
     684    return EXIT_FAILURE;
     685  }
     686
     687  /* parse command parameters */
     688  n = parse_args(mrb, argc, argv, &args);
     689  if (n == EXIT_FAILURE || args.rfp == NULL) {
     690    cleanup(mrb, &args);
     691    usage(argv[0]);
     692    return n;
     693  }
     694
     695  /* initialize debugger information */
     696  mrdb = mrdb_state_get(mrb);
     697  mrb_assert(mrdb && mrdb->dbg);
     698  mrdb->srcpath = args.srcpath;
     699
     700  if (mrdb->dbg->xm == DBG_QUIT) {
     701    mrdb->dbg->xphase = DBG_PHASE_RESTART;
     702  }
     703  else {
     704    mrdb->dbg->xphase = DBG_PHASE_BEFORE_RUN;
     705  }
     706  mrdb->dbg->xm = DBG_INIT;
     707  mrdb->dbg->ccnt = 1;
     708
     709  /* setup hook functions */
     710  mrb->code_fetch_hook = mrb_code_fetch_hook;
     711  mrdb->dbg->break_hook = mrb_debug_break_hook;
     712
     713  if (args.mrbfile) { /* .mrb */
     714    v = mrb_load_irep_file(mrb, args.rfp);
     715  }
     716  else {              /* .rb */
     717    mrbc_context *cc = mrbc_context_new(mrb);
     718    mrbc_filename(mrb, cc, args.fname);
     719    v = mrb_load_file_cxt(mrb, args.rfp, cc);
     720    mrbc_context_free(mrb, cc);
     721  }
     722  if (mrdb->dbg->xm == DBG_QUIT && !mrb_undef_p(v) && mrb->exc) {
     723    const char *classname = mrb_obj_classname(mrb, mrb_obj_value(mrb->exc));
     724    if (!strcmp(classname, "DebuggerExit")) {
     725      cleanup(mrb, &args);
     726      return 0;
     727    }
     728    if (!strcmp(classname, "DebuggerRestart")) {
     729      mrdb_backup = mrdb_state_get(mrb);
     730      dbg_backup = mrb_debug_context_get(mrb);
     731
     732      mrdb_state_set(NULL);
     733      mrb_debug_context_set(NULL);
     734
     735      cleanup(mrb, &args);
     736      mrb = mrb_open();
     737
     738      mrdb_state_set(mrdb_backup);
     739      mrb_debug_context_set(dbg_backup);
     740
     741      goto l_restart;
     742    }
     743  }
     744  puts("mruby application exited.");
     745  mrdb->dbg->xphase = DBG_PHASE_AFTER_RUN;
     746  if (!mrb_undef_p(v)) {
     747    if (mrb->exc) {
     748      mrb_print_error(mrb);
     749    }
     750    else {
     751      printf(" => ");
     752      mrb_p(mrb, v);
     753    }
     754  }
     755
     756  mrdb->dbg->prvfile = "-";
     757  mrdb->dbg->prvline = 0;
     758
     759  while (1) {
     760    cmd = get_and_parse_command(mrb, mrdb);
     761    mrb_assert(cmd);
     762
     763    if (cmd->id == DBGCMD_QUIT) {
     764      break;
     765    }
     766
     767    if ( cmd->func(mrb, mrdb) == DBGST_RESTART ) goto l_restart;
     768  }
     769
     770  cleanup(mrb, &args);
     771
     772  return 0;
     773}
Note: See TracChangeset for help on using the changeset viewer.