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

mrubyを2.1.1に更新

Location:
EcnlProtoTool/trunk/prototool
Files:
2 added
23 edited

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/prototool/.cproject

    r427 r439  
    8181                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/musl-1.1.18/include}&quot;"/>
    8282                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:}/onigmo-6.1.3/src&quot;"/>
    83                                                                         <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mruby-1.3.0/include}&quot;"/>
     83                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mruby-2.1.1/include}&quot;"/>
    8484                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mbed_api/src}&quot;"/>
    8585                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src}&quot;"/>
     
    8888                                                                </option>
    8989                                                                <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs.165293534" name="Defined symbols (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
    90                                                                         <listOptionValue builtIn="false" value="MRB_GC_STRESS"/>
     90                                                                        <listOptionValue builtIn="false" value="MRB_USE_CUSTOM_RO_DATA_P"/>
    9191                                                                        <listOptionValue builtIn="false" value="MRB_ENABLE_DEBUG_HOOK"/>
     92                                                                        <listOptionValue builtIn="false" value="MRB_CONSTRAINED_BASELINE_PROFILE"/>
    9293                                                                        <listOptionValue builtIn="false" value="_DEFAULT_SOURCE"/>
    9394                                                                </option>
     
    149150                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/onigmo-6.1.3/Debug}&quot;"/>
    150151                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mbed_api/Debug}&quot;"/>
    151                                                                         <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mruby-1.3.0/build/arm-none-eabi/lib}&quot;"/>
     152                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mruby-2.1.1/build/arm-none-eabi/lib}&quot;"/>
    152153                                                                        <listOptionValue builtIn="false" value="&quot;${TCINSTALL}/lib/gcc/arm-none-eabi/${GCC_VERSION}/thumb/v7-ar/fpv3/hard&quot;"/>
    153154                                                                        <listOptionValue builtIn="false" value="&quot;${TCINSTALL}/arm-none-eabi/lib/thumb/v7-ar/fpv3/hard&quot;"/>
     
    165166                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/onigmo-6.1.3/Debug}/libonigmo.a&quot;"/>
    166167                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mbed_api/Debug}/libmbed_api.a&quot;"/>
    167                                                                         <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mruby-1.3.0}/build/arm-none-eabi/lib/libmruby.a&quot;"/>
     168                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/mruby-2.1.1}/build/arm-none-eabi/lib/libmruby.a&quot;"/>
    168169                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/lib}/libmrbcode.a&quot;"/>
    169170                                                                </option>
  • EcnlProtoTool/trunk/prototool/.project

    r424 r439  
    66                <project>curl-7.57.0</project>
    77                <project>mbed_api</project>
    8                 <project>mruby-1.3.0</project>
     8                <project>mruby-2.1.1</project>
    99                <project>ntshell</project>
    1010                <project>onigmo-6.1.3</project>
  • EcnlProtoTool/trunk/prototool/debug_setting.txt

    r438 r439  
     1
     2-f interface/cmsis-dap.cfg -f target/renesas_rza1h_swd.cfg
     3
    14add-symbol-file ../ntshell/Debug/ntshell.elf 0x18004000
  • EcnlProtoTool/trunk/prototool/lib/makefile.mrbc

    r331 r439  
    22CC=arm-none-eabi-gcc
    33AR=arm-none-eabi-ar
    4 MRBC=../../mruby-1.3.0/bin/mrbc
     4MRBC=../../mruby-2.1.1/bin/mrbc
    55
    6 CFLAGS=-mcpu=cortex-a9 -march=armv7-a -mlittle-endian -marm -mthumb-interwork -mfloat-abi=hard -mfpu=vfpv3 -I../../mruby-1.3.0/include
     6CFLAGS=-mcpu=cortex-a9 -march=armv7-a -mlittle-endian -marm -mthumb-interwork -mfloat-abi=hard -mfpu=vfpv3 -I../../mruby-2.1.1/include
    77COBJS=echo_server.o echo_client.o
    88CSRCS=$(foreach file,$(COBJS),$(file:.o=.c))
  • EcnlProtoTool/trunk/prototool/src/apibreak.c

    r321 r439  
    44*/
    55
    6 #include <stdlib.h>
    76#include <string.h>
    8 
    9 #include "mruby.h"
    10 #include "mruby/irep.h"
     7#include <mruby.h>
     8#include <mruby/irep.h>
    119#include "mrdb.h"
    12 #include "mruby/debug.h"
    13 #include "mruby/opcode.h"
    14 #include "mruby/class.h"
    15 #include "mruby/proc.h"
    16 #include "mruby/variable.h"
     10#include <mruby/debug.h>
     11#include <mruby/opcode.h>
     12#include <mruby/class.h>
     13#include <mruby/proc.h>
     14#include <mruby/variable.h>
    1715#include "mrdberror.h"
    1816#include "apibreak.h"
     
    2523check_lineno(mrb_irep_debug_info_file *info_file, uint16_t lineno)
    2624{
    27         uint32_t count = info_file->line_entry_count;
    28         uint16_t l_idx;
    29 
    30         if (info_file->line_type == mrb_debug_line_ary) {
    31                 for (l_idx = 0; l_idx < count; ++l_idx) {
    32                         if (lineno == info_file->lines.ary[l_idx]) {
    33                                 return lineno;
    34                         }
    35                 }
    36         }
    37         else {
    38                 for (l_idx = 0; l_idx < count; ++l_idx) {
    39                         if (lineno == info_file->lines.flat_map[l_idx].line) {
    40                                 return lineno;
    41                         }
    42                 }
    43         }
    44 
    45         return 0;
     25  uint32_t count = info_file->line_entry_count;
     26  uint16_t l_idx;
     27
     28  if (info_file->line_type == mrb_debug_line_ary) {
     29    for (l_idx = 0; l_idx < count; ++l_idx) {
     30      if (lineno == info_file->lines.ary[l_idx]) {
     31        return lineno;
     32      }
     33    }
     34  }
     35  else {
     36    for (l_idx = 0; l_idx < count; ++l_idx) {
     37      if (lineno == info_file->lines.flat_map[l_idx].line) {
     38        return lineno;
     39      }
     40    }
     41  }
     42
     43  return 0;
    4644}
    4745
     
    4947get_break_index(mrb_debug_context *dbg, uint32_t bpno)
    5048{
    51         uint32_t i;
    52         int32_t index;
    53         char hit = FALSE;
    54 
    55         for (i = 0; i < dbg->bpnum; i++) {
    56                 if (dbg->bp[i].bpno == bpno) {
    57                         hit = TRUE;
    58                         index = i;
    59                         break;
    60                 }
    61         }
    62 
    63         if (hit == FALSE) {
    64                 return MRB_DEBUG_BREAK_INVALID_NO;
    65         }
    66 
    67         return index;
     49  uint32_t i;
     50  int32_t index;
     51  char hit = FALSE;
     52
     53  for(i = 0 ; i < dbg->bpnum; i++) {
     54    if (dbg->bp[i].bpno == bpno) {
     55      hit = TRUE;
     56      index = i;
     57      break;
     58    }
     59  }
     60
     61  if (hit == FALSE) {
     62    return MRB_DEBUG_BREAK_INVALID_NO;
     63  }
     64
     65  return index;
    6866}
    6967
     
    7169free_breakpoint(mrb_state *mrb, mrb_debug_breakpoint *bp)
    7270{
    73         switch (bp->type) {
    74         case MRB_DEBUG_BPTYPE_LINE:
    75                 mrb_free(mrb, (void*)bp->point.linepoint.file);
    76                 break;
    77         case MRB_DEBUG_BPTYPE_METHOD:
    78                 mrb_free(mrb, (void*)bp->point.methodpoint.method_name);
    79                 if (bp->point.methodpoint.class_name != NULL) {
    80                         mrb_free(mrb, (void*)bp->point.methodpoint.class_name);
    81                 }
    82                 break;
    83         default:
    84                 break;
    85         }
     71  switch(bp->type) {
     72    case MRB_DEBUG_BPTYPE_LINE:
     73      mrb_free(mrb, (void*)bp->point.linepoint.file);
     74      break;
     75    case MRB_DEBUG_BPTYPE_METHOD:
     76      mrb_free(mrb, (void*)bp->point.methodpoint.method_name);
     77      if (bp->point.methodpoint.class_name != NULL) {
     78        mrb_free(mrb, (void*)bp->point.methodpoint.class_name);
     79      }
     80      break;
     81    default:
     82      break;
     83  }
    8684}
    8785
    8886static uint16_t
    89 check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
    90 {
    91         mrb_irep_debug_info_file *info_file;
    92         uint16_t result = 0;
    93         uint16_t f_idx;
    94         uint16_t fix_lineno;
    95         uint16_t i;
    96 
    97         for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
    98                 info_file = irep->debug_info->files[f_idx];
    99                 if (!strcmp(info_file->filename, file)) {
    100                         result = MRB_DEBUG_BP_FILE_OK;
    101 
    102                         fix_lineno = check_lineno(info_file, lineno);
    103                         if (fix_lineno != 0) {
    104                                 return result | MRB_DEBUG_BP_LINENO_OK;
    105                         }
    106                 }
    107                 for (i = 0; i < irep->rlen; ++i) {
    108                         result |= check_file_lineno(irep->reps[i], file, lineno);
    109                         if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
    110                                 return result;
    111                         }
    112                 }
    113         }
    114         return result;
    115 }
    116 
    117 static const char*
    118 get_class_name(mrb_state *mrb, struct RClass *class_obj)
    119 {
    120         struct RClass *outer;
    121         mrb_sym class_sym;
    122 
    123         outer = mrb_class_outer_module(mrb, class_obj);
    124         class_sym = mrb_class_sym(mrb, class_obj, outer);
    125         return mrb_sym2name(mrb, class_sym);
     87check_file_lineno(mrb_state *mrb, struct mrb_irep *irep, const char *file, uint16_t lineno)
     88{
     89  mrb_irep_debug_info_file *info_file;
     90  uint16_t result = 0;
     91  uint16_t f_idx;
     92  uint16_t fix_lineno;
     93  uint16_t i;
     94
     95  for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
     96    const char *filename;
     97    info_file = irep->debug_info->files[f_idx];
     98    filename = mrb_sym_name_len(mrb, info_file->filename_sym, NULL);
     99    if (!strcmp(filename, file)) {
     100      result = MRB_DEBUG_BP_FILE_OK;
     101
     102      fix_lineno = check_lineno(info_file, lineno);
     103      if (fix_lineno != 0) {
     104        return result | MRB_DEBUG_BP_LINENO_OK;
     105      }
     106    }
     107    for (i=0; i < irep->rlen; ++i) {
     108      result  |= check_file_lineno(mrb, irep->reps[i], file, lineno);
     109      if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
     110        return result;
     111      }
     112    }
     113  }
     114  return result;
    126115}
    127116
     
    129118compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
    130119{
    131         const char* class_name;
    132         const char* method_name;
    133         struct RProc* m;
    134         struct RClass* sc;
    135         const char* sn;
    136         mrb_sym ssym;
    137         mrb_debug_methodpoint *method_p;
    138         mrb_bool is_defined;
    139 
    140         method_name = mrb_sym2name(mrb, method_sym);
    141 
    142         method_p = &bp->point.methodpoint;
    143         if (strcmp(method_p->method_name, method_name) == 0) {
    144                 class_name = get_class_name(mrb, class_obj);
    145                 if (class_name == NULL) {
    146                         if (method_p->class_name == NULL) {
    147                                 return bp->bpno;
    148                         }
    149                 }
    150                 else if (method_p->class_name != NULL) {
    151                         m = mrb_method_search_vm(mrb, &class_obj, method_sym);
    152                         if (m == NULL) {
    153                                 return MRB_DEBUG_OK;
    154                         }
    155                         if (MRB_PROC_CFUNC_P(m)) {
    156                                 *isCfunc = TRUE;
    157                         }
    158 
    159                         is_defined = mrb_class_defined(mrb, method_p->class_name);
    160                         if (is_defined == FALSE) {
    161                                 return MRB_DEBUG_OK;
    162                         }
    163 
    164                         sc = mrb_class_get(mrb, method_p->class_name);
    165                         ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
    166                         m = mrb_method_search_vm(mrb, &sc, ssym);
    167                         if (m == NULL) {
    168                                 return MRB_DEBUG_OK;
    169                         }
    170 
    171                         class_name = get_class_name(mrb, class_obj);
    172                         sn = get_class_name(mrb, sc);
    173                         if (strcmp(sn, class_name) == 0) {
    174                                 return bp->bpno;
    175                         }
    176                 }
    177         }
    178         return MRB_DEBUG_OK;
     120  const char* class_name;
     121  const char* method_name;
     122  mrb_method_t m;
     123  struct RClass* sc;
     124  const char* sn;
     125  mrb_sym ssym;
     126  mrb_debug_methodpoint *method_p;
     127  mrb_bool is_defined;
     128
     129  method_name = mrb_sym_name(mrb, method_sym);
     130
     131  method_p = &bp->point.methodpoint;
     132  if (strcmp(method_p->method_name, method_name) == 0) {
     133    class_name = mrb_class_name(mrb, class_obj);
     134    if (class_name == NULL) {
     135      if (method_p->class_name == NULL) {
     136        return bp->bpno;
     137      }
     138    }
     139    else if (method_p->class_name != NULL) {
     140      m = mrb_method_search_vm(mrb, &class_obj, method_sym);
     141      if (MRB_METHOD_UNDEF_P(m)) {
     142        return MRB_DEBUG_OK;
     143      }
     144      if (MRB_METHOD_CFUNC_P(m)) {
     145        *isCfunc = TRUE;
     146      }
     147
     148      is_defined = mrb_class_defined(mrb, method_p->class_name);
     149      if (is_defined == FALSE) {
     150        return MRB_DEBUG_OK;
     151      }
     152
     153      sc = mrb_class_get(mrb, method_p->class_name);
     154      ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
     155      m = mrb_method_search_vm(mrb, &sc, ssym);
     156      if (MRB_METHOD_UNDEF_P(m)) {
     157        return MRB_DEBUG_OK;
     158      }
     159
     160      class_name = mrb_class_name(mrb, class_obj);
     161      sn = mrb_class_name(mrb, sc);
     162      if (strcmp(sn, class_name) == 0) {
     163        return bp->bpno;
     164      }
     165    }
     166  }
     167  return MRB_DEBUG_OK;
    179168}
    180169
     
    182171mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t lineno)
    183172{
    184         int32_t index;
    185         char* set_file;
    186         uint16_t result;
    187 
    188         if ((mrb == NULL) || (dbg == NULL) || (file == NULL)) {
    189                 return MRB_DEBUG_INVALID_ARGUMENT;
    190         }
    191 
    192         if (dbg->bpnum >= MAX_BREAKPOINT) {
    193                 return MRB_DEBUG_BREAK_NUM_OVER;
    194         }
    195 
    196         if (dbg->next_bpno > MAX_BREAKPOINTNO) {
    197                 return MRB_DEBUG_BREAK_NO_OVER;
    198         }
    199 
    200         /* file and lineno check (line type mrb_debug_line_ary only.) */
    201         result = check_file_lineno(dbg->root_irep, file, lineno);
    202         if (result == 0) {
    203                 return MRB_DEBUG_BREAK_INVALID_FILE;
    204         }
    205         else if (result == MRB_DEBUG_BP_FILE_OK) {
    206                 return MRB_DEBUG_BREAK_INVALID_LINENO;
    207         }
    208 
    209         int len = strlen(file) + 1;
    210         set_file = (char *)mrb_malloc(mrb, len);
    211 
    212         index = dbg->bpnum;
    213         dbg->bp[index].bpno = dbg->next_bpno;
    214         dbg->next_bpno++;
    215         dbg->bp[index].enable = TRUE;
    216         dbg->bp[index].type = MRB_DEBUG_BPTYPE_LINE;
    217         dbg->bp[index].point.linepoint.lineno = lineno;
    218         dbg->bpnum++;
    219 
    220         strlcpy(set_file, file, len);
    221 
    222         dbg->bp[index].point.linepoint.file = set_file;
    223 
    224         return dbg->bp[index].bpno;
     173  int32_t index;
     174  char* set_file;
     175  uint16_t result;
     176
     177  if ((mrb == NULL)||(dbg == NULL)||(file == NULL)) {
     178    return MRB_DEBUG_INVALID_ARGUMENT;
     179  }
     180
     181  if (dbg->bpnum >= MAX_BREAKPOINT) {
     182    return MRB_DEBUG_BREAK_NUM_OVER;
     183  }
     184
     185  if (dbg->next_bpno > MAX_BREAKPOINTNO) {
     186    return MRB_DEBUG_BREAK_NO_OVER;
     187  }
     188
     189  /* file and lineno check (line type mrb_debug_line_ary only.) */
     190  result = check_file_lineno(mrb, dbg->root_irep, file, lineno);
     191  if (result == 0) {
     192    return MRB_DEBUG_BREAK_INVALID_FILE;
     193  }
     194  else if (result == MRB_DEBUG_BP_FILE_OK) {
     195    return MRB_DEBUG_BREAK_INVALID_LINENO;
     196  }
     197
     198  set_file = (char*)mrb_malloc(mrb, strlen(file) + 1);
     199
     200  index = dbg->bpnum;
     201  dbg->bp[index].bpno = dbg->next_bpno;
     202  dbg->next_bpno++;
     203  dbg->bp[index].enable = TRUE;
     204  dbg->bp[index].type = MRB_DEBUG_BPTYPE_LINE;
     205  dbg->bp[index].point.linepoint.lineno = lineno;
     206  dbg->bpnum++;
     207
     208  strncpy(set_file, file, strlen(file) + 1);
     209
     210  dbg->bp[index].point.linepoint.file = set_file;
     211
     212  return dbg->bp[index].bpno;
    225213}
    226214
     
    228216mrb_debug_set_break_method(mrb_state *mrb, mrb_debug_context *dbg, const char *class_name, const char *method_name)
    229217{
    230         int32_t index;
    231         char* set_class;
    232         char* set_method;
    233         int len;
    234 
    235         if ((mrb == NULL) || (dbg == NULL) || (method_name == NULL)) {
    236                 return MRB_DEBUG_INVALID_ARGUMENT;
    237         }
    238 
    239         if (dbg->bpnum >= MAX_BREAKPOINT) {
    240                 return MRB_DEBUG_BREAK_NUM_OVER;
    241         }
    242 
    243         if (dbg->next_bpno > MAX_BREAKPOINTNO) {
    244                 return MRB_DEBUG_BREAK_NO_OVER;
    245         }
    246 
    247         if (class_name != NULL) {
    248                 len = strlen(class_name) + 1;
    249                 set_class = (char *)mrb_malloc(mrb, len);
    250                 strlcpy(set_class, class_name, len);
    251         }
    252         else {
    253                 set_class = NULL;
    254         }
    255 
    256         len = strlen(method_name) + 1;
    257         set_method = (char *)mrb_malloc(mrb, len);
    258 
    259         strlcpy(set_method, method_name, len);
    260 
    261         index = dbg->bpnum;
    262         dbg->bp[index].bpno = dbg->next_bpno;
    263         dbg->next_bpno++;
    264         dbg->bp[index].enable = TRUE;
    265         dbg->bp[index].type = MRB_DEBUG_BPTYPE_METHOD;
    266         dbg->bp[index].point.methodpoint.method_name = set_method;
    267         dbg->bp[index].point.methodpoint.class_name = set_class;
    268         dbg->bpnum++;
    269 
    270         return dbg->bp[index].bpno;
     218  int32_t index;
     219  char* set_class;
     220  char* set_method;
     221
     222  if ((mrb == NULL) || (dbg == NULL) || (method_name == NULL)) {
     223    return MRB_DEBUG_INVALID_ARGUMENT;
     224  }
     225
     226  if (dbg->bpnum >= MAX_BREAKPOINT) {
     227    return MRB_DEBUG_BREAK_NUM_OVER;
     228  }
     229
     230  if (dbg->next_bpno > MAX_BREAKPOINTNO) {
     231    return MRB_DEBUG_BREAK_NO_OVER;
     232  }
     233
     234  if (class_name != NULL) {
     235    set_class = (char*)mrb_malloc(mrb, strlen(class_name) + 1);
     236    strncpy(set_class, class_name, strlen(class_name) + 1);
     237  }
     238  else {
     239    set_class = NULL;
     240  }
     241
     242  set_method = (char*)mrb_malloc(mrb, strlen(method_name) + 1);
     243
     244  strncpy(set_method, method_name, strlen(method_name) + 1);
     245
     246  index = dbg->bpnum;
     247  dbg->bp[index].bpno = dbg->next_bpno;
     248  dbg->next_bpno++;
     249  dbg->bp[index].enable = TRUE;
     250  dbg->bp[index].type = MRB_DEBUG_BPTYPE_METHOD;
     251  dbg->bp[index].point.methodpoint.method_name = set_method;
     252  dbg->bp[index].point.methodpoint.class_name = set_class;
     253  dbg->bpnum++;
     254
     255  return dbg->bp[index].bpno;
    271256}
    272257
     
    274259mrb_debug_get_breaknum(mrb_state *mrb, mrb_debug_context *dbg)
    275260{
    276         if ((mrb == NULL) || (dbg == NULL)) {
    277                 return MRB_DEBUG_INVALID_ARGUMENT;
    278         }
    279 
    280         return dbg->bpnum;
    281 }
    282 
    283 int32_t
    284 mrb_debug_get_break_all(mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, mrb_debug_breakpoint bp[])
    285 {
    286         uint32_t get_size = 0;
    287 
    288         if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
    289                 return MRB_DEBUG_INVALID_ARGUMENT;
    290         }
    291 
    292         if (dbg->bpnum >= size) {
    293                 get_size = size;
    294         }
    295         else {
    296                 get_size = dbg->bpnum;
    297         }
    298 
    299         memcpy(bp, dbg->bp, sizeof(mrb_debug_breakpoint) * get_size);
    300 
    301         return get_size;
     261  if ((mrb == NULL) || (dbg == NULL)) {
     262    return MRB_DEBUG_INVALID_ARGUMENT;
     263  }
     264
     265  return dbg->bpnum;
     266}
     267
     268int32_t
     269mrb_debug_get_break_all(mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, mrb_debug_breakpoint *bp)
     270{
     271  uint32_t get_size = 0;
     272
     273  if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
     274    return MRB_DEBUG_INVALID_ARGUMENT;
     275  }
     276
     277  if (dbg->bpnum >= size) {
     278    get_size = size;
     279  }
     280  else {
     281    get_size = dbg->bpnum;
     282  }
     283
     284  memcpy(bp, dbg->bp, sizeof(mrb_debug_breakpoint) * get_size);
     285
     286  return get_size;
    302287}
    303288
     
    307292  int32_t index;
    308293
    309         if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
    310                 return MRB_DEBUG_INVALID_ARGUMENT;
    311         }
    312 
    313         index = get_break_index(dbg, bpno);
    314         if (index == MRB_DEBUG_BREAK_INVALID_NO) {
    315                 return MRB_DEBUG_BREAK_INVALID_NO;
    316         }
    317 
    318         bp->bpno = dbg->bp[index].bpno;
    319         bp->enable = dbg->bp[index].enable;
    320         bp->point = dbg->bp[index].point;
    321         bp->type = dbg->bp[index].type;
    322 
    323         return 0;
     294  if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
     295    return MRB_DEBUG_INVALID_ARGUMENT;
     296  }
     297
     298  index = get_break_index(dbg, bpno);
     299  if (index == MRB_DEBUG_BREAK_INVALID_NO) {
     300    return MRB_DEBUG_BREAK_INVALID_NO;
     301  }
     302
     303  bp->bpno = dbg->bp[index].bpno;
     304  bp->enable = dbg->bp[index].enable;
     305  bp->point = dbg->bp[index].point;
     306  bp->type = dbg->bp[index].type;
     307
     308  return 0;
    324309}
    325310
     
    327312mrb_debug_delete_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
    328313{
    329         uint32_t i;
    330         int32_t index;
    331 
    332         if ((mrb == NULL) || (dbg == NULL)) {
    333                 return MRB_DEBUG_INVALID_ARGUMENT;
    334         }
    335 
    336         index = get_break_index(dbg, bpno);
    337         if (index == MRB_DEBUG_BREAK_INVALID_NO) {
    338                 return MRB_DEBUG_BREAK_INVALID_NO;
    339         }
    340 
    341         free_breakpoint(mrb, &dbg->bp[index]);
    342 
    343         for (i = index; i < dbg->bpnum; i++) {
    344                 if ((i + 1) == dbg->bpnum) {
    345                         memset(&dbg->bp[i], 0, sizeof(mrb_debug_breakpoint));
    346                 }
    347                 else {
    348                         memcpy(&dbg->bp[i], &dbg->bp[i + 1], sizeof(mrb_debug_breakpoint));
    349                 }
    350         }
    351 
    352         dbg->bpnum--;
    353 
    354         return MRB_DEBUG_OK;
     314  uint32_t i;
     315  int32_t index;
     316
     317  if ((mrb == NULL) ||(dbg == NULL)) {
     318    return MRB_DEBUG_INVALID_ARGUMENT;
     319  }
     320
     321  index = get_break_index(dbg, bpno);
     322  if (index == MRB_DEBUG_BREAK_INVALID_NO) {
     323    return MRB_DEBUG_BREAK_INVALID_NO;
     324  }
     325
     326  free_breakpoint(mrb, &dbg->bp[index]);
     327
     328  for(i = index ; i < dbg->bpnum; i++) {
     329    if ((i + 1) == dbg->bpnum) {
     330      memset(&dbg->bp[i], 0, sizeof(mrb_debug_breakpoint));
     331    }
     332    else {
     333      memcpy(&dbg->bp[i], &dbg->bp[i + 1], sizeof(mrb_debug_breakpoint));
     334    }
     335  }
     336
     337  dbg->bpnum--;
     338
     339  return MRB_DEBUG_OK;
    355340}
    356341
     
    358343mrb_debug_delete_break_all(mrb_state *mrb, mrb_debug_context *dbg)
    359344{
    360         uint32_t i;
    361 
    362         if ((mrb == NULL) || (dbg == NULL)) {
    363                 return MRB_DEBUG_INVALID_ARGUMENT;
    364         }
    365 
    366         for (i = 0; i < dbg->bpnum; i++) {
    367                 free_breakpoint(mrb, &dbg->bp[i]);
    368         }
    369 
    370         dbg->bpnum = 0;
    371 
    372         return MRB_DEBUG_OK;
     345  uint32_t i;
     346
     347  if ((mrb == NULL) || (dbg == NULL)) {
     348    return MRB_DEBUG_INVALID_ARGUMENT;
     349  }
     350
     351  for(i = 0 ; i < dbg->bpnum ; i++) {
     352    free_breakpoint(mrb, &dbg->bp[i]);
     353  }
     354
     355  dbg->bpnum = 0;
     356
     357  return MRB_DEBUG_OK;
    373358}
    374359
     
    376361mrb_debug_enable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
    377362{
    378         int32_t index = 0;
    379 
    380         if ((mrb == NULL) || (dbg == NULL)) {
    381                 return MRB_DEBUG_INVALID_ARGUMENT;
    382         }
    383 
    384         index = get_break_index(dbg, bpno);
    385         if (index == MRB_DEBUG_BREAK_INVALID_NO) {
    386                 return MRB_DEBUG_BREAK_INVALID_NO;
    387         }
    388 
    389         dbg->bp[index].enable = TRUE;
    390 
    391         return MRB_DEBUG_OK;
     363  int32_t index = 0;
     364
     365  if ((mrb == NULL) || (dbg == NULL)) {
     366    return MRB_DEBUG_INVALID_ARGUMENT;
     367  }
     368
     369  index = get_break_index(dbg, bpno);
     370  if (index == MRB_DEBUG_BREAK_INVALID_NO) {
     371    return MRB_DEBUG_BREAK_INVALID_NO;
     372  }
     373
     374  dbg->bp[index].enable = TRUE;
     375
     376  return MRB_DEBUG_OK;
    392377}
    393378
     
    395380mrb_debug_enable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
    396381{
    397         uint32_t i;
    398 
    399         if ((mrb == NULL) || (dbg == NULL)) {
    400                 return MRB_DEBUG_INVALID_ARGUMENT;
    401         }
    402 
    403         for (i = 0; i < dbg->bpnum; i++) {
    404                 dbg->bp[i].enable = TRUE;
    405         }
    406 
    407         return MRB_DEBUG_OK;
     382  uint32_t i;
     383
     384  if ((mrb == NULL) || (dbg == NULL)) {
     385    return MRB_DEBUG_INVALID_ARGUMENT;
     386  }
     387
     388  for(i = 0 ; i < dbg->bpnum; i++) {
     389    dbg->bp[i].enable = TRUE;
     390  }
     391
     392  return MRB_DEBUG_OK;
    408393}
    409394
     
    411396mrb_debug_disable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
    412397{
    413         int32_t index = 0;
    414 
    415         if ((mrb == NULL) || (dbg == NULL)) {
    416                 return MRB_DEBUG_INVALID_ARGUMENT;
    417         }
    418 
    419         index = get_break_index(dbg, bpno);
    420         if (index == MRB_DEBUG_BREAK_INVALID_NO) {
    421                 return MRB_DEBUG_BREAK_INVALID_NO;
    422         }
    423 
    424         dbg->bp[index].enable = FALSE;
    425 
    426         return MRB_DEBUG_OK;
     398  int32_t index = 0;
     399
     400  if ((mrb == NULL) || (dbg == NULL)) {
     401    return MRB_DEBUG_INVALID_ARGUMENT;
     402  }
     403
     404  index = get_break_index(dbg, bpno);
     405  if (index == MRB_DEBUG_BREAK_INVALID_NO) {
     406    return MRB_DEBUG_BREAK_INVALID_NO;
     407  }
     408
     409  dbg->bp[index].enable = FALSE;
     410
     411  return MRB_DEBUG_OK;
    427412}
    428413
     
    430415mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
    431416{
    432         uint32_t i;
    433 
    434         if ((mrb == NULL) || (dbg == NULL)) {
    435                 return MRB_DEBUG_INVALID_ARGUMENT;
    436         }
    437 
    438         for (i = 0; i < dbg->bpnum; i++) {
    439                 dbg->bp[i].enable = FALSE;
    440         }
    441 
    442         return MRB_DEBUG_OK;
     417  uint32_t i;
     418
     419  if ((mrb == NULL) || (dbg == NULL)) {
     420    return MRB_DEBUG_INVALID_ARGUMENT;
     421  }
     422
     423  for(i = 0 ; i < dbg->bpnum; i++) {
     424    dbg->bp[i].enable = FALSE;
     425  }
     426
     427  return MRB_DEBUG_OK;
    443428}
    444429
    445430static mrb_bool
    446 check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
    447 {
    448         if (pc > irep->iseq) {
    449                 if (line == mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq - 1))) {
    450                         return FALSE;
    451                 }
    452         }
    453         return TRUE;
     431check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, uint16_t line)
     432{
     433  if (pc > irep->iseq) {
     434    if (line == mrb_debug_get_line(mrb, irep, pc - irep->iseq - 1)) {
     435      return FALSE;
     436    }
     437  }
     438  return TRUE;
    454439}
    455440
     
    457442mrb_debug_check_breakpoint_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t line)
    458443{
    459         mrb_debug_breakpoint *bp;
    460         mrb_debug_linepoint *line_p;
    461   uint32_t i;
    462 
    463         if ((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) {
    464                 return MRB_DEBUG_INVALID_ARGUMENT;
    465         }
    466 
    467         if (!check_start_pc_for_line(dbg->irep, dbg->pc, line)) {
    468                 return MRB_DEBUG_OK;
    469         }
    470 
    471         bp = dbg->bp;
    472         for (i = 0; i < dbg->bpnum; i++) {
    473                 switch (bp->type) {
    474                 case MRB_DEBUG_BPTYPE_LINE:
    475                         if (bp->enable == TRUE) {
    476                                 line_p = &bp->point.linepoint;
    477                                 if ((strcmp(line_p->file, file) == 0) && (line_p->lineno == line)) {
    478                                         return bp->bpno;
    479                                 }
    480                         }
    481                         break;
    482                 case MRB_DEBUG_BPTYPE_METHOD:
    483                         break;
    484                 case MRB_DEBUG_BPTYPE_NONE:
    485                 default:
    486                         return MRB_DEBUG_OK;
    487                 }
    488                 bp++;
    489         }
    490         return MRB_DEBUG_OK;
     444  mrb_debug_breakpoint *bp;
     445  mrb_debug_linepoint *line_p;
     446  uint32_t i;
     447
     448  if ((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) {
     449    return MRB_DEBUG_INVALID_ARGUMENT;
     450  }
     451
     452  if (!check_start_pc_for_line(mrb, dbg->irep, dbg->pc, line)) {
     453    return MRB_DEBUG_OK;
     454  }
     455
     456  bp = dbg->bp;
     457  for(i=0; i<dbg->bpnum; i++) {
     458    switch (bp->type) {
     459      case MRB_DEBUG_BPTYPE_LINE:
     460        if (bp->enable == TRUE) {
     461          line_p = &bp->point.linepoint;
     462          if ((strcmp(line_p->file, file) == 0) && (line_p->lineno == line)) {
     463            return bp->bpno;
     464          }
     465        }
     466        break;
     467      case MRB_DEBUG_BPTYPE_METHOD:
     468        break;
     469      case MRB_DEBUG_BPTYPE_NONE:
     470      default:
     471        return MRB_DEBUG_OK;
     472    }
     473    bp++;
     474  }
     475  return MRB_DEBUG_OK;
    491476}
    492477
     
    495480mrb_debug_check_breakpoint_method(mrb_state *mrb, mrb_debug_context *dbg, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
    496481{
    497         mrb_debug_breakpoint *bp;
    498         int32_t bpno;
    499   uint32_t i;
    500 
    501         if ((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) {
    502                 return MRB_DEBUG_INVALID_ARGUMENT;
    503         }
    504 
    505         bp = dbg->bp;
    506         for (i = 0; i < dbg->bpnum; i++) {
    507                 if (bp->type == MRB_DEBUG_BPTYPE_METHOD) {
    508                         if (bp->enable == TRUE) {
    509                                 bpno = compare_break_method(mrb, bp, class_obj, method_sym, isCfunc);
    510                                 if (bpno > 0) {
    511                                         return bpno;
    512                                 }
    513                         }
    514                 }
    515                 else if (bp->type == MRB_DEBUG_BPTYPE_NONE) {
    516                         break;
    517                 }
    518                 bp++;
    519         }
    520 
    521         return 0;
    522 }
    523 
    524 
     482  mrb_debug_breakpoint *bp;
     483  int32_t bpno;
     484  uint32_t i;
     485
     486  if ((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) {
     487    return MRB_DEBUG_INVALID_ARGUMENT;
     488  }
     489
     490  bp = dbg->bp;
     491  for(i=0; i<dbg->bpnum; i++) {
     492    if (bp->type == MRB_DEBUG_BPTYPE_METHOD) {
     493      if (bp->enable == TRUE) {
     494        bpno = compare_break_method(mrb, bp, class_obj, method_sym, isCfunc);
     495        if (bpno > 0) {
     496          return bpno;
     497        }
     498      }
     499    }
     500    else if (bp->type == MRB_DEBUG_BPTYPE_NONE) {
     501      break;
     502    }
     503    bp++;
     504  }
     505
     506  return 0;
     507}
  • EcnlProtoTool/trunk/prototool/src/apibreak.h

    r321 r439  
    77#define APIBREAK_H_
    88
    9 #include "mruby.h"
     9#include <mruby.h>
    1010#include "mrdb.h"
    1111
    12 int32_t mrb_debug_set_break_line( mrb_state *, mrb_debug_context *, const char *, uint16_t );
    13 int32_t mrb_debug_set_break_method( mrb_state *, mrb_debug_context *, const char *, const char * );
    14 int32_t mrb_debug_get_breaknum( mrb_state *, mrb_debug_context * );
    15 int32_t mrb_debug_get_break_all( mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint bp[]);
    16 int32_t mrb_debug_get_break( mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint * );
    17 int32_t mrb_debug_delete_break( mrb_state *, mrb_debug_context *, uint32_t );
    18 int32_t mrb_debug_delete_break_all( mrb_state *, mrb_debug_context * );
    19 int32_t mrb_debug_enable_break( mrb_state *, mrb_debug_context *, uint32_t );
    20 int32_t mrb_debug_enable_break_all( mrb_state *, mrb_debug_context * );
    21 int32_t mrb_debug_disable_break( mrb_state *, mrb_debug_context *, uint32_t );
    22 int32_t mrb_debug_disable_break_all( mrb_state *, mrb_debug_context * );
    23 int32_t mrb_debug_check_breakpoint_line( mrb_state *, mrb_debug_context *, const char *, uint16_t );
    24 int32_t mrb_debug_check_breakpoint_method( mrb_state *, mrb_debug_context *, struct RClass *, mrb_sym, mrb_bool* );
     12int32_t mrb_debug_set_break_line(mrb_state *, mrb_debug_context *, const char *, uint16_t);
     13int32_t mrb_debug_set_break_method(mrb_state *, mrb_debug_context *, const char *, const char *);
     14int32_t mrb_debug_get_breaknum(mrb_state *, mrb_debug_context *);
     15int32_t mrb_debug_get_break_all(mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint bp[]);
     16int32_t mrb_debug_get_break(mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint *);
     17int32_t mrb_debug_delete_break(mrb_state *, mrb_debug_context *, uint32_t);
     18int32_t mrb_debug_delete_break_all(mrb_state *, mrb_debug_context *);
     19int32_t mrb_debug_enable_break(mrb_state *, mrb_debug_context *, uint32_t);
     20int32_t mrb_debug_enable_break_all(mrb_state *, mrb_debug_context *);
     21int32_t mrb_debug_disable_break(mrb_state *, mrb_debug_context *, uint32_t);
     22int32_t mrb_debug_disable_break_all(mrb_state *, mrb_debug_context *);
     23int32_t mrb_debug_check_breakpoint_line(mrb_state *, mrb_debug_context *, const char *, uint16_t);
     24int32_t mrb_debug_check_breakpoint_method(mrb_state *, mrb_debug_context *, struct RClass *, mrb_sym, mrb_bool*);
    2525
    2626#endif /* APIBREAK_H_ */
  • EcnlProtoTool/trunk/prototool/src/apiprint.c

    r321 r439  
    44*/
    55
    6 #include <stdlib.h>
    7 
     6#include <string.h>
    87#include "mrdb.h"
    9 #include "mruby/value.h"
    10 #include "mruby/class.h"
    11 #include "mruby/compile.h"
    12 #include "mruby/error.h"
    13 #include "mruby/numeric.h"
    14 #include "mruby/string.h"
     8#include <mruby/value.h>
     9#include <mruby/class.h>
     10#include <mruby/compile.h>
     11#include <mruby/error.h>
     12#include <mruby/numeric.h>
     13#include <mruby/string.h>
    1514#include "apiprint.h"
    1615
     
    1817mrdb_check_syntax(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len)
    1918{
    20         mrbc_context *c;
     19  mrbc_context *c;
    2120
    22         c = mrbc_context_new(mrb);
    23         c->no_exec = TRUE;
    24         c->capture_errors = TRUE;
    25         c->filename = (char*)dbg->prvfile;
    26         c->lineno = dbg->prvline;
     21  c = mrbc_context_new(mrb);
     22  c->no_exec = TRUE;
     23  c->capture_errors = TRUE;
     24  mrbc_filename(mrb, c, (const char*)dbg->prvfile);
     25  c->lineno = dbg->prvline;
    2726
    28         /* Load program */
    29         mrb_load_nstring_cxt(mrb, expr, len, c);
     27  /* Load program */
     28  mrb_load_nstring_cxt(mrb, expr, len, c);
    3029
    31         mrbc_context_free(mrb, c);
     30  mrbc_context_free(mrb, c);
    3231}
    3332
    3433mrb_value
    35 mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc)
     34mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc, int direct_eval)
    3635{
    37         void(*tmp)(struct mrb_state *, struct mrb_irep *, mrb_code *, mrb_value *);
    38         mrb_value ruby_code;
    39         mrb_value s;
    40         mrb_value v;
    41         mrb_value recv;
     36  void (*tmp)(struct mrb_state *, struct mrb_irep *, const mrb_code *, mrb_value *);
     37  mrb_value ruby_code;
     38  mrb_value s;
     39  mrb_value v;
     40  mrb_value recv;
    4241
    43         /* disable code_fetch_hook */
    44         tmp = mrb->code_fetch_hook;
    45         mrb->code_fetch_hook = NULL;
     42  /* disable code_fetch_hook */
     43  tmp = mrb->code_fetch_hook;
     44  mrb->code_fetch_hook = NULL;
    4645
    47         mrdb_check_syntax(mrb, dbg, expr, len);
    48         if (mrb->exc) {
    49                 v = mrb_obj_value(mrb->exc);
    50                 mrb->exc = 0;
    51         }
    52         else {
    53                 /*
    54                  * begin
    55                  *   expr
    56                  * rescue => e
    57                  *   e
    58                  * end
    59                  */
    60                 ruby_code = mrb_str_new_lit(mrb, "begin\n");
    61                 ruby_code = mrb_str_cat(mrb, ruby_code, expr, len);
    62                 ruby_code = mrb_str_cat_lit(mrb, ruby_code, "\nrescue => e\ne\nend");
     46  mrdb_check_syntax(mrb, dbg, expr, len);
     47  if (mrb->exc) {
     48    v = mrb_obj_value(mrb->exc);
     49    mrb->exc = 0;
     50  }
     51  else if (direct_eval) {
     52    recv = dbg->regs[0];
    6353
    64                 recv = dbg->regs[0];
     54    v = mrb_funcall(mrb, recv, expr, 0);
     55  }
     56  else {
     57    /*
     58     * begin
     59     *   expr
     60     * rescue => e
     61     *   e
     62     * end
     63     */
     64    ruby_code = mrb_str_new_lit(mrb, "begin\n");
     65    ruby_code = mrb_str_cat(mrb, ruby_code, expr, len);
     66    ruby_code = mrb_str_cat_lit(mrb, ruby_code, "\nrescue => e\ne\nend");
    6567
    66                 v = mrb_funcall(mrb, recv, "instance_eval", 1, ruby_code);
    67         }
     68    recv = dbg->regs[0];
    6869
    69         if (exc) {
    70                 *exc = mrb_obj_is_kind_of(mrb, v, mrb->eException_class);
    71         }
     70    v =  mrb_funcall(mrb, recv, "instance_eval", 1, ruby_code);
     71  }
    7272
    73         s = mrb_funcall(mrb, v, "inspect", 0);
     73  if (exc) {
     74    *exc = mrb_obj_is_kind_of(mrb, v, mrb->eException_class);
     75  }
    7476
    75         /* enable code_fetch_hook */
    76         mrb->code_fetch_hook = tmp;
     77  s = mrb_inspect(mrb, v);
    7778
    78         return s;
     79  /* enable code_fetch_hook */
     80  mrb->code_fetch_hook = tmp;
     81
     82  return s;
    7983}
  • EcnlProtoTool/trunk/prototool/src/apiprint.h

    r321 r439  
    66#define APIPRINT_H_
    77
    8 #include "mruby.h"
     8#include <mruby.h>
    99#include "mrdb.h"
    1010
    11 mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*);
     11mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*, int);
    1212
    1313#endif /* APIPRINT_H_ */
  • EcnlProtoTool/trunk/prototool/src/cmdbreak.c

    r321 r439  
    44*/
    55
    6 #include <stdlib.h>
     6#include <ctype.h>
    77#include <string.h>
    8 
    9 #include "mruby.h"
    10 #include "mruby/dump.h"
    11 #include "mruby/debug.h"
    12 #include "mruby/string.h"
     8#include <mruby.h>
     9#include <mruby/dump.h>
     10#include <mruby/debug.h>
     11#include <mruby/string.h>
    1312#include "mrdb.h"
    1413#include "mrdberror.h"
     
    4443#define BPNO_LETTER_NUM 9
    4544
    46 typedef int32_t(*all_command_func)(mrb_state *, mrb_debug_context *);
    47 typedef int32_t(*select_command_func)(mrb_state *, mrb_debug_context *, uint32_t);
     45typedef int32_t (*all_command_func)(mrb_state *, mrb_debug_context *);
     46typedef int32_t (*select_command_func)(mrb_state *, mrb_debug_context *, uint32_t);
    4847
    4948static void
    5049print_api_common_error(int32_t error)
    5150{
    52         switch (error) {
    53         case MRB_DEBUG_INVALID_ARGUMENT:
    54                 puts(BREAK_ERR_MSG_INVALIDARG);
    55                 break;
    56         default:
    57                 break;
    58         }
     51  switch(error) {
     52    case MRB_DEBUG_INVALID_ARGUMENT:
     53      puts(BREAK_ERR_MSG_INVALIDARG);
     54      break;
     55    default:
     56      break;
     57  }
    5958}
    6059
     
    6968parse_breakpoint_no(char* args)
    7069{
    71         char* ps = args;
    72         uint32_t l;
    73 
    74         if ((*ps == '0') || (strlen(ps) >= BPNO_LETTER_NUM)) {
    75                 return 0;
    76         }
    77 
    78         while (!(ISBLANK(*ps) || ISCNTRL(*ps))) {
    79                 if (!ISDIGIT(*ps)) {
    80                         return 0;
    81                 }
    82                 ps++;
    83         }
    84 
    85         STRTOUL(l, args);
    86         return l;
     70  char* ps = args;
     71  uint32_t l;
     72
     73  if ((*ps == '0')||(strlen(ps) >= BPNO_LETTER_NUM)) {
     74    return 0;
     75  }
     76
     77  while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
     78    if (!ISDIGIT(*ps)) {
     79      return 0;
     80    }
     81    ps++;
     82  }
     83
     84  STRTOUL(l, args);
     85  return l;
    8786}
    8887
     
    9089exe_set_command_all(mrb_state *mrb, mrdb_state *mrdb, all_command_func func)
    9190{
    92         int32_t ret = MRB_DEBUG_OK;
    93 
    94         if (mrdb->wcnt == 1) {
    95                 ret = func(mrb, mrdb->dbg);
    96                 print_api_common_error(ret);
    97                 return TRUE;
    98         }
    99         return FALSE;
     91  int32_t ret = MRB_DEBUG_OK;
     92
     93  if (mrdb->wcnt == 1) {
     94    ret = func(mrb, mrdb->dbg);
     95    print_api_common_error(ret);
     96    return TRUE;
     97  }
     98  return FALSE;
    10099}
    101100
     
    103102exe_set_command_select(mrb_state *mrb, mrdb_state *mrdb, select_command_func func)
    104103{
    105         char* ps;
    106         int32_t ret = MRB_DEBUG_OK;
    107         int32_t bpno = 0;
    108         int32_t i;
    109 
    110         for (i = 1; i < mrdb->wcnt; i++) {
    111                 ps = mrdb->words[i];
    112                 bpno = parse_breakpoint_no(ps);
    113                 if (bpno == 0) {
    114                         printf(BREAK_ERR_MSG_INVALIDBPNO, ps);
    115                         break;
    116                 }
    117                 ret = func(mrb, mrdb->dbg, (uint32_t)bpno);
    118                 if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
    119                         printf(BREAK_ERR_MSG_NOBPNO, bpno);
    120                 }
    121                 else if (ret != MRB_DEBUG_OK) {
    122                         print_api_common_error(ret);
    123                 }
    124         }
     104  char* ps;
     105  int32_t ret = MRB_DEBUG_OK;
     106  int32_t bpno = 0;
     107  int32_t i;
     108
     109  for(i=1; i<mrdb->wcnt; i++) {
     110    ps = mrdb->words[i];
     111    bpno = parse_breakpoint_no(ps);
     112    if (bpno == 0) {
     113      printf(BREAK_ERR_MSG_INVALIDBPNO, ps);
     114      break;
     115    }
     116    ret = func(mrb, mrdb->dbg, (uint32_t)bpno);
     117    if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
     118      printf(BREAK_ERR_MSG_NOBPNO, bpno);
     119    }
     120    else if (ret != MRB_DEBUG_OK) {
     121      print_api_common_error(ret);
     122    }
     123  }
    125124}
    126125
     
    128127check_bptype(char* args)
    129128{
    130         char* ps = args;
    131 
    132         if (ISBLANK(*ps) || ISCNTRL(*ps)) {
    133                 puts(BREAK_ERR_MSG_BLANK);
    134                 return MRB_DEBUG_BPTYPE_NONE;
    135         }
    136 
    137         if (!ISDIGIT(*ps)) {
    138                 return MRB_DEBUG_BPTYPE_METHOD;
    139         }
    140 
    141         while (!(ISBLANK(*ps) || ISCNTRL(*ps))) {
    142                 if (!ISDIGIT(*ps)) {
    143                         printf(BREAK_ERR_MSG_INVALIDSTR, args);
    144                         return MRB_DEBUG_BPTYPE_NONE;
    145                 }
    146                 ps++;
    147         }
    148 
    149         if ((*args == '0') || (strlen(args) >= LINENO_MAX_DIGIT)) {
    150                 puts(BREAK_ERR_MSG_RANGEOVER);
    151                 return MRB_DEBUG_BPTYPE_NONE;
    152         }
    153 
    154         return MRB_DEBUG_BPTYPE_LINE;
     129  char* ps = args;
     130
     131  if (ISBLANK(*ps)||ISCNTRL(*ps)) {
     132    puts(BREAK_ERR_MSG_BLANK);
     133    return MRB_DEBUG_BPTYPE_NONE;
     134  }
     135
     136  if (!ISDIGIT(*ps)) {
     137    return MRB_DEBUG_BPTYPE_METHOD;
     138  }
     139
     140  while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
     141    if (!ISDIGIT(*ps)) {
     142      printf(BREAK_ERR_MSG_INVALIDSTR, args);
     143      return MRB_DEBUG_BPTYPE_NONE;
     144    }
     145    ps++;
     146  }
     147
     148  if ((*args == '0')||(strlen(args) >= LINENO_MAX_DIGIT)) {
     149    puts(BREAK_ERR_MSG_RANGEOVER);
     150    return MRB_DEBUG_BPTYPE_NONE;
     151  }
     152
     153  return MRB_DEBUG_BPTYPE_LINE;
    155154}
    156155
     
    158157print_breakpoint(mrb_debug_breakpoint *bp)
    159158{
    160         const char* enable_letter[] = { BREAK_INFO_MSG_DISABLE, BREAK_INFO_MSG_ENABLE };
    161 
    162         if (bp->type == MRB_DEBUG_BPTYPE_LINE) {
    163                 printf(BREAK_INFO_MSG_LINEBREAK,
    164                         bp->bpno, enable_letter[bp->enable], bp->point.linepoint.file, bp->point.linepoint.lineno);
    165         }
    166         else {
    167                 if (bp->point.methodpoint.class_name == NULL) {
    168                         printf(BREAK_INFO_MSG_METHODBREAK_NOCLASS,
    169                                 bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.method_name);
    170                 }
    171                 else {
    172                         printf(BREAK_INFO_MSG_METHODBREAK,
    173                                 bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.class_name, bp->point.methodpoint.method_name);
    174                 }
    175         }
     159  const char* enable_letter[] = {BREAK_INFO_MSG_DISABLE, BREAK_INFO_MSG_ENABLE};
     160
     161  if (bp->type == MRB_DEBUG_BPTYPE_LINE) {
     162    printf(BREAK_INFO_MSG_LINEBREAK,
     163      bp->bpno, enable_letter[bp->enable], bp->point.linepoint.file, bp->point.linepoint.lineno);
     164  }
     165  else {
     166    if (bp->point.methodpoint.class_name == NULL) {
     167      printf(BREAK_INFO_MSG_METHODBREAK_NOCLASS,
     168        bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.method_name);
     169    }
     170    else {
     171      printf(BREAK_INFO_MSG_METHODBREAK,
     172        bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.class_name, bp->point.methodpoint.method_name);
     173    }
     174  }
    176175}
    177176
     
    179178info_break_all(mrb_state *mrb, mrdb_state *mrdb)
    180179{
    181         int32_t bpnum = 0;
    182         int32_t i = 0;
    183         int32_t ret = MRB_DEBUG_OK;
    184         mrb_debug_breakpoint *bp_list;
    185 
    186         bpnum = mrb_debug_get_breaknum(mrb, mrdb->dbg);
    187         if (bpnum < 0) {
    188                 print_api_common_error(bpnum);
    189                 return;
    190         }
    191         else if (bpnum == 0) {
    192                 puts(BREAK_ERR_MSG_NOBPNO_INFOALL);
    193                 return;
    194         }
    195         bp_list = (mrb_debug_breakpoint*)mrb_malloc(mrb, bpnum * sizeof(mrb_debug_breakpoint));
    196 
    197         ret = mrb_debug_get_break_all(mrb, mrdb->dbg, (uint32_t)bpnum, bp_list);
    198         if (ret < 0) {
    199                 print_api_common_error(ret);
    200                 return;
    201         }
    202         puts(BREAK_INFO_MSG_HEADER);
    203         for (i = 0; i < bpnum; i++) {
    204                 print_breakpoint(&bp_list[i]);
    205         }
    206 
    207         mrb_free(mrb, bp_list);
     180  int32_t bpnum = 0;
     181  int32_t i = 0;
     182  int32_t ret = MRB_DEBUG_OK;
     183  mrb_debug_breakpoint *bp_list;
     184
     185  bpnum = mrb_debug_get_breaknum(mrb, mrdb->dbg);
     186  if (bpnum < 0) {
     187    print_api_common_error(bpnum);
     188    return;
     189  }
     190  else if (bpnum == 0) {
     191    puts(BREAK_ERR_MSG_NOBPNO_INFOALL);
     192    return;
     193  }
     194  bp_list = (mrb_debug_breakpoint*)mrb_malloc(mrb, bpnum * sizeof(mrb_debug_breakpoint));
     195
     196  ret = mrb_debug_get_break_all(mrb, mrdb->dbg, (uint32_t)bpnum, bp_list);
     197  if (ret < 0) {
     198    print_api_common_error(ret);
     199    return;
     200  }
     201  puts(BREAK_INFO_MSG_HEADER);
     202  for(i = 0 ; i < bpnum ; i++) {
     203    print_breakpoint(&bp_list[i]);
     204  }
     205
     206  mrb_free(mrb, bp_list);
    208207}
    209208
     
    211210info_break_select(mrb_state *mrb, mrdb_state *mrdb)
    212211{
    213         int32_t ret = MRB_DEBUG_OK;
    214         int32_t bpno = 0;
    215         char* ps = mrdb->command;
    216         mrb_debug_breakpoint bp;
    217         mrb_bool isFirst = TRUE;
    218         int32_t i;
    219 
    220         for (i = 2; i < mrdb->wcnt; i++) {
    221                 ps = mrdb->words[i];
    222                 bpno = parse_breakpoint_no(ps);
    223                 if (bpno == 0) {
    224                         puts(BREAK_ERR_MSG_INVALIDBPNO_INFO);
    225                         break;
    226                 }
    227 
    228                 ret = mrb_debug_get_break(mrb, mrdb->dbg, bpno, &bp);
    229                 if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
    230                         printf(BREAK_ERR_MSG_NOBPNO_INFO, bpno);
    231                         break;
    232                 }
    233                 else if (ret != MRB_DEBUG_OK) {
    234                         print_api_common_error(ret);
    235                         break;
    236                 }
    237                 else if (isFirst == TRUE) {
    238                         isFirst = FALSE;
    239                         puts(BREAK_INFO_MSG_HEADER);
    240                 }
    241                 print_breakpoint(&bp);
    242         }
     212  int32_t ret = MRB_DEBUG_OK;
     213  int32_t bpno = 0;
     214  char* ps = mrdb->command;
     215  mrb_debug_breakpoint bp;
     216  mrb_bool isFirst = TRUE;
     217  int32_t i;
     218
     219  for(i=2; i<mrdb->wcnt; i++) {
     220    ps = mrdb->words[i];
     221    bpno = parse_breakpoint_no(ps);
     222    if (bpno == 0) {
     223      puts(BREAK_ERR_MSG_INVALIDBPNO_INFO);
     224      break;
     225    }
     226
     227    ret = mrb_debug_get_break(mrb, mrdb->dbg, bpno, &bp);
     228    if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
     229      printf(BREAK_ERR_MSG_NOBPNO_INFO, bpno);
     230      break;
     231    }
     232    else if (ret != MRB_DEBUG_OK) {
     233      print_api_common_error(ret);
     234      break;
     235    }
     236    else if (isFirst == TRUE) {
     237      isFirst = FALSE;
     238      puts(BREAK_INFO_MSG_HEADER);
     239    }
     240    print_breakpoint(&bp);
     241  }
    243242}
    244243
    245244mrb_debug_bptype
    246 parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
    247 {
    248         mrb_debug_context *dbg = mrdb->dbg;
    249         char *args;
    250         char *body;
    251         mrb_debug_bptype type;
    252         uint32_t l;
    253 
    254         if (mrdb->wcnt <= 1) {
    255                 puts(BREAK_ERR_MSG_BLANK);
    256                 return MRB_DEBUG_BPTYPE_NONE;
    257         }
    258 
    259         args = mrdb->words[1];
    260         if ((body = strrchr(args, ':')) == NULL) {
    261                 body = args;
    262                 type = check_bptype(body);
    263         }
    264         else {
    265                 if (body == args) {
    266                         printf(BREAK_ERR_MSG_INVALIDSTR, args);
    267                         return MRB_DEBUG_BPTYPE_NONE;
    268                 }
    269                 *body = '\0';
    270                 type = check_bptype(++body);
    271         }
    272 
    273         switch (type) {
    274         case MRB_DEBUG_BPTYPE_LINE:
    275                 STRTOUL(l, body);
    276                 if (l <= 65535) {
    277                         *line = l;
    278                         *file = (body == args) ? mrb_debug_get_filename(dbg->irep, (uint32_t)(dbg->pc - dbg->irep->iseq)) : args;
    279                 }
    280                 else {
    281                         puts(BREAK_ERR_MSG_RANGEOVER);
    282                         type = MRB_DEBUG_BPTYPE_NONE;
    283                 }
    284                 break;
    285         case MRB_DEBUG_BPTYPE_METHOD:
    286                 if (body == args) {
    287                         /* method only */
    288                         if (ISUPPER(*body) || ISLOWER(*body) || (*body == '_')) {
    289                                 *method = body;
    290                                 *cname = NULL;
    291                         }
    292                         else {
    293                                 printf(BREAK_ERR_MSG_INVALIDMETHOD, args);
    294                                 type = MRB_DEBUG_BPTYPE_NONE;
    295                         }
    296                 }
    297                 else {
    298                         if (ISUPPER(*args)) {
    299                                 switch (*body) {
    300                                 case '@': case '$': case '?': case '.': case ',': case ':':
    301                                 case ';': case '#': case '\\': case '\'': case '\"':
    302                                         printf(BREAK_ERR_MSG_INVALIDMETHOD, body);
    303                                         type = MRB_DEBUG_BPTYPE_NONE;
    304                                         break;
    305                                 default:
    306                                         *method = body;
    307                                         *cname = args;
    308                                         break;
    309                                 }
    310                         }
    311                         else {
    312                                 printf(BREAK_ERR_MSG_INVALIDCLASS, args);
    313                                 type = MRB_DEBUG_BPTYPE_NONE;
    314                         }
    315                 }
    316                 break;
    317         case MRB_DEBUG_BPTYPE_NONE:
    318         default:
    319                 break;
    320         }
    321 
    322         return type;
     245parse_breakcommand(mrb_state *mrb, mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
     246{
     247  mrb_debug_context *dbg = mrdb->dbg;
     248  char *args;
     249  char *body;
     250  mrb_debug_bptype type;
     251  uint32_t l;
     252
     253  if (mrdb->wcnt <= 1) {
     254    puts(BREAK_ERR_MSG_BLANK);
     255    return MRB_DEBUG_BPTYPE_NONE;
     256  }
     257
     258  args = mrdb->words[1];
     259  if ((body = strrchr(args, ':')) == NULL) {
     260    body = args;
     261    type = check_bptype(body);
     262  }
     263  else {
     264    if (body == args) {
     265      printf(BREAK_ERR_MSG_INVALIDSTR, args);
     266      return MRB_DEBUG_BPTYPE_NONE;
     267    }
     268    *body = '\0';
     269    type = check_bptype(++body);
     270  }
     271
     272  switch(type) {
     273    case MRB_DEBUG_BPTYPE_LINE:
     274      STRTOUL(l, body);
     275      if (l <= 65535) {
     276        *line = l;
     277        *file = (body == args)? mrb_debug_get_filename(mrb, dbg->irep, dbg->pc - dbg->irep->iseq): args;
     278      }
     279      else {
     280        puts(BREAK_ERR_MSG_RANGEOVER);
     281        type = MRB_DEBUG_BPTYPE_NONE;
     282      }
     283      break;
     284    case MRB_DEBUG_BPTYPE_METHOD:
     285      if (body == args) {
     286        /* method only */
     287        if (ISUPPER(*body)||ISLOWER(*body)||(*body == '_')) {
     288          *method = body;
     289          *cname = NULL;
     290        }
     291        else {
     292          printf(BREAK_ERR_MSG_INVALIDMETHOD, args);
     293          type = MRB_DEBUG_BPTYPE_NONE;
     294        }
     295      }
     296      else {
     297        if (ISUPPER(*args)) {
     298          switch(*body) {
     299            case '@': case '$': case '?': case '.': case ',': case ':':
     300            case ';': case '#': case '\\': case '\'': case '\"':
     301            printf(BREAK_ERR_MSG_INVALIDMETHOD, body);
     302            type = MRB_DEBUG_BPTYPE_NONE;
     303            break;
     304          default:
     305            *method = body;
     306            *cname = args;
     307            break;
     308          }
     309        }
     310        else {
     311          printf(BREAK_ERR_MSG_INVALIDCLASS, args);
     312          type = MRB_DEBUG_BPTYPE_NONE;
     313        }
     314      }
     315      break;
     316    case MRB_DEBUG_BPTYPE_NONE:
     317    default:
     318      break;
     319  }
     320
     321  return type;
    323322}
    324323
     
    326325dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb)
    327326{
    328         mrb_debug_bptype type;
    329         mrb_debug_context *dbg = mrdb->dbg;
    330         const char *file = NULL;
    331         uint32_t line = 0;
    332         char *cname = NULL;
    333         char *method = NULL;
    334         int32_t ret;
    335 
    336         type = parse_breakcommand(mrdb, &file, &line, &cname, &method);
    337         switch (type) {
    338         case MRB_DEBUG_BPTYPE_LINE:
    339                 ret = mrb_debug_set_break_line(mrb, dbg, file, line);
    340                 break;
    341         case MRB_DEBUG_BPTYPE_METHOD:
    342                 ret = mrb_debug_set_break_method(mrb, dbg, cname, method);
    343                 break;
    344         case MRB_DEBUG_BPTYPE_NONE:
    345         default:
    346                 return DBGST_PROMPT;
    347         }
    348 
    349         if (ret >= 0) {
    350                 if (type == MRB_DEBUG_BPTYPE_LINE) {
    351                         printf(BREAK_SET_MSG_LINE, ret, file, line);
    352                 }
    353                 else if ((type == MRB_DEBUG_BPTYPE_METHOD) && (cname == NULL)) {
    354                         printf(BREAK_SET_MSG_METHOD, ret, method);
    355                 }
    356                 else {
    357                         printf(BREAK_SET_MSG_CLASS_METHOD, ret, cname, method);
    358                 }
    359         }
    360         else {
    361                 switch (ret) {
    362                 case MRB_DEBUG_BREAK_INVALID_LINENO:
    363                         printf(BREAK_ERR_MSG_INVALIDLINENO, line, file);
    364                         break;
    365                 case MRB_DEBUG_BREAK_INVALID_FILE:
    366                         printf(BREAK_ERR_MSG_INVALIDFILE, file);
    367                         break;
    368                 case MRB_DEBUG_BREAK_NUM_OVER:
    369                         puts(BREAK_ERR_MSG_NUMOVER);
    370                         break;
    371                 case MRB_DEBUG_BREAK_NO_OVER:
    372                         puts(BREAK_ERR_MSG_NOOVER);
    373                         break;
    374                 case MRB_DEBUG_INVALID_ARGUMENT:
    375                         puts(BREAK_ERR_MSG_INVALIDARG);
    376                         break;
    377                 case MRB_DEBUG_NOBUF:
    378                         puts("T.B.D.");
    379                         break;
    380                 default:
    381                         break;
    382                 }
    383         }
    384 
    385         return DBGST_PROMPT;
     327  mrb_debug_bptype type;
     328  mrb_debug_context *dbg = mrdb->dbg;
     329  const char *file = NULL;
     330  uint32_t line = 0;
     331  char *cname = NULL;
     332  char *method = NULL;
     333  int32_t ret;
     334
     335  type = parse_breakcommand(mrb, mrdb, &file, &line, &cname, &method);
     336  switch (type) {
     337    case MRB_DEBUG_BPTYPE_LINE:
     338      ret = mrb_debug_set_break_line(mrb, dbg, file, line);
     339      break;
     340    case MRB_DEBUG_BPTYPE_METHOD:
     341      ret = mrb_debug_set_break_method(mrb, dbg, cname, method);
     342      break;
     343    case MRB_DEBUG_BPTYPE_NONE:
     344    default:
     345      return DBGST_PROMPT;
     346  }
     347
     348  if (ret >= 0) {
     349    if (type == MRB_DEBUG_BPTYPE_LINE) {
     350      printf(BREAK_SET_MSG_LINE, ret, file, line);
     351    }
     352    else if ((type == MRB_DEBUG_BPTYPE_METHOD)&&(cname == NULL)) {
     353      printf(BREAK_SET_MSG_METHOD, ret, method);
     354    }
     355    else {
     356      printf(BREAK_SET_MSG_CLASS_METHOD, ret, cname, method);
     357    }
     358  }
     359  else {
     360    switch (ret) {
     361      case MRB_DEBUG_BREAK_INVALID_LINENO:
     362        printf(BREAK_ERR_MSG_INVALIDLINENO, line, file);
     363        break;
     364      case MRB_DEBUG_BREAK_INVALID_FILE:
     365        printf(BREAK_ERR_MSG_INVALIDFILE, file);
     366        break;
     367      case MRB_DEBUG_BREAK_NUM_OVER:
     368        puts(BREAK_ERR_MSG_NUMOVER);
     369        break;
     370      case MRB_DEBUG_BREAK_NO_OVER:
     371        puts(BREAK_ERR_MSG_NOOVER);
     372        break;
     373      case MRB_DEBUG_INVALID_ARGUMENT:
     374        puts(BREAK_ERR_MSG_INVALIDARG);
     375        break;
     376      case MRB_DEBUG_NOBUF:
     377        puts("T.B.D.");
     378        break;
     379      default:
     380        break;
     381    }
     382  }
     383
     384  return DBGST_PROMPT;
    386385}
    387386
     
    389388dbgcmd_info_break(mrb_state *mrb, mrdb_state *mrdb)
    390389{
    391         if (mrdb->wcnt == 2) {
    392                 info_break_all(mrb, mrdb);
    393         }
    394         else {
    395                 info_break_select(mrb, mrdb);
    396         }
    397 
    398         return DBGST_PROMPT;
     390  if (mrdb->wcnt == 2) {
     391    info_break_all(mrb, mrdb);
     392  }
     393  else {
     394    info_break_select(mrb, mrdb);
     395  }
     396
     397  return DBGST_PROMPT;
    399398}
    400399
     
    402401dbgcmd_delete(mrb_state *mrb, mrdb_state *mrdb)
    403402{
    404         mrb_bool ret = FALSE;
    405 
    406         ret = exe_set_command_all(mrb, mrdb, mrb_debug_delete_break_all);
    407         if (ret != TRUE) {
    408                 exe_set_command_select(mrb, mrdb, mrb_debug_delete_break);
    409         }
    410 
    411         return DBGST_PROMPT;
     403  mrb_bool ret = FALSE;
     404
     405  ret = exe_set_command_all(mrb, mrdb, mrb_debug_delete_break_all);
     406  if (ret != TRUE) {
     407    exe_set_command_select(mrb, mrdb, mrb_debug_delete_break);
     408  }
     409
     410  return DBGST_PROMPT;
    412411}
    413412
     
    415414dbgcmd_enable(mrb_state *mrb, mrdb_state *mrdb)
    416415{
    417         mrb_bool ret = FALSE;
    418 
    419         ret = exe_set_command_all(mrb, mrdb, mrb_debug_enable_break_all);
    420         if (ret != TRUE) {
    421                 exe_set_command_select(mrb, mrdb, mrb_debug_enable_break);
    422         }
    423 
    424         return DBGST_PROMPT;
     416  mrb_bool ret = FALSE;
     417
     418  ret = exe_set_command_all(mrb, mrdb, mrb_debug_enable_break_all);
     419  if (ret != TRUE) {
     420    exe_set_command_select(mrb, mrdb, mrb_debug_enable_break);
     421  }
     422
     423  return DBGST_PROMPT;
    425424}
    426425
     
    428427dbgcmd_disable(mrb_state *mrb, mrdb_state *mrdb)
    429428{
    430         mrb_bool ret = FALSE;
    431 
    432         ret = exe_set_command_all(mrb, mrdb, mrb_debug_disable_break_all);
    433         if (ret != TRUE) {
    434                 exe_set_command_select(mrb, mrdb, mrb_debug_disable_break);
    435         }
    436         return DBGST_PROMPT;
    437 }
     429  mrb_bool ret = FALSE;
     430
     431  ret = exe_set_command_all(mrb, mrdb, mrb_debug_disable_break_all);
     432  if (ret != TRUE) {
     433    exe_set_command_select(mrb, mrdb, mrb_debug_disable_break);
     434  }
     435  return DBGST_PROMPT;
     436}
  • EcnlProtoTool/trunk/prototool/src/cmdmisc.c

    r321 r439  
    44*/
    55
     6#include <ctype.h>
    67#include <stdlib.h>
    78#include <string.h>
    89
    9 #include "mruby/compile.h"
    10 #include "mrdb.h"
    11 
    12 typedef struct help_msg
    13 {
    14         const char *cmd1;
    15         const char *cmd2;
    16         const char *short_msg;
    17         const char *long_msg;
     10#include "apilist.h"
     11#include <mruby/compile.h>
     12
     13typedef struct help_msg {
     14  const char *cmd1;
     15  const char *cmd2;
     16  const char *short_msg;
     17  const char *long_msg;
    1818} help_msg;
    1919
    2020static help_msg help_msg_list[] = {
    2121  {
    22         "b[reak]", NULL, "Set breakpoint",
    23         "Usage: break [file:]line\n"
    24         "       break [class:]method\n"
    25         "\n"
    26         "Set breakpoint at specified line or method.\n"
    27         "If \'[file:]line\' is specified, break at start of code for that line (in a file).\n"
    28         "If \'[class:]method\' is specified, break at start of code for that method (of the class).\n"
    29   },
    30   {
    31         "c[ontinue]", NULL, "Continue program being debugged",
    32         "Usage: continue [N]\n"
    33         "\n"
    34         "Continue program stopped by a breakpoint.\n"
    35         "If N, which is non negative value, is passed,\n"
    36         "proceed program until the N-th breakpoint is coming.\n"
    37         "If N is not passed, N is assumed 1.\n"
    38   },
    39   {
    40         "d[elete]", NULL, "Delete some breakpoints",
    41         "Usage: delete [bpno1 [bpno2 [... [bpnoN]]]]\n"
    42         "\n"
    43         "Delete some breakpoints.\n"
    44         "Arguments are breakpoint numbers with spaces in between.\n"
    45         "To delete all breakpoints, give no argument.\n"
    46   },
    47   {
    48         "dis[able]", NULL, "Disable some breakpoints",
    49         "Usage: disable [bpno1 [bpno2 [... [bpnoN]]]]\n"
    50         "\n"
    51         "Disable some breakpoints.\n"
    52         "Arguments are breakpoint numbers with spaces in between.\n"
    53         "To disable all breakpoints, give no argument.\n"
    54   },
    55   {
    56         "en[able]", NULL, "Enable some breakpoints",
    57         "Usage: enable [bpno1 [bpno2 [... [bpnoN]]]]\n"
    58         "\n"
    59         "Enable some breakpoints.\n"
    60         "Arguments are breakpoint numbers with spaces in between.\n"
    61         "To enable all breakpoints, give no argument.\n"
    62   },
    63   {
    64         "ev[al]", NULL, "Evaluate expression",
    65         "Usage: eval expr\n"
    66         "\n"
    67         "It evaluates and prints the value of the mruby expression.\n"
    68         "This is equivalent to the \'print\' command.\n"
    69   },
    70   {
    71         "h[elp]", NULL, "Print this help",
    72         "Usage: help [command]\n"
    73         "\n"
    74         "With no arguments, help displays a short list of commands.\n"
    75         "With a command name as help argument, help displays how to use that command.\n"
    76   },
    77   {
    78         "i[nfo]", "b[reakpoints]", "Status of breakpoints",
    79         "Usage: info breakpoints [bpno1 [bpno2 [... [bpnoN]]]]\n"
    80         "\n"
    81         "Status of specified breakpoints (all user-settable breakpoints if no argument).\n"
    82         "Arguments are breakpoint numbers with spaces in between.\n"
    83   },
    84   {
    85         "l[ist]", NULL, "List specified line",
    86         "Usage: list\n"
    87         "       list first[,last]\n"
    88         "       list filename:first[,last]\n"
    89         "\n"
    90         "Print lines from a source file.\n"
    91         "\n"
    92         "With first and last, list prints lines from first to last.\n"
    93         "When last is empty, it stands for ten lines away from first.\n"
    94         "With filename, list prints lines in the specified source file.\n"
    95   },
    96   {
    97         "p[rint]", NULL, "Print value of expression",
    98         "Usage: print expr\n"
    99         "\n"
    100         "It evaluates and prints the value of the mruby expression.\n"
    101         "This is equivalent to the \'eval\' command.\n"
    102   },
    103   {
    104         "q[uit]", NULL, "Exit mrdb",
    105         "Usage: quit\n"
    106         "\n"
    107         "Exit mrdb.\n"
    108   },
    109   {
    110         "r[un]", NULL, "Start debugged program",
    111         "Usage: run\n"
    112         "\n"
    113         "Start debugged program.\n"
    114   },
    115   {
    116         "s[tep]", NULL, "Step program until it reaches a different source line",
    117         "Usage: step\n"
    118         "\n"
    119         "Step program until it reaches a different source line.\n"
     22    "b[reak]", NULL, "Set breakpoint",
     23    "Usage: break [file:]line\n"
     24    "       break [class:]method\n"
     25    "\n"
     26    "Set breakpoint at specified line or method.\n"
     27    "If \'[file:]line\' is specified, break at start of code for that line (in a file).\n"
     28    "If \'[class:]method\' is specified, break at start of code for that method (of the class).\n"
     29  },
     30  {
     31    "c[ontinue]", NULL, "Continue program being debugged",
     32    "Usage: continue [N]\n"
     33    "\n"
     34    "Continue program stopped by a breakpoint.\n"
     35    "If N, which is non negative value, is passed,\n"
     36    "proceed program until the N-th breakpoint is coming.\n"
     37    "If N is not passed, N is assumed 1.\n"
     38  },
     39  {
     40    "d[elete]", NULL, "Delete some breakpoints",
     41    "Usage: delete [bpno1 [bpno2 [... [bpnoN]]]]\n"
     42    "\n"
     43    "Delete some breakpoints.\n"
     44    "Arguments are breakpoint numbers with spaces in between.\n"
     45    "To delete all breakpoints, give no argument.\n"
     46  },
     47  {
     48    "dis[able]", NULL, "Disable some breakpoints",
     49    "Usage: disable [bpno1 [bpno2 [... [bpnoN]]]]\n"
     50    "\n"
     51    "Disable some breakpoints.\n"
     52    "Arguments are breakpoint numbers with spaces in between.\n"
     53    "To disable all breakpoints, give no argument.\n"
     54  },
     55  {
     56    "en[able]", NULL, "Enable some breakpoints",
     57    "Usage: enable [bpno1 [bpno2 [... [bpnoN]]]]\n"
     58    "\n"
     59    "Enable some breakpoints.\n"
     60    "Arguments are breakpoint numbers with spaces in between.\n"
     61    "To enable all breakpoints, give no argument.\n"
     62  },
     63  {
     64    "ev[al]", NULL, "Evaluate expression",
     65    "Usage: eval expr\n"
     66    "\n"
     67    "It evaluates and prints the value of the mruby expression.\n"
     68    "This is equivalent to the \'print\' command.\n"
     69  },
     70  {
     71    "h[elp]", NULL, "Print this help",
     72    "Usage: help [command]\n"
     73    "\n"
     74    "With no arguments, help displays a short list of commands.\n"
     75    "With a command name as help argument, help displays how to use that command.\n"
     76  },
     77  {
     78    "i[nfo]", "b[reakpoints]", "Status of breakpoints",
     79    "Usage: info breakpoints [bpno1 [bpno2 [... [bpnoN]]]]\n"
     80    "\n"
     81    "Status of specified breakpoints (all user-settable breakpoints if no argument).\n"
     82    "Arguments are breakpoint numbers with spaces in between.\n"
     83  },
     84  {
     85    "i[nfo]", "l[ocals]", "Print name of local variables",
     86    "Usage: info locals\n"
     87    "\n"
     88    "Print name of local variables.\n"
     89  },
     90  {
     91    "l[ist]", NULL, "List specified line",
     92    "Usage: list\n"
     93    "       list first[,last]\n"
     94    "       list filename:first[,last]\n"
     95    "\n"
     96    "Print lines from a source file.\n"
     97    "\n"
     98    "With first and last, list prints lines from first to last.\n"
     99    "When last is empty, it stands for ten lines away from first.\n"
     100    "With filename, list prints lines in the specified source file.\n"
     101  },
     102  {
     103    "p[rint]", NULL, "Print value of expression",
     104    "Usage: print expr\n"
     105    "\n"
     106    "It evaluates and prints the value of the mruby expression.\n"
     107    "This is equivalent to the \'eval\' command.\n"
     108  },
     109  {
     110    "q[uit]", NULL, "Exit mrdb",
     111    "Usage: quit\n"
     112    "\n"
     113    "Exit mrdb.\n"
     114  },
     115  {
     116    "r[un]", NULL, "Start debugged program",
     117    "Usage: run\n"
     118    "\n"
     119    "Start debugged program.\n"
     120  },
     121  {
     122    "s[tep]", NULL, "Step program until it reaches a different source line",
     123    "Usage: step\n"
     124    "\n"
     125    "Step program until it reaches a different source line.\n"
    120126  },
    121127  { NULL, NULL, NULL, NULL }
    122128};
    123129
    124 typedef struct listcmd_parser_state
    125 {
    126         mrb_bool parse_error;
    127         mrb_bool has_line_min;
    128         mrb_bool has_line_max;
    129         char *filename;
    130         uint16_t line_min;
    131         uint16_t line_max;
     130typedef struct listcmd_parser_state {
     131  mrb_bool parse_error;
     132  mrb_bool has_line_min;
     133  mrb_bool has_line_max;
     134  char *filename;
     135  uint16_t line_min;
     136  uint16_t line_max;
    132137} listcmd_parser_state;
    133138
     
    135140listcmd_parser_state_new(mrb_state *mrb)
    136141{
    137         listcmd_parser_state *st = (listcmd_parser_state *)mrb_malloc(mrb, sizeof(listcmd_parser_state));
    138         memset(st, 0, sizeof(listcmd_parser_state));
    139         return st;
     142  listcmd_parser_state *st = (listcmd_parser_state*)mrb_malloc(mrb, sizeof(listcmd_parser_state));
     143  memset(st, 0, sizeof(listcmd_parser_state));
     144  return st;
    140145}
    141146
     
    143148listcmd_parser_state_free(mrb_state *mrb, listcmd_parser_state *st)
    144149{
    145         if (st != NULL) {
    146                 if (st->filename != NULL) {
    147                         mrb_free(mrb, st->filename);
    148                 }
    149                 mrb_free(mrb, st);
    150         }
     150  if (st != NULL) {
     151    if (st->filename != NULL) {
     152      mrb_free(mrb, st->filename);
     153    }
     154    mrb_free(mrb, st);
     155  }
    151156}
    152157
     
    154159parse_uint(char **sp, uint16_t *n)
    155160{
    156         char *p;
    157         int i;
    158 
    159         if (*sp == NULL || **sp == '\0') {
    160                 return FALSE;
    161         }
    162 
    163         for (p = *sp; *p != '\0' && ISDIGIT(*p); p++);
    164 
    165         if (p != *sp && (i = atoi(*sp)) >= 0) {
    166                 *n = (uint16_t)i;
    167                 *sp = p;
    168                 return TRUE;
    169         }
    170         return FALSE;
     161  char *p;
     162  int i;
     163
     164  if (*sp == NULL || **sp == '\0') {
     165    return FALSE;
     166  }
     167
     168  for (p = *sp; *p != '\0' && ISDIGIT(*p); p++) ;
     169
     170  if (p != *sp && (i = atoi(*sp)) >= 0) {
     171    *n = (uint16_t)i;
     172    *sp = p;
     173    return TRUE;
     174  }
     175  return FALSE;
    171176}
    172177
     
    174179skip_char(char **sp, char c)
    175180{
    176         if (*sp != NULL && **sp == c) {
    177                 ++*sp;
    178                 return TRUE;
    179         }
    180         return FALSE;
     181  if (*sp != NULL && **sp == c) {
     182    ++*sp;
     183    return TRUE;
     184  }
     185  return FALSE;
    181186}
    182187
     
    184189parse_lineno(mrb_state *mrb, char **sp, listcmd_parser_state *st)
    185190{
    186         if (*sp == NULL || **sp == '\0') {
    187                 return FALSE;
    188         }
    189 
    190         st->has_line_min = FALSE;
    191         st->has_line_max = FALSE;
    192 
    193         if (parse_uint(sp, &st->line_min)) {
    194                 st->has_line_min = TRUE;
    195         }
    196         else {
    197                 return FALSE;
    198         }
    199 
    200         if (skip_char(sp, ',')) {
    201                 if (parse_uint(sp, &st->line_max)) {
    202                         st->has_line_max = TRUE;
    203                 }
    204                 else {
    205                         st->parse_error = TRUE;
    206                         return FALSE;
    207                 }
    208         }
    209         return TRUE;
     191  if (*sp == NULL || **sp == '\0') {
     192    return FALSE;
     193  }
     194
     195  st->has_line_min = FALSE;
     196  st->has_line_max = FALSE;
     197
     198  if (parse_uint(sp, &st->line_min)) {
     199    st->has_line_min = TRUE;
     200  }
     201  else {
     202    return FALSE;
     203  }
     204
     205  if (skip_char(sp, ',')) {
     206    if (parse_uint(sp, &st->line_max)) {
     207      st->has_line_max = TRUE;
     208    }
     209    else {
     210      st->parse_error = TRUE;
     211      return FALSE;
     212    }
     213  }
     214  return TRUE;
    210215}
    211216
     
    213218parse_filename(mrb_state *mrb, char **sp, listcmd_parser_state *st)
    214219{
    215         char *p;
    216         int len;
    217 
    218         if (st->filename != NULL) {
    219                 mrb_free(mrb, st->filename);
    220                 st->filename = NULL;
    221         }
    222 
    223         if ((p = strchr(*sp, ':')) != NULL) {
    224                 len = p - *sp;
    225         }
    226         else {
    227                 len = strlen(*sp);
    228         }
    229 
    230         if (len > 0) {
    231                 st->filename = mrb_malloc(mrb, len + 1);
    232                 strlcpy(st->filename, *sp, len + 1);
    233                 st->filename[len] = '\0';
    234                 *sp += len;
    235                 return TRUE;
    236         }
    237         else {
    238                 return FALSE;
    239         }
     220  char *p;
     221  int len;
     222
     223  if (st->filename != NULL) {
     224    mrb_free(mrb, st->filename);
     225    st->filename = NULL;
     226  }
     227
     228  if ((p = strchr(*sp, ':')) != NULL) {
     229    len = p - *sp;
     230  }
     231  else {
     232    len = strlen(*sp);
     233  }
     234
     235  if (len > 0) {
     236    st->filename = (char*)mrb_malloc(mrb, len + 1);
     237    strncpy(st->filename, *sp, len);
     238    st->filename[len] = '\0';
     239    *sp += len;
     240    return TRUE;
     241  }
     242  else {
     243    return FALSE;
     244  }
    240245}
    241246
     
    243248replace_ext(mrb_state *mrb, const char *filename, const char *ext)
    244249{
    245         size_t len, len2;
    246         const char *p;
    247         char *s;
    248 
    249         if (filename == NULL) {
    250                 return NULL;
    251         }
    252 
    253         if ((p = strrchr(filename, '.')) != NULL && strchr(p, '/') == NULL) {
    254                 len = p - filename;
    255         }
    256         else {
    257                 len = strlen(filename);
    258         }
    259 
    260         len2 = len + strlen(ext) + 1;
    261         s = mrb_malloc(mrb, len2);
    262         memset(s, '\0', len2);
    263         strlcpy(s, filename, len);
    264         strlcat(s, ext, len2);
    265 
    266         return s;
     250  size_t len;
     251  const char *p;
     252  char *s;
     253
     254  if (filename == NULL) {
     255    return NULL;
     256  }
     257
     258  if ((p = strrchr(filename, '.')) != NULL && strchr(p, '/') == NULL) {
     259    len = p - filename;
     260  }
     261  else {
     262    len = strlen(filename);
     263  }
     264
     265  s = (char*)mrb_malloc(mrb, len + strlen(ext) + 1);
     266  memset(s, '\0', len + strlen(ext) + 1);
     267  strncpy(s, filename, len);
     268  strcat(s, ext);
     269
     270  return s;
    267271}
    268272
     
    270274parse_listcmd_args(mrb_state *mrb, mrdb_state *mrdb, listcmd_parser_state *st)
    271275{
    272         char *p;
    273 
    274         switch (mrdb->wcnt) {
    275         case 2:
    276                 p = mrdb->words[1];
    277 
    278                 /* mrdb->words[1] ::= <lineno> | <filename> ':' <lineno> | <filename> */
    279                 if (!parse_lineno(mrb, &p, st)) {
    280                         if (parse_filename(mrb, &p, st)) {
    281                                 if (skip_char(&p, ':')) {
    282                                         if (!parse_lineno(mrb, &p, st)) {
    283                                                 st->parse_error = TRUE;
    284                                         }
    285                                 }
    286                         }
    287                         else {
    288                                 st->parse_error = TRUE;
    289                         }
    290                 }
    291                 if (*p != '\0') {
    292                         st->parse_error = TRUE;
    293                 }
    294                 break;
    295         case 1:
    296         case 0:
    297                 /* do nothing */
    298                 break;
    299         default:
    300                 st->parse_error = TRUE;
    301                 printf("too many arguments\n");
    302                 break;
    303         }
    304 
    305         if (!st->parse_error) {
    306                 if (!st->has_line_min) {
    307                         st->line_min = (!st->filename && mrdb->dbg->prvline > 0) ? mrdb->dbg->prvline : 1;
    308                 }
    309 
    310                 if (!st->has_line_max) {
    311                         st->line_max = st->line_min + 9;
    312                 }
    313 
    314                 if (st->filename == NULL) {
    315                         if (mrdb->dbg->prvfile && strcmp(mrdb->dbg->prvfile, "-")) {
    316                                 st->filename = replace_ext(mrb, mrdb->dbg->prvfile, ".rb");
    317                         }
    318                 }
    319         }
    320 
    321         if (st->parse_error || st->filename == NULL) {
    322                 return FALSE;
    323         }
    324 
    325         return TRUE;
     276  char *p;
     277
     278  switch (mrdb->wcnt) {
     279  case 2:
     280    p = mrdb->words[1];
     281
     282    /* mrdb->words[1] ::= <lineno> | <filename> ':' <lineno> | <filename> */
     283    if (!parse_lineno(mrb, &p, st)) {
     284      if (parse_filename(mrb, &p, st)) {
     285        if (skip_char(&p, ':')) {
     286          if (!parse_lineno(mrb, &p, st)) {
     287            st->parse_error = TRUE;
     288          }
     289        }
     290      }
     291      else {
     292        st->parse_error = TRUE;
     293      }
     294    }
     295    if (*p != '\0') {
     296      st->parse_error = TRUE;
     297    }
     298    break;
     299  case 1:
     300  case 0:
     301    /* do nothing */
     302    break;
     303  default:
     304    st->parse_error = TRUE;
     305    printf("too many arguments\n");
     306    break;
     307  }
     308
     309  if (!st->parse_error) {
     310    if (!st->has_line_min) {
     311      st->line_min = (!st->filename && mrdb->dbg->prvline > 0) ? mrdb->dbg->prvline : 1;
     312    }
     313
     314    if (!st->has_line_max) {
     315      st->line_max = st->line_min + 9;
     316    }
     317
     318    if (st->filename == NULL) {
     319      if (mrdb->dbg->prvfile && strcmp(mrdb->dbg->prvfile, "-")) {
     320        st->filename = replace_ext(mrb, mrdb->dbg->prvfile, ".rb");
     321      }
     322    }
     323  }
     324
     325  if (st->parse_error || st->filename == NULL) {
     326    return FALSE;
     327  }
     328
     329  return TRUE;
    326330}
    327331
     
    329333check_cmd_pattern(const char *pattern, const char *cmd)
    330334{
    331         const char *lbracket, *rbracket, *p, *q;
    332 
    333         if (pattern == NULL && cmd == NULL) {
    334                 return TRUE;
    335         }
    336         if (pattern == NULL || cmd == NULL) {
    337                 return FALSE;
    338         }
    339         if ((lbracket = strchr(pattern, '[')) == NULL) {
    340                 return !strcmp(pattern, cmd);
    341         }
    342         if ((rbracket = strchr(pattern, ']')) == NULL) {
    343                 return FALSE;
    344         }
    345         if (strncmp(pattern, cmd, lbracket - pattern)) {
    346                 return FALSE;
    347         }
    348 
    349         p = lbracket + 1;
    350         q = (char *)cmd + (lbracket - pattern);
    351 
    352         for (; p < rbracket && *q != '\0'; p++, q++) {
    353                 if (*p != *q) {
    354                         break;
    355                 }
    356         }
    357         return *q == '\0';
     335  const char *lbracket, *rbracket, *p, *q;
     336
     337  if (pattern == NULL && cmd == NULL) {
     338    return TRUE;
     339  }
     340  if (pattern == NULL || cmd == NULL) {
     341    return FALSE;
     342  }
     343  if ((lbracket = strchr(pattern, '[')) == NULL) {
     344    return !strcmp(pattern, cmd);
     345  }
     346  if ((rbracket = strchr(pattern, ']')) == NULL) {
     347    return FALSE;
     348  }
     349  if (strncmp(pattern, cmd, lbracket - pattern)) {
     350    return FALSE;
     351  }
     352
     353  p = lbracket + 1;
     354  q = (char *)cmd + (lbracket - pattern);
     355
     356  for ( ; p < rbracket && *q != '\0'; p++, q++) {
     357    if (*p != *q) {
     358      break;
     359    }
     360  }
     361  return *q == '\0';
    358362}
    359363
     
    361365get_help_msg(char *cmd1, char *cmd2)
    362366{
    363         help_msg *p;
    364 
    365         if (cmd1 == NULL) {
    366                 return NULL;
    367         }
    368         for (p = help_msg_list; p->cmd1 != NULL; p++) {
    369                 if (check_cmd_pattern(p->cmd1, cmd1) && check_cmd_pattern(p->cmd2, cmd2)) {
    370                         return p;
    371                 }
    372         }
    373         return NULL;
     367  help_msg *p;
     368
     369  if (cmd1 == NULL) {
     370    return NULL;
     371  }
     372  for (p = help_msg_list; p->cmd1 != NULL; p++) {
     373    if (check_cmd_pattern(p->cmd1, cmd1) && check_cmd_pattern(p->cmd2, cmd2)) {
     374      return p;
     375    }
     376  }
     377  return NULL;
    374378}
    375379
     
    377381show_short_help(void)
    378382{
    379         help_msg *p;
    380 
    381         printf("Commands\n");
    382 
    383         for (p = help_msg_list; p->cmd1 != NULL; p++) {
    384                 if (p->cmd2 == NULL) {
    385                         printf("  %s -- %s\n", p->cmd1, p->short_msg);
    386                 }
    387                 else {
    388                         printf("  %s %s -- %s\n", p->cmd1, p->cmd2, p->short_msg);
    389                 }
    390         }
    391         return TRUE;
     383  help_msg *p;
     384
     385  printf("Commands\n");
     386
     387  for (p = help_msg_list; p->cmd1 != NULL; p++) {
     388    if (p->cmd2 == NULL) {
     389      printf("  %s -- %s\n", p->cmd1, p->short_msg);
     390    }
     391    else {
     392      printf("  %s %s -- %s\n", p->cmd1, p->cmd2, p->short_msg);
     393    }
     394  }
     395  return TRUE;
    392396}
    393397
     
    395399show_long_help(char *cmd1, char *cmd2)
    396400{
    397         help_msg *help;
    398 
    399         if ((help = get_help_msg(cmd1, cmd2)) == NULL) {
    400                 return FALSE;
    401         }
    402         printf("%s", help->long_msg);
    403         return TRUE;
     401  help_msg *help;
     402
     403  if ((help = get_help_msg(cmd1, cmd2)) == NULL) {
     404    return FALSE;
     405  }
     406  printf("%s", help->long_msg);
     407  return TRUE;
     408}
     409
     410dbgcmd_state
     411dbgcmd_list(mrb_state *mrb, mrdb_state *mrdb)
     412{
     413  char *filename;
     414  listcmd_parser_state *st = listcmd_parser_state_new(mrb);
     415
     416  if (parse_listcmd_args(mrb, mrdb, st)) {
     417    if ((filename = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, st->filename)) == NULL) {
     418      filename = st->filename;
     419    }
     420    mrb_debug_list(mrb, mrdb->dbg, filename, st->line_min, st->line_max);
     421
     422    if (filename != NULL && filename != st->filename) {
     423      mrb_free(mrb, filename);
     424    }
     425    listcmd_parser_state_free(mrb, st);
     426  }
     427
     428  return DBGST_PROMPT;
    404429}
    405430
     
    407432dbgcmd_help(mrb_state *mrb, mrdb_state *mrdb)
    408433{
    409         mrb_bool is_valid;
    410         int i;
    411 
    412         switch (mrdb->wcnt) {
    413         case 0:
    414         case 1:
    415                 is_valid = show_short_help();
    416                 break;
    417         case 2:
    418                 is_valid = show_long_help(mrdb->words[1], NULL);
    419                 break;
    420         case 3:
    421                 is_valid = show_long_help(mrdb->words[1], mrdb->words[2]);
    422                 break;
    423         default:
    424                 is_valid = FALSE;
    425                 break;
    426         }
    427 
    428         if (!is_valid) {
    429                 printf("Invalid command \"");
    430                 for (i = 1; i < mrdb->wcnt; i++) {
    431                         printf("%s%s", i == 1 ? "" : " ", mrdb->words[i]);
    432                 }
    433                 printf("\". Try \"help\".\n");
    434         }
    435 
    436         return DBGST_PROMPT;
     434  mrb_bool is_valid;
     435  int i;
     436
     437  switch (mrdb->wcnt) {
     438  case 0:
     439  case 1:
     440    is_valid = show_short_help();
     441    break;
     442  case 2:
     443    is_valid = show_long_help(mrdb->words[1], NULL);
     444    break;
     445  case 3:
     446    is_valid = show_long_help(mrdb->words[1], mrdb->words[2]);
     447    break;
     448  default:
     449    is_valid = FALSE;
     450    break;
     451  }
     452
     453  if (!is_valid) {
     454    printf("Invalid command \"");
     455    for (i = 1; i < mrdb->wcnt; i++) {
     456      printf("%s%s", i == 1 ? "" : " ", mrdb->words[i]);
     457    }
     458    printf("\". Try \"help\".\n");
     459  }
     460
     461  return DBGST_PROMPT;
    437462}
    438463
     
    440465dbgcmd_quit(mrb_state *mrb, mrdb_state *mrdb)
    441466{
    442         switch (mrdb->dbg->xm) {
    443         case DBG_RUN:
    444         case DBG_STEP:
    445         case DBG_NEXT:
    446                 while (1) {
    447                         char c;
    448                         int buf;
    449 
    450                         printf("The program is running.  Exit anyway? (y or n) ");
    451                         fflush(stdout);
    452 
    453                         if ((buf = getchar()) == EOF) {
    454                                 InterlockedExchange(&mrdb->dbg->xm, DBG_QUIT);
    455                                 break;
    456                         }
    457                         c = buf;
    458                         while (buf != '\n' && (buf = getchar()) != EOF);
    459 
    460                         if (c == 'y' || c == 'Y') {
    461                                 InterlockedExchange(&mrdb->dbg->xm, DBG_QUIT);
    462                                 break;
    463                         }
    464                         else if (c == 'n' || c == 'N') {
    465                                 break;
    466                         }
    467                         else {
    468                                 printf("Please answer y or n.\n");
    469                         }
    470                 }
    471                 break;
    472         default:
    473                 InterlockedExchange(&mrdb->dbg->xm, DBG_QUIT);
    474                 break;
    475         }
    476 
    477         if (mrdb->dbg->xm == DBG_QUIT) {
    478                 struct RClass *exc;
    479                 exc = mrb_define_class(mrb, "DebuggerExit", mrb_class_get(mrb, "Exception"));
    480                 mrb_raise(mrb, exc, "Exit mrdb.");
    481         }
    482         return DBGST_PROMPT;
    483 }
     467  switch (mrdb->dbg->xm) {
     468  case DBG_RUN:
     469  case DBG_STEP:
     470  case DBG_NEXT:
     471    while (1) {
     472      char c;
     473      int buf;
     474
     475      printf("The program is running.  Exit anyway? (y or n) ");
     476      fflush(stdout);
     477
     478      if ((buf = getchar()) == EOF) {
     479        mrdb->dbg->xm = DBG_QUIT;
     480        break;
     481      }
     482      c = buf;
     483      while (buf != '\n' && (buf = getchar()) != EOF) ;
     484
     485      if (c == 'y' || c == 'Y') {
     486        mrdb->dbg->xm = DBG_QUIT;
     487        break;
     488      }
     489      else if (c == 'n' || c == 'N') {
     490        break;
     491      }
     492      else {
     493        printf("Please answer y or n.\n");
     494      }
     495    }
     496    break;
     497  default:
     498    mrdb->dbg->xm = DBG_QUIT;
     499    break;
     500  }
     501
     502  if (mrdb->dbg->xm == DBG_QUIT) {
     503    struct RClass *exc;
     504    exc = mrb_define_class(mrb, "DebuggerExit", mrb->eException_class);
     505    mrb_raise(mrb, exc, "Exit mrdb.");
     506  }
     507  return DBGST_PROMPT;
     508}
  • EcnlProtoTool/trunk/prototool/src/cmdprint.c

    r321 r439  
    44*/
    55
    6 #include <stdlib.h>
    7 
     6#include <string.h>
    87#include "mrdb.h"
    9 #include "mruby/value.h"
    10 #include "mruby/class.h"
    11 #include "mruby/compile.h"
    12 #include "mruby/error.h"
    13 #include "mruby/numeric.h"
    14 #include "mruby/string.h"
     8#include <mruby/value.h>
     9#include <mruby/class.h>
     10#include <mruby/compile.h>
     11#include <mruby/error.h>
     12#include <mruby/numeric.h>
     13#include <mruby/string.h>
    1514#include "apiprint.h"
    1615
     
    1817dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb)
    1918{
    20         mrb_value expr;
    21         mrb_value result;
    22         mrb_value s;
    23         uint8_t wcnt;
    24         int ai;
     19  mrb_value expr;
     20  mrb_value result;
     21  uint8_t wcnt;
     22  int ai;
    2523
    26         if (mrdb->wcnt <= 1) {
    27                 puts("Parameter not specified.");
    28                 return DBGST_PROMPT;
    29         }
     24  if (mrdb->wcnt <= 1) {
     25    puts("Parameter not specified.");
     26    return DBGST_PROMPT;
     27  }
    3028
    31         ai = mrb_gc_arena_save(mrb);
     29  ai = mrb_gc_arena_save(mrb);
    3230
    33         /* eval expr */
    34         expr = mrb_str_new_cstr(mrb, NULL);
    35         for (wcnt = 1; wcnt < mrdb->wcnt; wcnt++) {
    36                 expr = mrb_str_cat_lit(mrb, expr, " ");
    37                 expr = mrb_str_cat_cstr(mrb, expr, mrdb->words[wcnt]);
    38         }
     31  /* eval expr */
     32  expr = mrb_str_new_cstr(mrb, NULL);
     33  for (wcnt=1; wcnt<mrdb->wcnt; wcnt++) {
     34    expr = mrb_str_cat_lit(mrb, expr, " ");
     35    expr = mrb_str_cat_cstr(mrb, expr, mrdb->words[wcnt]);
     36  }
    3937
    40         result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL);
     38  result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL, 0);
    4139
    42         /* $print_no = result */
    43         s = mrb_str_cat_lit(mrb, result, "\0");
    44         printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
     40  /* $print_no = result */
     41  printf("$%lu = ", (unsigned long)mrdb->print_no++);
     42  fwrite(RSTRING_PTR(result), RSTRING_LEN(result), 1, stdout);
     43  putc('\n', stdout);
    4544
    46         if (mrdb->print_no == 0) {
    47                 mrdb->print_no = 1;
    48         }
     45  if (mrdb->print_no == 0) {
     46    mrdb->print_no = 1;
     47  }
    4948
    50         mrb_gc_arena_restore(mrb, ai);
     49  mrb_gc_arena_restore(mrb, ai);
    5150
    52         return DBGST_PROMPT;
     51  return DBGST_PROMPT;
    5352}
    5453
     
    5655dbgcmd_eval(mrb_state *mrb, mrdb_state *mrdb)
    5756{
    58         return dbgcmd_print(mrb, mrdb);
     57  return dbgcmd_print(mrb, mrdb);
    5958}
     59
     60dbgcmd_state
     61dbgcmd_info_local(mrb_state *mrb, mrdb_state *mrdb)
     62{
     63  mrb_value result;
     64  mrb_value s;
     65  int ai;
     66
     67  ai = mrb_gc_arena_save(mrb);
     68
     69  result = mrb_debug_eval(mrb, mrdb->dbg, "local_variables", 0, NULL, 1);
     70
     71  s = mrb_str_cat_lit(mrb, result, "\0");
     72  printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
     73
     74  if (mrdb->print_no == 0) {
     75    mrdb->print_no = 1;
     76  }
     77
     78  mrb_gc_arena_restore(mrb, ai);
     79
     80  return DBGST_PROMPT;
     81}
  • EcnlProtoTool/trunk/prototool/src/cmdrun.c

    r321 r439  
    44*/
    55
    6 #include <stdlib.h>
    7 
    8 #include "mruby/opcode.h"
     6#include <mruby/opcode.h>
    97#include "mrdb.h"
    108
     
    1210dbgcmd_run(mrb_state *mrb, mrdb_state *mrdb)
    1311{
    14         mrb_debug_context *dbg = mrdb->dbg;
     12  mrb_debug_context *dbg = mrdb->dbg;
    1513
    16         if (dbg->xm == DBG_INIT) {
    17                 InterlockedExchange(&dbg->xm, DBG_RUN);
    18         }
    19         else {
    20                 InterlockedExchange(&dbg->xm, DBG_QUIT);
    21                 if (dbg->xphase == DBG_PHASE_RUNNING) {
    22                         struct RClass *exc;
    23                         puts("Start it from the beginning.");
    24                         exc = mrb_define_class(mrb, "DebuggerRestart", mrb_class_get(mrb, "Exception"));
    25                         mrb_raise(mrb, exc, "Restart mrdb.");
    26                 }
    27         }
     14  if (dbg->xm == DBG_INIT){
     15    dbg->xm = DBG_RUN;
     16  }
     17  else {
     18    dbg->xm = DBG_QUIT;
     19    if (dbg->xphase == DBG_PHASE_RUNNING){
     20      struct RClass *exc;
     21      puts("Start it from the beginning.");
     22      exc = mrb_define_class(mrb, "DebuggerRestart", mrb->eException_class);
     23      mrb_raise(mrb, exc, "Restart mrdb.");
     24    }
     25  }
    2826
    29         return DBGST_RESTART;
     27  return DBGST_RESTART;
    3028}
    3129
     
    3331dbgcmd_continue(mrb_state *mrb, mrdb_state *mrdb)
    3432{
    35         mrb_debug_context *dbg = mrdb->dbg;
    36         int ccnt = 1;
     33  mrb_debug_context *dbg = mrdb->dbg;
     34  int ccnt = 1;
    3735
    38         if (mrdb->wcnt > 1) {
    39                 sscanf(mrdb->words[1], "%d", &ccnt);
    40         }
    41         dbg->ccnt = (uint16_t)(ccnt > 0 ? ccnt : 1);  /* count of continue */
     36  if (mrdb->wcnt > 1){
     37    sscanf(mrdb->words[1], "%d", &ccnt);
     38  }
     39  dbg->ccnt = (uint16_t)(ccnt > 0 ? ccnt : 1);  /* count of continue */
    4240
    43         if (dbg->xphase == DBG_PHASE_AFTER_RUN) {
    44                 puts("The program is not running.");
    45                 InterlockedExchange(&dbg->xm, DBG_QUIT);
    46         }
    47         else {
    48                 InterlockedExchange(&dbg->xm, DBG_RUN);
    49         }
    50         return DBGST_CONTINUE;
     41  if (dbg->xphase == DBG_PHASE_AFTER_RUN){
     42    puts("The program is not running.");
     43    dbg->xm = DBG_QUIT;
     44  }
     45  else {
     46    dbg->xm = DBG_RUN;
     47  }
     48  return DBGST_CONTINUE;
    5149}
    5250
     
    5452dbgcmd_step(mrb_state *mrb, mrdb_state *mrdb)
    5553{
    56         InterlockedExchange(&mrdb->dbg->xm, DBG_STEP);
    57         return DBGST_CONTINUE;
     54  mrdb->dbg->xm = DBG_STEP;
     55  return DBGST_CONTINUE;
    5856}
    5957
     
    6159dbgcmd_next(mrb_state *mrb, mrdb_state *mrdb)
    6260{
    63         InterlockedExchange(&mrdb->dbg->xm, DBG_NEXT);
    64         mrdb->dbg->prvci = mrb->c->ci;
    65         return DBGST_CONTINUE;
     61  mrdb->dbg->xm = DBG_NEXT;
     62  mrdb->dbg->prvci = mrb->c->ci;
     63  return DBGST_CONTINUE;
    6664}
  • EcnlProtoTool/trunk/prototool/src/libbb/AUTHORS

    • Property svn:eol-style set to native
  • EcnlProtoTool/trunk/prototool/src/libbb/LICENSE

    • Property svn:eol-style set to native
  • EcnlProtoTool/trunk/prototool/src/libbb/README

    • Property svn:eol-style set to native
  • EcnlProtoTool/trunk/prototool/src/linker_scriptDebug.ld

    • Property svn:eol-style set to native
  • EcnlProtoTool/trunk/prototool/src/main.c

    r428 r439  
    11/*
    2  *  TOPPERS ECHONET Lite Communication Middleware
     2 *  TOPPERS PROJECT Home Network Working Group Software
    33 *
    4  *  Copyright (C) 2014-2017 Cores Co., Ltd. Japan
     4 *  Copyright (C) 2017-2019 Cores Co., Ltd. Japan
    55 *
    66 *  上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
     
    515515}
    516516
     517extern char __start_rodata, __end_rodata;
     518
     519mrb_bool mrb_ro_data_p(const char *p)
     520{
     521        return (&__start_rodata <= p && p < &__end_rodata);
     522}
     523
    517524void _start_c(long *p);
    518525extern int __start_idata, __start_data, __end_data;
  • EcnlProtoTool/trunk/prototool/src/mirb.c

    r321 r439  
    77*/
    88
     9#include <mruby.h>
     10
     11#ifdef MRB_DISABLE_STDIO
     12# error mruby-bin-mirb conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     13#endif
     14
     15#include <mruby/array.h>
     16#include <mruby/proc.h>
     17#include <mruby/compile.h>
     18#include <mruby/dump.h>
     19#include <mruby/string.h>
     20#include <mruby/variable.h>
     21#include <mruby/throw.h>
     22
    923#include <stdlib.h>
    1024#include <string.h>
    11 #include <stdio.h>
    1225#include <ctype.h>
     26
     27#include <signal.h>
     28#include <setjmp.h>
    1329
    1430#ifdef ENABLE_READLINE
     
    1733#define MIRB_ADD_HISTORY(line) add_history(line)
    1834#define MIRB_READLINE(ch) readline(ch)
     35#if !defined(RL_READLINE_VERSION) || RL_READLINE_VERSION < 0x600
     36/* libedit & older readline do not have rl_free() */
     37#define MIRB_LINE_FREE(line) free(line)
     38#else
     39#define MIRB_LINE_FREE(line) rl_free(line)
     40#endif
    1941#define MIRB_WRITE_HISTORY(path) write_history(path)
    2042#define MIRB_READ_HISTORY(path) read_history(path)
     
    2547#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
    2648#define MIRB_READLINE(ch) linenoise(ch)
     49#define MIRB_LINE_FREE(line) linenoiseFree(line)
    2750#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
    2851#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
     
    3053#endif
    3154
    32 #include "mruby.h"
    33 #include "mruby/array.h"
    34 #include "mruby/proc.h"
    35 #include "mruby/compile.h"
    36 #include "mruby/string.h"
     55#ifndef _WIN32
     56#define MIRB_SIGSETJMP(env) sigsetjmp(env, 1)
     57#define MIRB_SIGLONGJMP(env, val) siglongjmp(env, val)
     58#define SIGJMP_BUF sigjmp_buf
     59#else
     60#define MIRB_SIGSETJMP(env) setjmp(env)
     61#define MIRB_SIGLONGJMP(env, val) longjmp(env, val)
     62#define SIGJMP_BUF jmp_buf
     63#endif
    3764
    3865#ifdef ENABLE_READLINE
     
    4370get_history_path(mrb_state *mrb)
    4471{
    45         char *path = NULL;
    46         const char *home = getenv("HOME");
     72  char *path = NULL;
     73  const char *home = getenv("HOME");
    4774
    4875#ifdef _WIN32
    49         if (home != NULL) {
    50                 home = getenv("USERPROFILE");
    51         }
    52 #endif
    53 
    54         if (home != NULL) {
    55                 int len = snprintf(NULL, 0, "%s/%s", home, history_file_name);
    56                 if (len >= 0) {
    57                         size_t size = len + 1;
    58                         path = (char *)mrb_malloc_simple(mrb, size);
    59                         if (path != NULL) {
    60                                 int n = snprintf(path, size, "%s/%s", home, history_file_name);
    61                                 if (n != len) {
    62                                         mrb_free(mrb, path);
    63                                         path = NULL;
    64                                 }
    65                         }
    66                 }
    67         }
    68 
    69         return path;
     76  if (home != NULL) {
     77    home = getenv("USERPROFILE");
     78  }
     79#endif
     80
     81  if (home != NULL) {
     82    int len = snprintf(NULL, 0, "%s/%s", home, history_file_name);
     83    if (len >= 0) {
     84      size_t size = len + 1;
     85      path = (char *)mrb_malloc_simple(mrb, size);
     86      if (path != NULL) {
     87        int n = snprintf(path, size, "%s/%s", home, history_file_name);
     88        if (n != len) {
     89          mrb_free(mrb, path);
     90          path = NULL;
     91        }
     92      }
     93    }
     94  }
     95
     96  return path;
    7097}
    7198
     
    75102p(mrb_state *mrb, mrb_value obj, int prompt)
    76103{
    77         mrb_value val;
    78 
    79         val = mrb_funcall(mrb, obj, "inspect", 0);
    80         if (prompt) {
    81                 if (!mrb->exc) {
    82                         fputs(" => ", stdout);
    83                 }
    84                 else {
    85                         val = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
    86                 }
    87         }
    88         if (!mrb_string_p(val)) {
    89                 val = mrb_obj_as_string(mrb, obj);
    90         }
    91         fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
    92         putc('\n', stdout);
     104  mrb_value val;
     105  char* msg;
     106
     107  val = mrb_funcall(mrb, obj, "inspect", 0);
     108  if (prompt) {
     109    if (!mrb->exc) {
     110      fputs(" => ", stdout);
     111    }
     112    else {
     113      val = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
     114    }
     115  }
     116  if (!mrb_string_p(val)) {
     117    val = mrb_obj_as_string(mrb, obj);
     118  }
     119  msg = mrb_locale_from_utf8(RSTRING_PTR(val), (int)RSTRING_LEN(val));
     120  fwrite(msg, strlen(msg), 1, stdout);
     121  mrb_locale_free(msg);
     122  putc('\n', stdout);
    93123}
    94124
     
    98128is_code_block_open(struct mrb_parser_state *parser)
    99129{
    100         mrb_bool code_block_open = FALSE;
    101 
    102         /* check for heredoc */
    103         if (parser->parsing_heredoc != NULL) return TRUE;
    104         if (parser->heredoc_end_now) {
    105                 parser->heredoc_end_now = FALSE;
    106                 return FALSE;
    107         }
    108 
    109         /* check for unterminated string */
    110         if (parser->lex_strterm) return TRUE;
    111 
    112         /* check if parser error are available */
    113         if (0 < parser->nerr) {
    114                 const char unexpected_end[] = "syntax error, unexpected $end";
    115                 const char *message = parser->error_buffer[0].message;
    116 
    117                 /* a parser error occur, we have to check if */
    118                 /* we need to read one more line or if there is */
    119                 /* a different issue which we have to show to */
    120                 /* the user */
    121 
    122                 if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) {
    123                         code_block_open = TRUE;
    124                 }
    125                 else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) {
    126                         code_block_open = FALSE;
    127                 }
    128                 else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) {
    129                         code_block_open = FALSE;
    130                 }
    131                 return code_block_open;
    132         }
    133 
    134         switch (parser->lstate) {
    135 
    136         /* all states which need more code */
    137 
    138         case EXPR_BEG:
    139           /* beginning of a statement, */
    140           /* that means previous line ended */
    141                 code_block_open = FALSE;
    142                 break;
    143         case EXPR_DOT:
    144           /* a message dot was the last token, */
    145           /* there has to come more */
    146                 code_block_open = TRUE;
    147                 break;
    148         case EXPR_CLASS:
    149           /* a class keyword is not enough! */
    150           /* we need also a name of the class */
    151                 code_block_open = TRUE;
    152                 break;
    153         case EXPR_FNAME:
    154           /* a method name is necessary */
    155                 code_block_open = TRUE;
    156                 break;
    157         case EXPR_VALUE:
    158           /* if, elsif, etc. without condition */
    159                 code_block_open = TRUE;
    160                 break;
    161 
    162           /* now all the states which are closed */
    163 
    164         case EXPR_ARG:
    165           /* an argument is the last token */
    166                 code_block_open = FALSE;
    167                 break;
    168 
    169           /* all states which are unsure */
    170 
    171         case EXPR_CMDARG:
    172                 break;
    173         case EXPR_END:
    174           /* an expression was ended */
    175                 break;
    176         case EXPR_ENDARG:
    177           /* closing parenthese */
    178                 break;
    179         case EXPR_ENDFN:
    180           /* definition end */
    181                 break;
    182         case EXPR_MID:
    183           /* jump keyword like break, return, ... */
    184                 break;
    185         case EXPR_MAX_STATE:
    186           /* don't know what to do with this token */
    187                 break;
    188         default:
    189           /* this state is unexpected! */
    190                 break;
    191         }
    192 
    193         return code_block_open;
     130  mrb_bool code_block_open = FALSE;
     131
     132  /* check for heredoc */
     133  if (parser->parsing_heredoc != NULL) return TRUE;
     134
     135  /* check for unterminated string */
     136  if (parser->lex_strterm) return TRUE;
     137
     138  /* check if parser error are available */
     139  if (0 < parser->nerr) {
     140    const char unexpected_end[] = "syntax error, unexpected $end";
     141    const char *message = parser->error_buffer[0].message;
     142
     143    /* a parser error occur, we have to check if */
     144    /* we need to read one more line or if there is */
     145    /* a different issue which we have to show to */
     146    /* the user */
     147
     148    if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) {
     149      code_block_open = TRUE;
     150    }
     151    else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) {
     152      code_block_open = FALSE;
     153    }
     154    else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) {
     155      code_block_open = FALSE;
     156    }
     157    return code_block_open;
     158  }
     159
     160  switch (parser->lstate) {
     161
     162  /* all states which need more code */
     163
     164  case EXPR_BEG:
     165    /* beginning of a statement, */
     166    /* that means previous line ended */
     167    code_block_open = FALSE;
     168    break;
     169  case EXPR_DOT:
     170    /* a message dot was the last token, */
     171    /* there has to come more */
     172    code_block_open = TRUE;
     173    break;
     174  case EXPR_CLASS:
     175    /* a class keyword is not enough! */
     176    /* we need also a name of the class */
     177    code_block_open = TRUE;
     178    break;
     179  case EXPR_FNAME:
     180    /* a method name is necessary */
     181    code_block_open = TRUE;
     182    break;
     183  case EXPR_VALUE:
     184    /* if, elsif, etc. without condition */
     185    code_block_open = TRUE;
     186    break;
     187
     188  /* now all the states which are closed */
     189
     190  case EXPR_ARG:
     191    /* an argument is the last token */
     192    code_block_open = FALSE;
     193    break;
     194
     195  /* all states which are unsure */
     196
     197  case EXPR_CMDARG:
     198    break;
     199  case EXPR_END:
     200    /* an expression was ended */
     201    break;
     202  case EXPR_ENDARG:
     203    /* closing parenthese */
     204    break;
     205  case EXPR_ENDFN:
     206    /* definition end */
     207    break;
     208  case EXPR_MID:
     209    /* jump keyword like break, return, ... */
     210    break;
     211  case EXPR_MAX_STATE:
     212    /* don't know what to do with this token */
     213    break;
     214  default:
     215    /* this state is unexpected! */
     216    break;
     217  }
     218
     219  return code_block_open;
    194220}
    195221
    196222struct _args {
    197         mrb_bool verbose : 1;
    198         int argc;
    199         char** argv;
     223  FILE *rfp;
     224  mrb_bool verbose      : 1;
     225  mrb_bool debug        : 1;
     226  int argc;
     227  char** argv;
     228  int libc;
     229  char **libv;
    200230};
    201231
     
    203233usage(const char *name)
    204234{
    205         static const char *const usage_msg[] = {
    206                 "switches:",
    207                 "-v           print version number, then run in verbose mode",
    208                 "--verbose    run in verbose mode",
    209                 "--version    print the version",
    210                 "--copyright  print the copyright",
    211                 NULL
    212         };
    213         const char *const *p = usage_msg;
    214 
    215         printf("Usage: %s [switches]\n", name);
    216         while (*p)
    217                 printf("  %s\n", *p++);
     235  static const char *const usage_msg[] = {
     236  "switches:",
     237  "-d           set $DEBUG to true (same as `mruby -d`)",
     238  "-r library   same as `mruby -r`",
     239  "-v           print version number, then run in verbose mode",
     240  "--verbose    run in verbose mode",
     241  "--version    print the version",
     242  "--copyright  print the copyright",
     243  NULL
     244  };
     245  const char *const *p = usage_msg;
     246
     247  printf("Usage: %s [switches] [programfile] [arguments]\n", name);
     248  while (*p)
     249    printf("  %s\n", *p++);
     250}
     251
     252static char *
     253dup_arg_item(mrb_state *mrb, const char *item)
     254{
     255  size_t buflen = strlen(item) + 1;
     256  char *buf = (char*)mrb_malloc(mrb, buflen);
     257  memcpy(buf, item, buflen);
     258  return buf;
    218259}
    219260
     
    221262parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
    222263{
    223         static const struct _args args_zero = {0};
    224 
    225         *args = args_zero;
    226 
    227         for (argc--, argv++; argc > 0; argc--, argv++) {
    228                 char *item;
    229                 if (argv[0][0] != '-') break;
    230 
    231                 item = argv[0] + 1;
    232                 switch (*item++) {
    233                 case 'v':
    234                         if (!args->verbose) mrb_show_version(mrb);
    235                         args->verbose = TRUE;
    236                         break;
    237                 case '-':
    238                         if (strcmp((*argv) + 2, "version") == 0) {
    239                                 mrb_show_version(mrb);
    240                                 exit(EXIT_SUCCESS);
    241                         }
    242                         else if (strcmp((*argv) + 2, "verbose") == 0) {
    243                                 args->verbose = TRUE;
    244                                 break;
    245                         }
    246                         else if (strcmp((*argv) + 2, "copyright") == 0) {
    247                                 mrb_show_copyright(mrb);
    248                                 exit(EXIT_SUCCESS);
    249                         }
    250                 default:
    251                         return EXIT_FAILURE;
    252                 }
    253         }
    254         return EXIT_SUCCESS;
     264  char **origargv = argv;
     265  static const struct _args args_zero = { 0 };
     266
     267  *args = args_zero;
     268
     269  for (argc--,argv++; argc > 0; argc--,argv++) {
     270    char *item;
     271    if (argv[0][0] != '-') break;
     272
     273    item = argv[0] + 1;
     274    switch (*item++) {
     275    case 'd':
     276      args->debug = TRUE;
     277      break;
     278    case 'r':
     279      if (!item[0]) {
     280        if (argc <= 1) {
     281          printf("%s: No library specified for -r\n", *origargv);
     282          return EXIT_FAILURE;
     283        }
     284        argc--; argv++;
     285        item = argv[0];
     286      }
     287      if (args->libc == 0) {
     288        args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
     289      }
     290      else {
     291        args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
     292      }
     293      args->libv[args->libc++] = dup_arg_item(mrb, item);
     294      break;
     295    case 'v':
     296      if (!args->verbose) mrb_show_version(mrb);
     297      args->verbose = TRUE;
     298      break;
     299    case '-':
     300      if (strcmp((*argv) + 2, "version") == 0) {
     301        mrb_show_version(mrb);
     302        exit(EXIT_SUCCESS);
     303      }
     304      else if (strcmp((*argv) + 2, "verbose") == 0) {
     305        args->verbose = TRUE;
     306        break;
     307      }
     308      else if (strcmp((*argv) + 2, "copyright") == 0) {
     309        mrb_show_copyright(mrb);
     310        exit(EXIT_SUCCESS);
     311      }
     312    default:
     313      return EXIT_FAILURE;
     314    }
     315  }
     316
     317  if (args->rfp == NULL) {
     318    if (*argv != NULL) {
     319      args->rfp = fopen(argv[0], "r");
     320      if (args->rfp == NULL) {
     321        printf("Cannot open program file. (%s)\n", *argv);
     322        return EXIT_FAILURE;
     323      }
     324      argc--; argv++;
     325    }
     326  }
     327  args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
     328  memcpy(args->argv, argv, (argc+1) * sizeof(char*));
     329  args->argc = argc;
     330
     331  return EXIT_SUCCESS;
    255332}
    256333
     
    258335cleanup(mrb_state *mrb, struct _args *args)
    259336{
    260         mrb_close(mrb);
     337  if (args->rfp)
     338    fclose(args->rfp);
     339  mrb_free(mrb, args->argv);
     340  if (args->libc) {
     341    while (args->libc--) {
     342      mrb_free(mrb, args->libv[args->libc]);
     343    }
     344    mrb_free(mrb, args->libv);
     345  }
     346  mrb_close(mrb);
    261347}
    262348
     
    265351print_hint(void)
    266352{
    267         printf("mirb - Embeddable Interactive Ruby Shell\n\n");
     353  printf("mirb - Embeddable Interactive Ruby Shell\n\n");
    268354}
    269355
     
    273359print_cmdline(int code_block_open)
    274360{
    275         if (code_block_open) {
    276                 printf("* ");
    277         }
    278         else {
    279                 printf("> ");
    280         }
    281         fflush(stdout);
     361  if (code_block_open) {
     362    printf("* ");
     363  }
     364  else {
     365    printf("> ");
     366  }
     367  fflush(stdout);
    282368}
    283369#endif
     
    288374check_keyword(const char *buf, const char *word)
    289375{
    290         const char *p = buf;
    291         size_t len = strlen(word);
    292 
    293         /* skip preceding spaces */
    294         while (*p && isspace((unsigned char)*p)) {
    295                 p++;
    296         }
    297         /* check keyword */
    298         if (strncmp(p, word, len) != 0) {
    299                 return 0;
    300         }
    301         p += len;
    302         /* skip trailing spaces */
    303         while (*p) {
    304                 if (!isspace((unsigned char)*p)) return 0;
    305                 p++;
    306         }
    307         return 1;
    308 }
     376  const char *p = buf;
     377  size_t len = strlen(word);
     378
     379  /* skip preceding spaces */
     380  while (*p && ISSPACE(*p)) {
     381    p++;
     382  }
     383  /* check keyword */
     384  if (strncmp(p, word, len) != 0) {
     385    return 0;
     386  }
     387  p += len;
     388  /* skip trailing spaces */
     389  while (*p) {
     390    if (!ISSPACE(*p)) return 0;
     391    p++;
     392  }
     393  return 1;
     394}
     395
     396
     397#ifndef ENABLE_READLINE
     398volatile sig_atomic_t input_canceled = 0;
     399void
     400ctrl_c_handler(int signo)
     401{
     402  input_canceled = 1;
     403}
     404#else
     405SIGJMP_BUF ctrl_c_buf;
     406void
     407ctrl_c_handler(int signo)
     408{
     409  MIRB_SIGLONGJMP(ctrl_c_buf, 1);
     410}
     411#endif
     412
     413#ifndef DISABLE_MIRB_UNDERSCORE
     414void decl_lv_underscore(mrb_state *mrb, mrbc_context *cxt)
     415{
     416  struct RProc *proc;
     417  struct mrb_parser_state *parser;
     418
     419  parser = mrb_parse_string(mrb, "_=nil", cxt);
     420  if (parser == NULL) {
     421    fputs("create parser state error\n", stderr);
     422    mrb_close(mrb);
     423    exit(EXIT_FAILURE);
     424  }
     425
     426  proc = mrb_generate_code(mrb, parser);
     427  mrb_vm_run(mrb, proc, mrb_top_self(mrb), 0);
     428
     429  mrb_parser_free(parser);
     430}
     431#endif
    309432
    310433int
    311434mirb_main(int argc, char **argv)
    312435{
    313         char ruby_code[1024] = {0};
    314         char last_code_line[1024] = {0};
     436  char ruby_code[4096] = { 0 };
     437  char last_code_line[1024] = { 0 };
    315438#ifndef ENABLE_READLINE
    316         int last_char;
    317         int char_index;
     439  int last_char;
     440  size_t char_index;
    318441#else
    319         char *history_path;
    320 #endif
    321         mrbc_context *cxt;
    322         struct mrb_parser_state *parser;
    323         mrb_state *mrb;
    324         mrb_value result;
    325         struct _args args;
    326         int n;
    327         mrb_bool code_block_open = FALSE;
    328         int ai;
    329         unsigned int stack_keep = 0;
    330 
    331         /* new interpreter instance */
    332         mrb = mrb_open();
    333         if (mrb == NULL) {
    334                 fputs("Invalid mrb interpreter, exiting mirb\n", stderr);
    335                 return EXIT_FAILURE;
    336         }
    337         mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0));
    338 
    339         n = parse_args(mrb, argc, argv, &args);
    340         if (n == EXIT_FAILURE) {
    341                 cleanup(mrb, &args);
    342                 usage(argv[0]);
    343                 return n;
    344         }
     442  char *history_path;
     443  char* line;
     444#endif
     445  mrbc_context *cxt;
     446  struct mrb_parser_state *parser;
     447  mrb_state *mrb;
     448  mrb_value result;
     449  struct _args args;
     450  mrb_value ARGV;
     451  int n;
     452  int i;
     453  mrb_bool code_block_open = FALSE;
     454  int ai;
     455  unsigned int stack_keep = 0;
     456
     457  /* new interpreter instance */
     458  mrb = mrb_open();
     459  if (mrb == NULL) {
     460    fputs("Invalid mrb interpreter, exiting mirb\n", stderr);
     461    return EXIT_FAILURE;
     462  }
     463
     464  n = parse_args(mrb, argc, argv, &args);
     465  if (n == EXIT_FAILURE) {
     466    cleanup(mrb, &args);
     467    usage(argv[0]);
     468    return n;
     469  }
     470
     471  ARGV = mrb_ary_new_capa(mrb, args.argc);
     472  for (i = 0; i < args.argc; i++) {
     473    char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
     474    if (utf8) {
     475      mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
     476      mrb_utf8_free(utf8);
     477    }
     478  }
     479  mrb_define_global_const(mrb, "ARGV", ARGV);
     480  mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
    345481
    346482#ifdef ENABLE_READLINE
    347         history_path = get_history_path(mrb);
    348         if (history_path == NULL) {
    349                 fputs("failed to get history path\n", stderr);
    350                 mrb_close(mrb);
    351                 return EXIT_FAILURE;
    352         }
    353 
    354         MIRB_USING_HISTORY();
    355         MIRB_READ_HISTORY(history_path);
    356 #endif
    357 
    358         print_hint();
    359 
    360         cxt = mrbc_context_new(mrb);
    361         cxt->capture_errors = TRUE;
    362         cxt->lineno = 1;
    363         mrbc_filename(mrb, cxt, "(mirb)");
    364         if (args.verbose) cxt->dump_result = TRUE;
    365 
    366         ai = mrb_gc_arena_save(mrb);
    367 
    368         while (TRUE) {
    369                 char *utf8;
     483  history_path = get_history_path(mrb);
     484  if (history_path == NULL) {
     485    fputs("failed to get history path\n", stderr);
     486    mrb_close(mrb);
     487    return EXIT_FAILURE;
     488  }
     489
     490  MIRB_USING_HISTORY();
     491  MIRB_READ_HISTORY(history_path);
     492#endif
     493
     494  print_hint();
     495
     496  cxt = mrbc_context_new(mrb);
     497
     498#ifndef DISABLE_MIRB_UNDERSCORE
     499  decl_lv_underscore(mrb, cxt);
     500#endif
     501
     502  /* Load libraries */
     503  for (i = 0; i < args.libc; i++) {
     504    FILE *lfp = fopen(args.libv[i], "r");
     505    if (lfp == NULL) {
     506      printf("Cannot open library file. (%s)\n", args.libv[i]);
     507      cleanup(mrb, &args);
     508      return EXIT_FAILURE;
     509    }
     510    mrb_load_file_cxt(mrb, lfp, cxt);
     511    fclose(lfp);
     512  }
     513
     514  cxt->capture_errors = TRUE;
     515  cxt->lineno = 1;
     516  mrbc_filename(mrb, cxt, "(mirb)");
     517  if (args.verbose) cxt->dump_result = TRUE;
     518
     519  ai = mrb_gc_arena_save(mrb);
     520
     521  while (TRUE) {
     522    char *utf8;
     523    struct mrb_jmpbuf c_jmp;
     524
     525    MRB_TRY(&c_jmp);
     526    mrb->jmp = &c_jmp;
     527    if (args.rfp) {
     528      if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL)
     529        goto done;
     530      break;
     531    }
    370532
    371533#ifndef ENABLE_READLINE
    372                 print_cmdline(code_block_open);
    373 
    374                 char_index = 0;
    375                 while ((last_char = getchar()) != '\n') {
    376                         if (last_char == EOF) break;
    377                         if (char_index > sizeof(last_code_line) - 2) {
    378                                 fputs("input string too long\n", stderr);
    379                                 continue;
    380                         }
    381                         last_code_line[char_index++] = last_char;
    382                 }
    383                 if (last_char == EOF) {
    384                         fputs("\n", stdout);
    385                         break;
    386                 }
    387 
    388                 last_code_line[char_index++] = '\n';
    389                 last_code_line[char_index] = '\0';
     534    print_cmdline(code_block_open);
     535
     536    signal(SIGINT, ctrl_c_handler);
     537    char_index = 0;
     538    while ((last_char = getchar()) != '\n') {
     539      if (last_char == EOF) break;
     540      if (char_index >= sizeof(last_code_line)-2) {
     541        fputs("input string too long\n", stderr);
     542        continue;
     543      }
     544      last_code_line[char_index++] = last_char;
     545    }
     546    signal(SIGINT, SIG_DFL);
     547    if (input_canceled) {
     548      ruby_code[0] = '\0';
     549      last_code_line[0] = '\0';
     550      code_block_open = FALSE;
     551      puts("^C");
     552      input_canceled = 0;
     553      continue;
     554    }
     555    if (last_char == EOF) {
     556      fputs("\n", stdout);
     557      break;
     558    }
     559
     560    last_code_line[char_index++] = '\n';
     561    last_code_line[char_index] = '\0';
    390562#else
    391                 char* line = MIRB_READLINE(code_block_open ? "* " : "> ");
    392                 if (line == NULL) {
    393                         printf("\n");
    394                         break;
    395                 }
    396                 if (strlen(line) > sizeof(last_code_line) - 2) {
    397                         fputs("input string too long\n", stderr);
    398                         continue;
    399                 }
    400                 strlcpy(last_code_line, line, sizeof(last_code_line));
    401                 strlcat(last_code_line, "\n", sizeof(last_code_line));
    402                 MIRB_ADD_HISTORY(line);
    403                 free(line);
    404 #endif
    405 
    406                 if (code_block_open) {
    407                         if (strlen(ruby_code) + strlen(last_code_line) > sizeof(ruby_code) - 1) {
    408                                 fputs("concatenated input string too long\n", stderr);
    409                                 continue;
    410                         }
    411                         strlcat(ruby_code, last_code_line, sizeof(ruby_code));
    412                 }
    413                 else {
    414                         if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) {
    415                                 break;
    416                         }
    417                         strlcpy(ruby_code, last_code_line, sizeof(ruby_code));
    418                 }
    419 
    420                 utf8 = mrb_utf8_from_locale(ruby_code, -1);
    421                 if (!utf8) abort();
    422 
    423                 /* parse code */
    424                 parser = mrb_parser_new(mrb);
    425                 if (parser == NULL) {
    426                         fputs("create parser state error\n", stderr);
    427                         break;
    428                 }
    429                 parser->s = utf8;
    430                 parser->send = utf8 + strlen(utf8);
    431                 parser->lineno = cxt->lineno;
    432                 mrb_parser_parse(parser, cxt);
    433                 code_block_open = is_code_block_open(parser);
    434                 mrb_utf8_free(utf8);
    435 
    436                 if (code_block_open) {
    437                   /* no evaluation of code */
    438                 }
    439                 else {
    440                         if (0 < parser->nerr) {
    441                           /* syntax error */
    442                                 printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
    443                         }
    444                         else {
    445                           /* generate bytecode */
    446                                 struct RProc *proc = mrb_generate_code(mrb, parser);
    447                                 if (proc == NULL) {
    448                                         fputs("codegen error\n", stderr);
    449                                         mrb_parser_free(parser);
    450                                         break;
    451                                 }
    452 
    453                                 if (args.verbose) {
    454                                         mrb_codedump_all(mrb, proc);
    455                                 }
    456                                 /* pass a proc for evaulation */
    457                                 /* evaluate the bytecode */
    458                                 result = mrb_context_run(mrb,
    459                                         proc,
    460                                         mrb_top_self(mrb),
    461                                         stack_keep);
    462                                 stack_keep = proc->body.irep->nlocals;
    463                                 /* did an exception occur? */
    464                                 if (mrb->exc) {
    465                                         p(mrb, mrb_obj_value(mrb->exc), 0);
    466                                         mrb->exc = 0;
    467                                 }
    468                                 else {
    469                                   /* no */
    470                                         if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))) {
    471                                                 result = mrb_any_to_s(mrb, result);
    472                                         }
    473                                         p(mrb, result, 1);
    474                                 }
    475                         }
    476                         ruby_code[0] = '\0';
    477                         last_code_line[0] = '\0';
    478                         mrb_gc_arena_restore(mrb, ai);
    479                 }
    480                 mrb_parser_free(parser);
    481                 cxt->lineno++;
    482         }
     563    if (MIRB_SIGSETJMP(ctrl_c_buf) == 0) {
     564      ;
     565    }
     566    else {
     567      ruby_code[0] = '\0';
     568      last_code_line[0] = '\0';
     569      code_block_open = FALSE;
     570      puts("^C");
     571    }
     572    signal(SIGINT, ctrl_c_handler);
     573    line = MIRB_READLINE(code_block_open ? "* " : "> ");
     574    signal(SIGINT, SIG_DFL);
     575
     576    if (line == NULL) {
     577      printf("\n");
     578      break;
     579    }
     580    if (strlen(line) > sizeof(last_code_line)-2) {
     581      fputs("input string too long\n", stderr);
     582      continue;
     583    }
     584    strcpy(last_code_line, line);
     585    strcat(last_code_line, "\n");
     586    MIRB_ADD_HISTORY(line);
     587    MIRB_LINE_FREE(line);
     588#endif
     589
     590  done:
     591    if (code_block_open) {
     592      if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
     593        fputs("concatenated input string too long\n", stderr);
     594        continue;
     595      }
     596      strcat(ruby_code, last_code_line);
     597    }
     598    else {
     599      if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) {
     600        break;
     601      }
     602      strcpy(ruby_code, last_code_line);
     603    }
     604
     605    utf8 = mrb_utf8_from_locale(ruby_code, -1);
     606    if (!utf8) abort();
     607
     608    /* parse code */
     609    parser = mrb_parser_new(mrb);
     610    if (parser == NULL) {
     611      fputs("create parser state error\n", stderr);
     612      break;
     613    }
     614    parser->s = utf8;
     615    parser->send = utf8 + strlen(utf8);
     616    parser->lineno = cxt->lineno;
     617    mrb_parser_parse(parser, cxt);
     618    code_block_open = is_code_block_open(parser);
     619    mrb_utf8_free(utf8);
     620
     621    if (code_block_open) {
     622      /* no evaluation of code */
     623    }
     624    else {
     625      if (0 < parser->nwarn) {
     626        /* warning */
     627        char* msg = mrb_locale_from_utf8(parser->warn_buffer[0].message, -1);
     628        printf("line %d: %s\n", parser->warn_buffer[0].lineno, msg);
     629        mrb_locale_free(msg);
     630      }
     631      if (0 < parser->nerr) {
     632        /* syntax error */
     633        char* msg = mrb_locale_from_utf8(parser->error_buffer[0].message, -1);
     634        printf("line %d: %s\n", parser->error_buffer[0].lineno, msg);
     635        mrb_locale_free(msg);
     636      }
     637      else {
     638        /* generate bytecode */
     639        struct RProc *proc = mrb_generate_code(mrb, parser);
     640        if (proc == NULL) {
     641          fputs("codegen error\n", stderr);
     642          mrb_parser_free(parser);
     643          break;
     644        }
     645
     646        if (args.verbose) {
     647          mrb_codedump_all(mrb, proc);
     648        }
     649        /* adjust stack length of toplevel environment */
     650        if (mrb->c->cibase->env) {
     651          struct REnv *e = mrb->c->cibase->env;
     652          if (e && MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals) {
     653            MRB_ENV_SET_STACK_LEN(e, proc->body.irep->nlocals);
     654          }
     655        }
     656        /* pass a proc for evaluation */
     657        /* evaluate the bytecode */
     658        result = mrb_vm_run(mrb,
     659            proc,
     660            mrb_top_self(mrb),
     661            stack_keep);
     662        stack_keep = proc->body.irep->nlocals;
     663        /* did an exception occur? */
     664        if (mrb->exc) {
     665          p(mrb, mrb_obj_value(mrb->exc), 0);
     666          mrb->exc = 0;
     667        }
     668        else {
     669          /* no */
     670          if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){
     671            result = mrb_any_to_s(mrb, result);
     672          }
     673          p(mrb, result, 1);
     674#ifndef DISABLE_MIRB_UNDERSCORE
     675          *(mrb->c->stack + 1) = result;
     676#endif
     677        }
     678      }
     679      ruby_code[0] = '\0';
     680      last_code_line[0] = '\0';
     681      mrb_gc_arena_restore(mrb, ai);
     682    }
     683    mrb_parser_free(parser);
     684    cxt->lineno++;
     685    MRB_CATCH(&c_jmp) {
     686      p(mrb, mrb_obj_value(mrb->exc), 0);
     687      mrb->exc = 0;
     688    }
     689    MRB_END_EXC(&c_jmp);
     690  }
    483691
    484692#ifdef ENABLE_READLINE
    485         MIRB_WRITE_HISTORY(history_path);
    486         mrb_free(mrb, history_path);
    487 #endif
    488 
    489         mrbc_context_free(mrb, cxt);
    490         mrb_close(mrb);
    491 
    492         return 0;
    493 }
     693  MIRB_WRITE_HISTORY(history_path);
     694  mrb_free(mrb, history_path);
     695#endif
     696
     697  if (args.rfp) fclose(args.rfp);
     698  mrb_free(mrb, args.argv);
     699  if (args.libv) {
     700    for (i = 0; i < args.libc; ++i) {
     701      mrb_free(mrb, args.libv[i]);
     702    }
     703    mrb_free(mrb, args.libv);
     704  }
     705  mrbc_context_free(mrb, cxt);
     706  mrb_close(mrb);
     707
     708  return 0;
     709}
  • EcnlProtoTool/trunk/prototool/src/mrbc.c

    r321 r439  
     1#include <mruby.h>
     2
     3#ifdef MRB_DISABLE_STDIO
     4# error mruby-bin-mrbc conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     5#endif
     6
    17#include <stdlib.h>
    2 
    3 #include "mruby.h"
    4 #include "mruby/compile.h"
    5 #include "mruby/dump.h"
    6 #include "mruby/proc.h"
     8#include <string.h>
     9#include <mruby/compile.h>
     10#include <mruby/dump.h>
     11#include <mruby/proc.h>
    712
    813#define RITEBIN_EXT ".mrb"
    914#define C_EXT       ".c"
    1015
    11 struct mrbc_args
    12 {
    13         int argc;
    14         char **argv;
    15         int idx;
    16         const char *prog;
    17         const char *outfile;
    18         const char *initname;
    19         mrb_bool check_syntax : 1;
    20         mrb_bool verbose : 1;
    21         unsigned int flags : 4;
     16struct mrbc_args {
     17  int argc;
     18  char **argv;
     19  int idx;
     20  const char *prog;
     21  const char *outfile;
     22  const char *initname;
     23  mrb_bool check_syntax : 1;
     24  mrb_bool verbose      : 1;
     25  mrb_bool remove_lv    : 1;
     26  unsigned int flags    : 4;
    2227};
    2328
     
    2530usage(const char *name)
    2631{
    27         static const char *const usage_msg[] = {
    28                 "switches:",
    29                 "-c           check syntax only",
    30                 "-o<outfile>  place the output into <outfile>",
    31                 "-v           print version number, then turn on verbose mode",
    32                 "-g           produce debugging information",
    33                 "-B<symbol>   binary <symbol> output in C language format",
    34                 "-e           generate little endian iseq data",
    35                 "-E           generate big endian iseq data",
    36                 "--verbose    run at verbose mode",
    37                 "--version    print the version",
    38                 "--copyright  print the copyright",
    39                 NULL
    40         };
    41         const char *const *p = usage_msg;
    42 
    43         printf("Usage: %s [switches] programfile\n", name);
    44         while (*p)
    45                 printf("  %s\n", *p++);
     32  static const char *const usage_msg[] = {
     33  "switches:",
     34  "-c           check syntax only",
     35  "-o<outfile>  place the output into <outfile>",
     36  "-v           print version number, then turn on verbose mode",
     37  "-g           produce debugging information",
     38  "-B<symbol>   binary <symbol> output in C language format",
     39  "-e           generate little endian iseq data",
     40  "-E           generate big endian iseq data",
     41  "--remove-lv  remove local variables",
     42  "--verbose    run at verbose mode",
     43  "--version    print the version",
     44  "--copyright  print the copyright",
     45  NULL
     46  };
     47  const char *const *p = usage_msg;
     48
     49  printf("Usage: %s [switches] programfile\n", name);
     50  while (*p)
     51    printf("  %s\n", *p++);
    4652}
    4753
     
    4955get_outfilename(mrb_state *mrb, char *infile, const char *ext)
    5056{
    51         size_t infilelen;
    52         size_t extlen;
    53         char *outfile;
    54         char *p;
    55 
    56         infilelen = strlen(infile);
    57         extlen = strlen(ext);
    58         outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1);
    59         memcpy(outfile, infile, infilelen + 1);
    60         if (*ext) {
    61                 if ((p = strrchr(outfile, '.')) == NULL)
    62                         p = outfile + infilelen;
    63                 memcpy(p, ext, extlen + 1);
    64         }
    65 
    66         return outfile;
     57  size_t infilelen;
     58  size_t extlen;
     59  char *outfile;
     60  char *p;
     61
     62  infilelen = strlen(infile);
     63  extlen = strlen(ext);
     64  outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1);
     65  memcpy(outfile, infile, infilelen + 1);
     66  if (*ext) {
     67    if ((p = strrchr(outfile, '.')) == NULL)
     68      p = outfile + infilelen;
     69    memcpy(p, ext, extlen + 1);
     70  }
     71
     72  return outfile;
    6773}
    6874
     
    7076parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
    7177{
    72         static const struct mrbc_args args_zero = { 0 };
    73         int i;
    74 
    75         *args = args_zero;
    76         args->argc = argc;
    77         args->argv = argv;
    78         args->prog = argv[0];
    79 
    80         for (i = 1; i < argc; i++) {
    81                 if (argv[i][0] == '-') {
    82                         switch ((argv[i])[1]) {
    83                         case 'o':
    84                                 if (args->outfile) {
    85                                         fprintf(stderr, "%s: an output file is already specified. (%s)\n",
    86                                                 args->prog, args->outfile);
    87                                         return -1;
    88                                 }
    89                                 if (argv[i][2] == '\0' && argv[i + 1]) {
    90                                         i++;
    91                                         args->outfile = get_outfilename(mrb, argv[i], "");
    92                                 }
    93                                 else {
    94                                         args->outfile = get_outfilename(mrb, argv[i] + 2, "");
    95                                 }
    96                                 break;
    97                         case 'B':
    98                                 if (argv[i][2] == '\0' && argv[i + 1]) {
    99                                         i++;
    100                                         args->initname = argv[i];
    101                                 }
    102                                 else {
    103                                         args->initname = argv[i] + 2;
    104                                 }
    105                                 if (*args->initname == '\0') {
    106                                         fprintf(stderr, "%s: function name is not specified.\n", args->prog);
    107                                         return -1;
    108                                 }
    109                                 break;
    110                         case 'c':
    111                                 args->check_syntax = TRUE;
    112                                 break;
    113                         case 'v':
    114                                 if (!args->verbose) mrb_show_version(mrb);
    115                                 args->verbose = TRUE;
    116                                 break;
    117                         case 'g':
    118                                 args->flags |= DUMP_DEBUG_INFO;
    119                                 break;
    120                         case 'E':
    121                                 args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
    122                                 break;
    123                         case 'e':
    124                                 args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
    125                                 break;
    126                         case 'h':
    127                                 return -1;
    128                         case '-':
    129                                 if (argv[i][1] == '\n') {
    130                                         return i;
    131                                 }
    132                                 if (strcmp(argv[i] + 2, "version") == 0) {
    133                                         mrb_show_version(mrb);
    134                                         exit(EXIT_SUCCESS);
    135                                 }
    136                                 else if (strcmp(argv[i] + 2, "verbose") == 0) {
    137                                         args->verbose = TRUE;
    138                                         break;
    139                                 }
    140                                 else if (strcmp(argv[i] + 2, "copyright") == 0) {
    141                                         mrb_show_copyright(mrb);
    142                                         exit(EXIT_SUCCESS);
    143                                 }
    144                                 return -1;
    145                         default:
    146                                 return i;
    147                         }
    148                 }
    149                 else {
    150                         break;
    151                 }
    152         }
    153         if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) {
    154                 fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n",
    155                         args->prog, bigendian_p() ? "big" : "little");
    156         }
    157         return i;
     78  static const struct mrbc_args args_zero = { 0 };
     79  int i;
     80
     81  *args = args_zero;
     82  args->argc = argc;
     83  args->argv = argv;
     84  args->prog = argv[0];
     85
     86  for (i=1; i<argc; i++) {
     87    if (argv[i][0] == '-') {
     88      switch ((argv[i])[1]) {
     89      case 'o':
     90        if (args->outfile) {
     91          fprintf(stderr, "%s: an output file is already specified. (%s)\n",
     92                  args->prog, args->outfile);
     93          return -1;
     94        }
     95        if (argv[i][2] == '\0' && argv[i+1]) {
     96          i++;
     97          args->outfile = get_outfilename(mrb, argv[i], "");
     98        }
     99        else {
     100          args->outfile = get_outfilename(mrb, argv[i] + 2, "");
     101        }
     102        break;
     103      case 'B':
     104        if (argv[i][2] == '\0' && argv[i+1]) {
     105          i++;
     106          args->initname = argv[i];
     107        }
     108        else {
     109          args->initname = argv[i]+2;
     110        }
     111        if (*args->initname == '\0') {
     112          fprintf(stderr, "%s: function name is not specified.\n", args->prog);
     113          return -1;
     114        }
     115        break;
     116      case 'c':
     117        args->check_syntax = TRUE;
     118        break;
     119      case 'v':
     120        if (!args->verbose) mrb_show_version(mrb);
     121        args->verbose = TRUE;
     122        break;
     123      case 'g':
     124        args->flags |= DUMP_DEBUG_INFO;
     125        break;
     126      case 'E':
     127        args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
     128        break;
     129      case 'e':
     130        args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
     131        break;
     132      case 'h':
     133        return -1;
     134      case '-':
     135        if (argv[i][1] == '\n') {
     136          return i;
     137        }
     138        if (strcmp(argv[i] + 2, "version") == 0) {
     139          mrb_show_version(mrb);
     140          exit(EXIT_SUCCESS);
     141        }
     142        else if (strcmp(argv[i] + 2, "verbose") == 0) {
     143          args->verbose = TRUE;
     144          break;
     145        }
     146        else if (strcmp(argv[i] + 2, "copyright") == 0) {
     147          mrb_show_copyright(mrb);
     148          exit(EXIT_SUCCESS);
     149        }
     150        else if (strcmp(argv[i] + 2, "remove-lv") == 0) {
     151          args->remove_lv = TRUE;
     152          break;
     153        }
     154        return -1;
     155      default:
     156        return i;
     157      }
     158    }
     159    else {
     160      break;
     161    }
     162  }
     163  if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) {
     164    fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n",
     165            args->prog, bigendian_p() ? "big" : "little");
     166  }
     167  return i;
    158168}
    159169
     
    161171cleanup(mrb_state *mrb, struct mrbc_args *args)
    162172{
    163         mrb_free(mrb, (void*)args->outfile);
    164         mrb_close(mrb);
     173  mrb_free(mrb, (void*)args->outfile);
     174  mrb_close(mrb);
    165175}
    166176
     
    168178partial_hook(struct mrb_parser_state *p)
    169179{
    170         mrbc_context *c = p->cxt;
    171         struct mrbc_args *args = (struct mrbc_args *)c->partial_data;
    172         const char *fn;
    173 
    174         if (p->f) fclose(p->f);
    175         if (args->idx >= args->argc) {
    176                 p->f = NULL;
    177                 return -1;
    178         }
    179         fn = args->argv[args->idx++];
    180         p->f = fopen(fn, "r");
    181         if (p->f == NULL) {
    182                 fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
    183                 return -1;
    184         }
    185         mrb_parser_set_filename(p, fn);
    186         return 0;
     180  mrbc_context *c = p->cxt;
     181  struct mrbc_args *args = (struct mrbc_args *)c->partial_data;
     182  const char *fn;
     183
     184  if (p->f) fclose(p->f);
     185  if (args->idx >= args->argc) {
     186    p->f = NULL;
     187    return -1;
     188  }
     189  fn = args->argv[args->idx++];
     190  p->f = fopen(fn, "rb");
     191  if (p->f == NULL) {
     192    fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
     193    return -1;
     194  }
     195  mrb_parser_set_filename(p, fn);
     196  return 0;
    187197}
    188198
     
    190200load_file(mrb_state *mrb, struct mrbc_args *args)
    191201{
    192         mrbc_context *c;
    193         mrb_value result;
    194         char *input = args->argv[args->idx];
    195         FILE *infile;
    196         mrb_bool need_close = FALSE;
    197 
    198         c = mrbc_context_new(mrb);
    199         if (args->verbose)
    200                 c->dump_result = TRUE;
    201         c->no_exec = TRUE;
    202         if (input[0] == '-' && input[1] == '\0') {
    203                 infile = stdin;
    204         }
    205         else {
    206                 need_close = TRUE;
    207                 if ((infile = fopen(input, "r")) == NULL) {
    208                         fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
    209                         return mrb_nil_value();
    210                 }
    211         }
    212         mrbc_filename(mrb, c, input);
    213         args->idx++;
    214         if (args->idx < args->argc) {
    215                 need_close = FALSE;
    216                 mrbc_partial_hook(mrb, c, partial_hook, (void*)args);
    217         }
    218 
    219         result = mrb_load_file_cxt(mrb, infile, c);
    220         if (need_close) fclose(infile);
    221         mrbc_context_free(mrb, c);
    222         if (mrb_undef_p(result)) {
    223                 return mrb_nil_value();
    224         }
    225         return result;
     202  mrbc_context *c;
     203  mrb_value result;
     204  char *input = args->argv[args->idx];
     205  FILE *infile;
     206  mrb_bool need_close = FALSE;
     207
     208  c = mrbc_context_new(mrb);
     209  if (args->verbose)
     210    c->dump_result = TRUE;
     211  c->no_exec = TRUE;
     212  if (input[0] == '-' && input[1] == '\0') {
     213    infile = stdin;
     214  }
     215  else {
     216    need_close = TRUE;
     217    if ((infile = fopen(input, "rb")) == NULL) {
     218      fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
     219      return mrb_nil_value();
     220    }
     221  }
     222  mrbc_filename(mrb, c, input);
     223  args->idx++;
     224  if (args->idx < args->argc) {
     225    need_close = FALSE;
     226    mrbc_partial_hook(mrb, c, partial_hook, (void*)args);
     227  }
     228
     229  result = mrb_load_file_cxt(mrb, infile, c);
     230  if (need_close) fclose(infile);
     231  mrbc_context_free(mrb, c);
     232  if (mrb_undef_p(result)) {
     233    return mrb_nil_value();
     234  }
     235  return result;
    226236}
    227237
     
    229239dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, struct mrbc_args *args)
    230240{
    231         int n = MRB_DUMP_OK;
    232         mrb_irep *irep = proc->body.irep;
    233 
    234         if (args->initname) {
    235                 n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
    236                 if (n == MRB_DUMP_INVALID_ARGUMENT) {
    237                         fprintf(stderr, "%s: invalid C language symbol name\n", args->initname);
    238                 }
    239         }
    240         else {
    241                 n = mrb_dump_irep_binary(mrb, irep, args->flags, wfp);
    242         }
    243         if (n != MRB_DUMP_OK) {
    244                 fprintf(stderr, "%s: error in mrb dump (%s) %d\n", args->prog, outfile, n);
    245         }
    246         return n;
     241  int n = MRB_DUMP_OK;
     242  mrb_irep *irep = proc->body.irep;
     243
     244  if (args->remove_lv) {
     245    mrb_irep_remove_lv(mrb, irep);
     246  }
     247  if (args->initname) {
     248    n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
     249    if (n == MRB_DUMP_INVALID_ARGUMENT) {
     250      fprintf(stderr, "%s: invalid C language symbol name\n", args->initname);
     251    }
     252  }
     253  else {
     254    n = mrb_dump_irep_binary(mrb, irep, args->flags, wfp);
     255  }
     256  if (n != MRB_DUMP_OK) {
     257    fprintf(stderr, "%s: error in mrb dump (%s) %d\n", args->prog, outfile, n);
     258  }
     259  return n;
    247260}
    248261
     
    250263mrbc_main(int argc, char **argv)
    251264{
    252         mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL, TRUE);
    253         int n, result;
    254         struct mrbc_args args;
    255         FILE *wfp;
    256         mrb_value load;
    257 
    258         if (mrb == NULL) {
    259                 fputs("Invalid mrb_state, exiting mrbc\n", stderr);
    260                 return EXIT_FAILURE;
    261         }
    262 
    263         n = parse_args(mrb, argc, argv, &args);
    264         if (n < 0) {
    265                 cleanup(mrb, &args);
    266                 usage(argv[0]);
    267                 return EXIT_FAILURE;
    268         }
    269         if (n == argc) {
    270                 fprintf(stderr, "%s: no program file given\n", args.prog);
    271                 return EXIT_FAILURE;
    272         }
    273         if (args.outfile == NULL && !args.check_syntax) {
    274                 if (n + 1 == argc) {
    275                         args.outfile = get_outfilename(mrb, argv[n], args.initname ? C_EXT : RITEBIN_EXT);
    276                 }
    277                 else {
    278                         fprintf(stderr, "%s: output file should be specified to compile multiple files\n", args.prog);
    279                         return EXIT_FAILURE;
    280                 }
    281         }
    282 
    283         args.idx = n;
    284         load = load_file(mrb, &args);
    285         if (mrb_nil_p(load)) {
    286                 cleanup(mrb, &args);
    287                 return EXIT_FAILURE;
    288         }
    289         if (args.check_syntax) {
    290                 printf("%s:%s:Syntax OK\n", args.prog, argv[n]);
    291         }
    292 
    293         if (args.check_syntax) {
    294                 cleanup(mrb, &args);
    295                 return EXIT_SUCCESS;
    296         }
    297 
    298         if (args.outfile) {
    299                 if (strcmp("-", args.outfile) == 0) {
    300                         wfp = stdout;
    301                 }
    302                 else if ((wfp = fopen(args.outfile, "wb")) == NULL) {
    303                         fprintf(stderr, "%s: cannot open output file:(%s)\n", args.prog, args.outfile);
    304                         return EXIT_FAILURE;
    305                 }
    306         }
    307         else {
    308                 fprintf(stderr, "Output file is required\n");
    309                 return EXIT_FAILURE;
    310         }
    311         result = dump_file(mrb, wfp, args.outfile, mrb_proc_ptr(load), &args);
    312         fclose(wfp);
    313         cleanup(mrb, &args);
    314         if (result != MRB_DUMP_OK) {
    315                 return EXIT_FAILURE;
    316         }
    317         return EXIT_SUCCESS;
    318 }
     265  mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL, TRUE);
     266  int n, result;
     267  struct mrbc_args args;
     268  FILE *wfp;
     269  mrb_value load;
     270
     271  if (mrb == NULL) {
     272    fputs("Invalid mrb_state, exiting mrbc\n", stderr);
     273    return EXIT_FAILURE;
     274  }
     275
     276  n = parse_args(mrb, argc, argv, &args);
     277  if (n < 0) {
     278    cleanup(mrb, &args);
     279    usage(argv[0]);
     280    return EXIT_FAILURE;
     281  }
     282  if (n == argc) {
     283    fprintf(stderr, "%s: no program file given\n", args.prog);
     284    return EXIT_FAILURE;
     285  }
     286  if (args.outfile == NULL && !args.check_syntax) {
     287    if (n + 1 == argc) {
     288      args.outfile = get_outfilename(mrb, argv[n], args.initname ? C_EXT : RITEBIN_EXT);
     289    }
     290    else {
     291      fprintf(stderr, "%s: output file should be specified to compile multiple files\n", args.prog);
     292      return EXIT_FAILURE;
     293    }
     294  }
     295
     296  args.idx = n;
     297  load = load_file(mrb, &args);
     298  if (mrb_nil_p(load)) {
     299    cleanup(mrb, &args);
     300    return EXIT_FAILURE;
     301  }
     302  if (args.check_syntax) {
     303    printf("%s:%s:Syntax OK\n", args.prog, argv[n]);
     304  }
     305
     306  if (args.check_syntax) {
     307    cleanup(mrb, &args);
     308    return EXIT_SUCCESS;
     309  }
     310
     311  if (args.outfile) {
     312    if (strcmp("-", args.outfile) == 0) {
     313      wfp = stdout;
     314    }
     315    else if ((wfp = fopen(args.outfile, "wb")) == NULL) {
     316      fprintf(stderr, "%s: cannot open output file:(%s)\n", args.prog, args.outfile);
     317      return EXIT_FAILURE;
     318    }
     319  }
     320  else {
     321    fprintf(stderr, "Output file is required\n");
     322    return EXIT_FAILURE;
     323  }
     324  result = dump_file(mrb, wfp, args.outfile, mrb_proc_ptr(load), &args);
     325  fclose(wfp);
     326  cleanup(mrb, &args);
     327  if (result != MRB_DUMP_OK) {
     328    return EXIT_FAILURE;
     329  }
     330  return EXIT_SUCCESS;
     331}
  • 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}
  • EcnlProtoTool/trunk/prototool/src/mrdb.h

    r321 r439  
    77#define MRDB_H
    88
    9 #include "mruby.h"
     9#include <mruby.h>
    1010
    1111#include "mrdbconf.h"
     12
     13#ifdef _MSC_VER
     14# define __func__ __FUNCTION__
     15#endif
    1216
    1317#define MAX_COMMAND_WORD (16)
     
    2024  DBGCMD_BREAK,
    2125  DBGCMD_INFO_BREAK,
     26  DBGCMD_INFO_LOCAL,
    2227  DBGCMD_WATCH,
    2328  DBGCMD_INFO_WATCH,
     
    5257  DBG_QUIT,
    5358} mrdb_exemode;
    54 
    55 #ifdef _MSC_VER
    56 # define __func__ __FUNCTION__
    57 extern long __stdcall InterlockedExchange(long *dst, long src);
    58 extern long __stdcall InterlockedCompareExchange(long *dst, long src, long cmp);
    59 #else
    60 #define InterlockedExchange(dst, src) do { *(dst) = src; } while(0)
    61 __inline__ static enum mrdb_exemode InterlockedCompareExchange(enum mrdb_exemode *dst, enum mrdb_exemode src, enum mrdb_exemode cmp) { long prev = *(dst); if (*(dst) == cmp) *(dst) = src; return prev; }
    62 #endif
    6359
    6460typedef enum mrdb_exephase {
     
    110106  struct mrb_irep *root_irep;
    111107  struct mrb_irep *irep;
    112   mrb_code *pc;
     108  const mrb_code *pc;
    113109  mrb_value *regs;
    114110
     
    117113  mrb_callinfo *prvci;
    118114
    119 #ifdef _MSC_VER
    120   long xm;
    121 #else
    122115  mrdb_exemode xm;
    123 #endif
    124116  mrdb_exephase xphase;
    125117  mrdb_brkmode bm;
     
    161153dbgcmd_state dbgcmd_break(mrb_state*, mrdb_state*);
    162154dbgcmd_state dbgcmd_info_break(mrb_state*, mrdb_state*);
     155dbgcmd_state dbgcmd_info_local(mrb_state*, mrdb_state*);
    163156dbgcmd_state dbgcmd_delete(mrb_state*, mrdb_state*);
    164157dbgcmd_state dbgcmd_enable(mrb_state*, mrdb_state*);
     
    168161dbgcmd_state dbgcmd_eval(mrb_state*, mrdb_state*);
    169162/* cmdmisc.c */
     163dbgcmd_state dbgcmd_list(mrb_state*, mrdb_state*);
    170164dbgcmd_state dbgcmd_help(mrb_state*, mrdb_state*);
    171165dbgcmd_state dbgcmd_quit(mrb_state*, mrdb_state*);
  • EcnlProtoTool/trunk/prototool/src/mrdbconf.h

    r321 r439  
    66#ifndef MRDBCONF_H
    77#define MRDBCONF_H
     8
     9#ifndef MRB_ENABLE_DEBUG_HOOK
     10# error mruby-bin-debugger need 'MRB_ENABLE_DEBUG_HOOK' configuration in your 'build_config.rb'
     11#endif
     12
     13#ifdef MRB_DISABLE_STDIO
     14# error mruby-bin-debugger conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     15#endif
    816
    917/* configuration options: */
  • EcnlProtoTool/trunk/prototool/src/mruby.c

    r321 r439  
     1#include <mruby.h>
     2
     3#ifdef MRB_DISABLE_STDIO
     4# error mruby-bin-mruby conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     5#endif
     6
    17#include <stdlib.h>
    28#include <string.h>
    3 
    4 #include "mruby.h"
    5 #include "mruby/array.h"
    6 #include "mruby/compile.h"
    7 #include "mruby/dump.h"
    8 #include "mruby/variable.h"
    9 
    10 #ifdef MRB_DISABLE_STDIO
    11 static void
    12 p(mrb_state *mrb, mrb_value obj)
    13 {
    14         mrb_value val = mrb_inspect(mrb, obj);
    15 
    16         fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
    17         putc('\n', stdout);
    18 }
    19 #else
    20 #define p(mrb,obj) mrb_p(mrb,obj)
    21 #endif
    22 
    23 struct _args
    24 {
    25         FILE *rfp;
    26         char* cmdline;
    27         mrb_bool fname : 1;
    28         mrb_bool mrbfile : 1;
    29         mrb_bool check_syntax : 1;
    30         mrb_bool verbose : 1;
    31         int argc;
    32         char** argv;
     9#include <mruby/array.h>
     10#include <mruby/compile.h>
     11#include <mruby/dump.h>
     12#include <mruby/variable.h>
     13
     14struct _args {
     15  FILE *rfp;
     16  char *cmdline;
     17  mrb_bool fname        : 1;
     18  mrb_bool mrbfile      : 1;
     19  mrb_bool check_syntax : 1;
     20  mrb_bool verbose      : 1;
     21  mrb_bool version      : 1;
     22  mrb_bool debug        : 1;
     23  int argc;
     24  char **argv;
     25  int libc;
     26  char **libv;
     27};
     28
     29struct options {
     30  int argc;
     31  char **argv;
     32  char *program;
     33  char *opt;
     34  char short_opt[2];
    3335};
    3436
     
    3638usage(const char *name)
    3739{
    38         static const char *const usage_msg[] = {
    39                 "switches:",
    40                 "-b           load and execute RiteBinary (mrb) file",
    41                 "-c           check syntax only",
    42                 "-e 'command' one line of script",
    43                 "-v           print version number, then run in verbose mode",
    44                 "--verbose    run in verbose mode",
    45                 "--version    print the version",
    46                 "--copyright  print the copyright",
    47                 NULL
    48         };
    49         const char *const *p = usage_msg;
    50 
    51         printf("Usage: %s [switches] programfile\n", name);
    52         while (*p)
    53                 printf("  %s\n", *p++);
     40  static const char *const usage_msg[] = {
     41  "switches:",
     42  "-b           load and execute RiteBinary (mrb) file",
     43  "-c           check syntax only",
     44  "-d           set debugging flags (set $DEBUG to true)",
     45  "-e 'command' one line of script",
     46  "-r library   load the library before executing your script",
     47  "-v           print version number, then run in verbose mode",
     48  "--verbose    run in verbose mode",
     49  "--version    print the version",
     50  "--copyright  print the copyright",
     51  NULL
     52  };
     53  const char *const *p = usage_msg;
     54
     55  printf("Usage: %s [switches] [programfile] [arguments]\n", name);
     56  while (*p)
     57    printf("  %s\n", *p++);
     58}
     59
     60static void
     61options_init(struct options *opts, int argc, char **argv)
     62{
     63  opts->argc = argc;
     64  opts->argv = argv;
     65  opts->program = *argv;
     66  *opts->short_opt = 0;
     67}
     68
     69static const char *
     70options_opt(struct options *opts)
     71{
     72  /* concatenated short options (e.g. `-cv`) */
     73  if (*opts->short_opt && *++opts->opt) {
     74   short_opt:
     75    opts->short_opt[0] = *opts->opt;
     76    opts->short_opt[1] = 0;
     77    return opts->short_opt;
     78  }
     79
     80  while (++opts->argv, --opts->argc) {
     81    opts->opt = *opts->argv;
     82
     83    /*  empty         || not start with `-`  || `-` */
     84    if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
     85
     86    if (opts->opt[1] == '-') {
     87      /* `--` */
     88      if (!opts->opt[2]) {
     89        ++opts->argv, --opts->argc;
     90        return NULL;
     91      }
     92      /* long option */
     93      opts->opt += 2;
     94      *opts->short_opt = 0;
     95      return opts->opt;
     96    }
     97    else {
     98      /* short option */
     99      ++opts->opt;
     100      goto short_opt;
     101    }
     102  }
     103  return NULL;
     104}
     105
     106static const char *
     107options_arg(struct options *opts)
     108{
     109  if (*opts->short_opt && opts->opt[1]) {
     110    /* concatenated short option and option argument (e.g. `-rLIBRARY`) */
     111    *opts->short_opt = 0;
     112    return opts->opt + 1;
     113  }
     114  --opts->argc, ++opts->argv;
     115  return opts->argc ? *opts->argv : NULL;
     116}
     117
     118static char *
     119dup_arg_item(mrb_state *mrb, const char *item)
     120{
     121  size_t buflen = strlen(item) + 1;
     122  char *buf = (char*)mrb_malloc(mrb, buflen);
     123  memcpy(buf, item, buflen);
     124  return buf;
    54125}
    55126
     
    57128parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
    58129{
    59         char **origargv = argv;
    60         static const struct _args args_zero = { 0 };
    61 
    62         *args = args_zero;
    63 
    64         for (argc--, argv++; argc > 0; argc--, argv++) {
    65                 char *item;
    66                 if (argv[0][0] != '-') break;
    67 
    68                 if (strlen(*argv) <= 1) {
    69                         argc--; argv++;
    70                         args->rfp = stdin;
    71                         break;
    72                 }
    73 
    74                 item = argv[0] + 1;
    75                 switch (*item++) {
    76                 case 'b':
    77                         args->mrbfile = TRUE;
    78                         break;
    79                 case 'c':
    80                         args->check_syntax = TRUE;
    81                         break;
    82                 case 'e':
    83                         if (item[0]) {
    84                                 goto append_cmdline;
    85                         }
    86                         else if (argc > 1) {
    87                                 argc--; argv++;
    88                                 item = argv[0];
    89                         append_cmdline:
    90                                 if (!args->cmdline) {
    91                                         size_t buflen;
    92                                         char *buf;
    93 
    94                                         buflen = strlen(item) + 1;
    95                                         buf = (char *)mrb_malloc(mrb, buflen);
    96                                         memcpy(buf, item, buflen);
    97                                         args->cmdline = buf;
    98                                 }
    99                                 else {
    100                                         size_t cmdlinelen;
    101                                         size_t itemlen;
    102 
    103                                         cmdlinelen = strlen(args->cmdline);
    104                                         itemlen = strlen(item);
    105                                         args->cmdline =
    106                                                 (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
    107                                         args->cmdline[cmdlinelen] = '\n';
    108                                         memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
    109                                 }
    110                         }
    111                         else {
    112                                 printf("%s: No code specified for -e\n", *origargv);
    113                                 return EXIT_SUCCESS;
    114                         }
    115                         break;
    116                 case 'v':
    117                         if (!args->verbose) mrb_show_version(mrb);
    118                         args->verbose = TRUE;
    119                         break;
    120                 case '-':
    121                         if (strcmp((*argv) + 2, "version") == 0) {
    122                                 mrb_show_version(mrb);
    123                                 exit(EXIT_SUCCESS);
    124                         }
    125                         else if (strcmp((*argv) + 2, "verbose") == 0) {
    126                                 args->verbose = TRUE;
    127                                 break;
    128                         }
    129                         else if (strcmp((*argv) + 2, "copyright") == 0) {
    130                                 mrb_show_copyright(mrb);
    131                                 exit(EXIT_SUCCESS);
    132                         }
    133                 default:
    134                         return EXIT_FAILURE;
    135                 }
    136         }
    137 
    138         if (args->rfp == NULL && args->cmdline == NULL) {
    139                 if (*argv == NULL) args->rfp = stdin;
    140                 else {
    141                         args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
    142                         if (args->rfp == NULL) {
    143                                 printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
    144                                 return EXIT_FAILURE;
    145                         }
    146                         args->fname = TRUE;
    147                         args->cmdline = argv[0];
    148                         argc--; argv++;
    149                 }
    150         }
    151         args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
    152         memcpy(args->argv, argv, (argc + 1) * sizeof(char*));
    153         args->argc = argc;
    154 
    155         return EXIT_SUCCESS;
     130  static const struct _args args_zero = { 0 };
     131  struct options opts[1];
     132  const char *opt, *item;
     133
     134  *args = args_zero;
     135  options_init(opts, argc, argv);
     136  while ((opt = options_opt(opts))) {
     137    if (strcmp(opt, "b") == 0) {
     138      args->mrbfile = TRUE;
     139    }
     140    else if (strcmp(opt, "c") == 0) {
     141      args->check_syntax = TRUE;
     142    }
     143    else if (strcmp(opt, "d") == 0) {
     144      args->debug = TRUE;
     145    }
     146    else if (strcmp(opt, "e") == 0) {
     147      if ((item = options_arg(opts))) {
     148        if (!args->cmdline) {
     149          args->cmdline = dup_arg_item(mrb, item);
     150        }
     151        else {
     152          size_t cmdlinelen;
     153          size_t itemlen;
     154
     155          cmdlinelen = strlen(args->cmdline);
     156          itemlen = strlen(item);
     157          args->cmdline =
     158            (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
     159          args->cmdline[cmdlinelen] = '\n';
     160          memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
     161        }
     162      }
     163      else {
     164        fprintf(stderr, "%s: No code specified for -e\n", opts->program);
     165        return EXIT_FAILURE;
     166      }
     167    }
     168    else if (strcmp(opt, "h") == 0) {
     169      usage(opts->program);
     170      exit(EXIT_SUCCESS);
     171    }
     172    else if (strcmp(opt, "r") == 0) {
     173      if ((item = options_arg(opts))) {
     174        if (args->libc == 0) {
     175          args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
     176        }
     177        else {
     178          args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
     179        }
     180        args->libv[args->libc++] = dup_arg_item(mrb, item);
     181      }
     182      else {
     183        fprintf(stderr, "%s: No library specified for -r\n", opts->program);
     184        return EXIT_FAILURE;
     185      }
     186    }
     187    else if (strcmp(opt, "v") == 0) {
     188      if (!args->verbose) {
     189        mrb_show_version(mrb);
     190        args->version = TRUE;
     191      }
     192      args->verbose = TRUE;
     193    }
     194    else if (strcmp(opt, "version") == 0) {
     195      mrb_show_version(mrb);
     196      exit(EXIT_SUCCESS);
     197    }
     198    else if (strcmp(opt, "verbose") == 0) {
     199      args->verbose = TRUE;
     200    }
     201    else if (strcmp(opt, "copyright") == 0) {
     202      mrb_show_copyright(mrb);
     203      exit(EXIT_SUCCESS);
     204    }
     205    else {
     206      fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
     207              opts->program, opt[1] ? "--" : "-", opt);
     208      return EXIT_FAILURE;
     209    }
     210  }
     211
     212  argc = opts->argc; argv = opts->argv;
     213  if (args->cmdline == NULL) {
     214    if (*argv == NULL) {
     215      if (args->version) exit(EXIT_SUCCESS);
     216      args->rfp = stdin;
     217    }
     218    else {
     219      args->rfp = strcmp(argv[0], "-") == 0 ?
     220        stdin : fopen(argv[0], args->mrbfile ? "rb" : "r");
     221      if (args->rfp == NULL) {
     222        fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
     223        return EXIT_FAILURE;
     224      }
     225      args->fname = TRUE;
     226      args->cmdline = argv[0];
     227      argc--; argv++;
     228    }
     229  }
     230  args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
     231  memcpy(args->argv, argv, (argc+1) * sizeof(char*));
     232  args->argc = argc;
     233
     234  return EXIT_SUCCESS;
    156235}
    157236
     
    159238cleanup(mrb_state *mrb, struct _args *args)
    160239{
    161         if (args->rfp && args->rfp != stdin)
    162                 fclose(args->rfp);
    163         if (!args->fname)
    164                 mrb_free(mrb, args->cmdline);
    165         mrb_free(mrb, args->argv);
    166         mrb_close(mrb);
     240  if (args->rfp && args->rfp != stdin)
     241    fclose(args->rfp);
     242  if (!args->fname)
     243    mrb_free(mrb, args->cmdline);
     244  mrb_free(mrb, args->argv);
     245  if (args->libc) {
     246    while (args->libc--) {
     247      mrb_free(mrb, args->libv[args->libc]);
     248    }
     249    mrb_free(mrb, args->libv);
     250  }
     251  mrb_close(mrb);
    167252}
    168253
     
    170255mruby_main(int argc, char **argv)
    171256{
    172         mrb_state *mrb = mrb_open();
    173         int n = -1;
    174         int i;
    175         struct _args args;
    176         mrb_value ARGV;
    177         mrbc_context *c;
    178         mrb_value v;
    179         mrb_sym zero_sym;
    180 
    181         if (mrb == NULL) {
    182                 fputs("Invalid mrb_state, exiting mruby\n", stderr);
    183                 return EXIT_FAILURE;
    184         }
    185 
    186         n = parse_args(mrb, argc, argv, &args);
    187         if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
    188                 cleanup(mrb, &args);
    189                 usage(argv[0]);
    190                 return n;
    191         }
    192         else {
    193                 int ai = mrb_gc_arena_save(mrb);
    194                 ARGV = mrb_ary_new_capa(mrb, args.argc);
    195                 for (i = 0; i < args.argc; i++) {
    196                         mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, args.argv[i]));
    197                 }
    198                 mrb_define_global_const(mrb, "ARGV", ARGV);
    199 
    200                 c = mrbc_context_new(mrb);
    201                 if (args.verbose)
    202                         c->dump_result = TRUE;
    203                 if (args.check_syntax)
    204                         c->no_exec = TRUE;
    205 
    206                 /* Set $0 */
    207                 zero_sym = mrb_intern_lit(mrb, "$0");
    208                 if (args.rfp) {
    209                         const char *cmdline;
    210                         cmdline = args.cmdline ? args.cmdline : "-";
    211                         mrbc_filename(mrb, c, cmdline);
    212                         mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
    213                 }
    214                 else {
    215                         mrbc_filename(mrb, c, "-e");
    216                         mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
    217                 }
    218 
    219                 /* Load program */
    220                 if (args.mrbfile) {
    221                         v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
    222                 }
    223                 else if (args.rfp) {
    224                         v = mrb_load_file_cxt(mrb, args.rfp, c);
    225                 }
    226                 else {
    227                         v = mrb_load_string_cxt(mrb, args.cmdline, c);
    228                 }
    229 
    230                 mrb_gc_arena_restore(mrb, ai);
    231                 mrbc_context_free(mrb, c);
    232                 if (mrb->exc) {
    233                         if (!mrb_undef_p(v)) {
    234                                 mrb_print_error(mrb);
    235                         }
    236                         n = -1;
    237                 }
    238                 else if (args.check_syntax) {
    239                         printf("Syntax OK\n");
    240                 }
    241         }
    242         cleanup(mrb, &args);
    243 
    244         return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
    245 }
     257  mrb_state *mrb = mrb_open();
     258  int n = -1;
     259  int i;
     260  struct _args args;
     261  mrb_value ARGV;
     262  mrbc_context *c;
     263  mrb_value v;
     264  mrb_sym zero_sym;
     265
     266  if (mrb == NULL) {
     267    fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv);
     268    return EXIT_FAILURE;
     269  }
     270
     271  n = parse_args(mrb, argc, argv, &args);
     272  if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
     273    cleanup(mrb, &args);
     274    return n;
     275  }
     276  else {
     277    int ai = mrb_gc_arena_save(mrb);
     278    ARGV = mrb_ary_new_capa(mrb, args.argc);
     279    for (i = 0; i < args.argc; i++) {
     280      char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
     281      if (utf8) {
     282        mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
     283        mrb_utf8_free(utf8);
     284      }
     285    }
     286    mrb_define_global_const(mrb, "ARGV", ARGV);
     287    mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
     288
     289    c = mrbc_context_new(mrb);
     290    if (args.verbose)
     291      c->dump_result = TRUE;
     292    if (args.check_syntax)
     293      c->no_exec = TRUE;
     294
     295    /* Set $0 */
     296    zero_sym = mrb_intern_lit(mrb, "$0");
     297    if (args.rfp) {
     298      const char *cmdline;
     299      cmdline = args.cmdline ? args.cmdline : "-";
     300      mrbc_filename(mrb, c, cmdline);
     301      mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
     302    }
     303    else {
     304      mrbc_filename(mrb, c, "-e");
     305      mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
     306    }
     307
     308    /* Load libraries */
     309    for (i = 0; i < args.libc; i++) {
     310      FILE *lfp = fopen(args.libv[i], args.mrbfile ? "rb" : "r");
     311      if (lfp == NULL) {
     312        fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
     313        mrbc_context_free(mrb, c);
     314        cleanup(mrb, &args);
     315        return EXIT_FAILURE;
     316      }
     317      if (args.mrbfile) {
     318        v = mrb_load_irep_file_cxt(mrb, lfp, c);
     319      }
     320      else {
     321        v = mrb_load_file_cxt(mrb, lfp, c);
     322      }
     323      fclose(lfp);
     324    }
     325
     326    /* Load program */
     327    if (args.mrbfile) {
     328      v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
     329    }
     330    else if (args.rfp) {
     331      v = mrb_load_file_cxt(mrb, args.rfp, c);
     332    }
     333    else {
     334      char* utf8 = mrb_utf8_from_locale(args.cmdline, -1);
     335      if (!utf8) abort();
     336      v = mrb_load_string_cxt(mrb, utf8, c);
     337      mrb_utf8_free(utf8);
     338    }
     339
     340    mrb_gc_arena_restore(mrb, ai);
     341    mrbc_context_free(mrb, c);
     342    if (mrb->exc) {
     343      if (!mrb_undef_p(v)) {
     344        mrb_print_error(mrb);
     345      }
     346      n = EXIT_FAILURE;
     347    }
     348    else if (args.check_syntax) {
     349      puts("Syntax OK");
     350    }
     351  }
     352  cleanup(mrb, &args);
     353
     354  return n;
     355}
Note: See TracChangeset for help on using the changeset viewer.