mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers load.c Source File

load.c

00001 /*
00002 ** load.c - mruby binary loader
00003 **
00004 ** See Copyright Notice in mruby.h
00005 */
00006 
00007 #include <limits.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include "mruby/dump.h"
00011 #include "mruby/irep.h"
00012 #include "mruby/proc.h"
00013 #include "mruby/string.h"
00014 #include "mruby/debug.h"
00015 #include "mruby/error.h"
00016 
00017 #define FLAG_BYTEORDER_NATIVE 2
00018 #define FLAG_BYTEORDER_NONATIVE 0
00019 #define FLAG_SRC_MALLOC 1
00020 #define FLAG_SRC_STATIC 0
00021 
00022 #if !defined(_WIN32) && SIZE_MAX < UINT32_MAX
00023 # define SIZE_ERROR_MUL(x, y) ((x) > SIZE_MAX / (y))
00024 # define SIZE_ERROR(x) ((x) > SIZE_MAX)
00025 #else
00026 # define SIZE_ERROR_MUL(x, y) (0)
00027 # define SIZE_ERROR(x) (0)
00028 #endif
00029 
00030 #if UINT32_MAX > SIZE_MAX
00031 # error This code cannot be built on your environment.
00032 #endif
00033 
00034 static size_t
00035 skip_padding(const uint8_t *buf)
00036 {
00037   const size_t align = MRB_DUMP_ALIGNMENT;
00038   return -(intptr_t)buf & (align-1);
00039 }
00040 
00041 static size_t
00042 offset_crc_body(void)
00043 {
00044   struct rite_binary_header header;
00045   return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc);
00046 }
00047 
00048 static mrb_irep*
00049 read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
00050 {
00051   size_t i;
00052   const uint8_t *src = bin;
00053   ptrdiff_t diff;
00054   uint16_t tt, pool_data_len, snl;
00055   size_t plen;
00056   int ai = mrb_gc_arena_save(mrb);
00057   mrb_irep *irep = mrb_add_irep(mrb);
00058 
00059   /* skip record size */
00060   src += sizeof(uint32_t);
00061 
00062   /* number of local variable */
00063   irep->nlocals = bin_to_uint16(src);
00064   src += sizeof(uint16_t);
00065 
00066   /* number of register variable */
00067   irep->nregs = bin_to_uint16(src);
00068   src += sizeof(uint16_t);
00069 
00070   /* number of child irep */
00071   irep->rlen = (size_t)bin_to_uint16(src);
00072   src += sizeof(uint16_t);
00073 
00074   /* Binary Data Section */
00075   /* ISEQ BLOCK */
00076   irep->ilen = (size_t)bin_to_uint32(src);
00077   src += sizeof(uint32_t);
00078   src += skip_padding(src);
00079 
00080   if (irep->ilen > 0) {
00081     if (SIZE_ERROR_MUL(sizeof(mrb_code), irep->ilen)) {
00082       return NULL;
00083     }
00084     if ((flags & FLAG_SRC_MALLOC) == 0 &&
00085         (flags & FLAG_BYTEORDER_NATIVE)) {
00086       irep->iseq = (mrb_code*)src;
00087       src += sizeof(uint32_t) * irep->ilen;
00088       irep->flags |= MRB_ISEQ_NO_FREE;
00089     }
00090     else {
00091       irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen);
00092       if (flags & FLAG_BYTEORDER_NATIVE) {
00093         memcpy(irep->iseq, src, sizeof(uint32_t) * irep->ilen);
00094         src += sizeof(uint32_t) * irep->ilen;
00095       }
00096       else {
00097         for (i = 0; i < irep->ilen; i++) {
00098           irep->iseq[i] = (mrb_code)bin_to_uint32(src);     /* iseq */
00099           src += sizeof(uint32_t);
00100         }
00101       }
00102     }
00103   }
00104 
00105   /* POOL BLOCK */
00106   plen = (size_t)bin_to_uint32(src); /* number of pool */
00107   src += sizeof(uint32_t);
00108   if (plen > 0) {
00109     if (SIZE_ERROR_MUL(sizeof(mrb_value), plen)) {
00110       return NULL;
00111     }
00112     irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen);
00113 
00114     for (i = 0; i < plen; i++) {
00115       mrb_value s;
00116 
00117       tt = *src++; /* pool TT */
00118       pool_data_len = bin_to_uint16(src); /* pool data length */
00119       src += sizeof(uint16_t);
00120       if (flags & FLAG_SRC_MALLOC) {
00121         s = mrb_str_new(mrb, (char *)src, pool_data_len);
00122       }
00123       else {
00124         s = mrb_str_new_static(mrb, (char *)src, pool_data_len);
00125       }
00126       src += pool_data_len;
00127       switch (tt) { /* pool data */
00128       case IREP_TT_FIXNUM:
00129         irep->pool[i] = mrb_str_to_inum(mrb, s, 10, FALSE);
00130         break;
00131 
00132       case IREP_TT_FLOAT:
00133         irep->pool[i] = mrb_float_pool(mrb, mrb_str_to_dbl(mrb, s, FALSE));
00134         break;
00135 
00136       case IREP_TT_STRING:
00137         irep->pool[i] = mrb_str_pool(mrb, s);
00138         break;
00139 
00140       default:
00141         /* should not happen */
00142         irep->pool[i] = mrb_nil_value();
00143         break;
00144       }
00145       irep->plen++;
00146       mrb_gc_arena_restore(mrb, ai);
00147     }
00148   }
00149 
00150   /* SYMS BLOCK */
00151   irep->slen = (size_t)bin_to_uint32(src);  /* syms length */
00152   src += sizeof(uint32_t);
00153   if (irep->slen > 0) {
00154     if (SIZE_ERROR_MUL(sizeof(mrb_sym), irep->slen)) {
00155       return NULL;
00156     }
00157     irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen);
00158 
00159     for (i = 0; i < irep->slen; i++) {
00160       snl = bin_to_uint16(src);               /* symbol name length */
00161       src += sizeof(uint16_t);
00162 
00163       if (snl == MRB_DUMP_NULL_SYM_LEN) {
00164         irep->syms[i] = 0;
00165         continue;
00166       }
00167 
00168       if (flags & FLAG_SRC_MALLOC) {
00169         irep->syms[i] = mrb_intern(mrb, (char *)src, snl);
00170       }
00171       else {
00172         irep->syms[i] = mrb_intern_static(mrb, (char *)src, snl);
00173       }
00174       src += snl + 1;
00175 
00176       mrb_gc_arena_restore(mrb, ai);
00177     }
00178   }
00179 
00180   irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen);
00181 
00182   diff = src - bin;
00183   mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
00184   *len = (size_t)diff;
00185 
00186   return irep;
00187 }
00188 
00189 static mrb_irep*
00190 read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
00191 {
00192   mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags);
00193   size_t i;
00194 
00195   if (irep == NULL) {
00196     return NULL;
00197   }
00198 
00199   bin += *len;
00200   for (i=0; i<irep->rlen; i++) {
00201     size_t rlen;
00202 
00203     irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags);
00204     if (irep->reps[i] == NULL) {
00205       return NULL;
00206     }
00207     bin += rlen;
00208     *len += rlen;
00209   }
00210   return irep;
00211 }
00212 
00213 static mrb_irep*
00214 read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags)
00215 {
00216   size_t len;
00217 
00218   bin += sizeof(struct rite_section_irep_header);
00219   return read_irep_record(mrb, bin, &len, flags);
00220 }
00221 
00222 static int
00223 read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len)
00224 {
00225   size_t i, fname_len, niseq;
00226   char *fname;
00227   uint16_t *lines;
00228 
00229   *len = 0;
00230   bin += sizeof(uint32_t); /* record size */
00231   *len += sizeof(uint32_t);
00232   fname_len = bin_to_uint16(bin);
00233   bin += sizeof(uint16_t);
00234   *len += sizeof(uint16_t);
00235   if (SIZE_ERROR(fname_len + 1)) {
00236     return MRB_DUMP_GENERAL_FAILURE;
00237   }
00238   fname = (char *)mrb_malloc(mrb, fname_len + 1);
00239   memcpy(fname, bin, fname_len);
00240   fname[fname_len] = '\0';
00241   bin += fname_len;
00242   *len += fname_len;
00243 
00244   niseq = (size_t)bin_to_uint32(bin);
00245   bin += sizeof(uint32_t); /* niseq */
00246   *len += sizeof(uint32_t);
00247 
00248   if (SIZE_ERROR_MUL(niseq, sizeof(uint16_t))) {
00249     return MRB_DUMP_GENERAL_FAILURE;
00250   }
00251   lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t));
00252   for (i = 0; i < niseq; i++) {
00253     lines[i] = bin_to_uint16(bin);
00254     bin += sizeof(uint16_t); /* niseq */
00255     *len += sizeof(uint16_t);
00256   }
00257 
00258   irep->filename = fname;
00259   irep->lines = lines;
00260   return MRB_DUMP_OK;
00261 }
00262 
00263 static int
00264 read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *lenp)
00265 {
00266   int result = read_lineno_record_1(mrb, bin, irep, lenp);
00267   size_t i;
00268 
00269   if (result != MRB_DUMP_OK) return result;
00270   for (i = 0; i < irep->rlen; i++) {
00271     size_t len;
00272 
00273     result = read_lineno_record(mrb, bin, irep->reps[i], &len);
00274     if (result != MRB_DUMP_OK) break;
00275     bin += len;
00276     *lenp += len;
00277   }
00278   return result;
00279 }
00280 
00281 static int
00282 read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep)
00283 {
00284   size_t len;
00285 
00286   len = 0;
00287   bin += sizeof(struct rite_section_lineno_header);
00288 
00289   /* Read Binary Data Section */
00290   return read_lineno_record(mrb, bin, irep, &len);
00291 }
00292 
00293 static int
00294 read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len)
00295 {
00296   const uint8_t *bin = start;
00297   ptrdiff_t diff;
00298   size_t record_size, i;
00299   uint16_t f_idx;
00300 
00301   if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
00302 
00303   irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info));
00304   irep->debug_info->pc_count = irep->ilen;
00305 
00306   record_size = (size_t)bin_to_uint32(bin);
00307   bin += sizeof(uint32_t);
00308 
00309   irep->debug_info->flen = bin_to_uint16(bin);
00310   irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen);
00311   bin += sizeof(uint16_t);
00312 
00313   for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
00314     mrb_irep_debug_info_file *file;
00315     uint16_t filename_idx;
00316     mrb_int len;
00317 
00318     file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file));
00319     irep->debug_info->files[f_idx] = file;
00320 
00321     file->start_pos = bin_to_uint32(bin);
00322     bin += sizeof(uint32_t);
00323 
00324     /* filename */
00325     filename_idx = bin_to_uint16(bin);
00326     bin += sizeof(uint16_t);
00327     mrb_assert(filename_idx < filenames_len);
00328     file->filename_sym = filenames[filename_idx];
00329     len = 0;
00330     file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len);
00331 
00332     file->line_entry_count = bin_to_uint32(bin);
00333     bin += sizeof(uint32_t);
00334     file->line_type = (mrb_debug_line_type)bin_to_uint8(bin);
00335     bin += sizeof(uint8_t);
00336     switch (file->line_type) {
00337       case mrb_debug_line_ary: {
00338         uint32_t l;
00339 
00340         file->lines.ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * (size_t)(file->line_entry_count));
00341         for (l = 0; l < file->line_entry_count; ++l) {
00342           file->lines.ary[l] = bin_to_uint16(bin);
00343           bin += sizeof(uint16_t);
00344         }
00345       } break;
00346 
00347       case mrb_debug_line_flat_map: {
00348         uint32_t l;
00349 
00350         file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(
00351             mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count));
00352         for (l = 0; l < file->line_entry_count; ++l) {
00353           file->lines.flat_map[l].start_pos = bin_to_uint32(bin);
00354           bin += sizeof(uint32_t);
00355           file->lines.flat_map[l].line = bin_to_uint16(bin);
00356           bin += sizeof(uint16_t);
00357         }
00358       } break;
00359 
00360       default: return MRB_DUMP_GENERAL_FAILURE;
00361     }
00362   }
00363 
00364   diff = bin - start;
00365   mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
00366 
00367   if (record_size != (size_t)diff) {
00368     return MRB_DUMP_GENERAL_FAILURE;
00369   }
00370 
00371   for (i = 0; i < irep->rlen; i++) {
00372     size_t len;
00373     int ret;
00374 
00375     ret = read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len);
00376     if (ret != MRB_DUMP_OK) return ret;
00377     bin += len;
00378   }
00379 
00380   diff = bin - start;
00381   mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
00382   *record_len = (size_t)diff;
00383 
00384   return MRB_DUMP_OK;
00385 }
00386 
00387 static int
00388 read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags)
00389 {
00390   const uint8_t *bin;
00391   ptrdiff_t diff;
00392   struct rite_section_debug_header *header;
00393   uint16_t i;
00394   size_t len = 0;
00395   int result;
00396   uint16_t filenames_len;
00397   mrb_sym *filenames;
00398 
00399   bin = start;
00400   header = (struct rite_section_debug_header *)bin;
00401   bin += sizeof(struct rite_section_debug_header);
00402 
00403   filenames_len = bin_to_uint16(bin);
00404   bin += sizeof(uint16_t);
00405   filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len);
00406   for (i = 0; i < filenames_len; ++i) {
00407     uint16_t f_len = bin_to_uint16(bin);
00408     bin += sizeof(uint16_t);
00409     if (flags & FLAG_SRC_MALLOC) {
00410       filenames[i] = mrb_intern(mrb, (const char *)bin, (size_t)f_len);
00411     }
00412     else {
00413       filenames[i] = mrb_intern_static(mrb, (const char *)bin, (size_t)f_len);
00414     }
00415     bin += f_len;
00416   }
00417 
00418   result = read_debug_record(mrb, bin, irep, &len, filenames, filenames_len);
00419   if (result != MRB_DUMP_OK) goto debug_exit;
00420 
00421   bin += len;
00422   diff = bin - start;
00423   mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
00424   if ((uint32_t)diff != bin_to_uint32(header->section_size)) {
00425     result = MRB_DUMP_GENERAL_FAILURE;
00426   }
00427 
00428 debug_exit:
00429   mrb_free(mrb, filenames);
00430   return result;
00431 }
00432 
00433 static int
00434 read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *record_len, mrb_sym const *syms, uint32_t syms_len)
00435 {
00436   const uint8_t *bin = start;
00437   size_t i;
00438   ptrdiff_t diff;
00439 
00440   irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (irep->nlocals - 1));
00441 
00442   for (i = 0; i + 1< irep->nlocals; ++i) {
00443     uint16_t const sym_idx = bin_to_uint16(bin);
00444     bin += sizeof(uint16_t);
00445     if (sym_idx == RITE_LV_NULL_MARK) {
00446       irep->lv[i].name = 0;
00447       irep->lv[i].r = 0;
00448     }
00449     else {
00450       if (sym_idx >= syms_len) {
00451         return MRB_DUMP_GENERAL_FAILURE;
00452       }
00453       irep->lv[i].name = syms[sym_idx];
00454 
00455       irep->lv[i].r = bin_to_uint16(bin);
00456     }
00457     bin += sizeof(uint16_t);
00458   }
00459 
00460   for (i = 0; i < irep->rlen; ++i) {
00461     size_t len;
00462     int ret;
00463 
00464     ret = read_lv_record(mrb, bin, irep->reps[i], &len, syms, syms_len);
00465     if (ret != MRB_DUMP_OK) return ret;
00466     bin += len;
00467   }
00468 
00469   diff = bin - start;
00470   mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
00471   *record_len = (size_t)diff;
00472 
00473   return MRB_DUMP_OK;
00474 }
00475 
00476 static int
00477 read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags)
00478 {
00479   const uint8_t *bin;
00480   ptrdiff_t diff;
00481   struct rite_section_lv_header const *header;
00482   uint32_t i;
00483   size_t len = 0;
00484   int result;
00485   uint32_t syms_len;
00486   mrb_sym *syms;
00487   mrb_sym (*intern_func)(mrb_state*, const char*, size_t) =
00488     (flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static;
00489 
00490   bin = start;
00491   header = (struct rite_section_lv_header const*)bin;
00492   bin += sizeof(struct rite_section_lv_header);
00493 
00494   syms_len = bin_to_uint32(bin);
00495   bin += sizeof(uint32_t);
00496   syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len);
00497   for (i = 0; i < syms_len; ++i) {
00498     uint16_t const str_len = bin_to_uint16(bin);
00499     bin += sizeof(uint16_t);
00500 
00501     syms[i] = intern_func(mrb, (const char*)bin, str_len);
00502     bin += str_len;
00503   }
00504 
00505   result = read_lv_record(mrb, bin, irep, &len, syms, syms_len);
00506   if (result != MRB_DUMP_OK) goto lv_exit;
00507 
00508   bin += len;
00509   diff = bin - start;
00510   mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
00511   if ((uint32_t)diff != bin_to_uint32(header->section_size)) {
00512     result = MRB_DUMP_GENERAL_FAILURE;
00513   }
00514 
00515 lv_exit:
00516   mrb_free(mrb, syms);
00517   return result;
00518 }
00519 
00520 static int
00521 read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t *flags)
00522 {
00523   const struct rite_binary_header *header = (const struct rite_binary_header *)bin;
00524   uint32_t ident = 0;
00525   size_t i;
00526 
00527   /* create native byteorder version of RITE_BINARY_IDENTIFIER */
00528   for(i=0; i<sizeof(ident); i++) {
00529     ident<<=8;
00530     ident|=RITE_BINARY_IDENTIFIER[i];
00531   }
00532   if (memcmp(header->binary_identify, &ident, sizeof(header->binary_identify)) == 0) {
00533     *flags |= FLAG_BYTEORDER_NATIVE;
00534   }
00535   else if (memcmp(header->binary_identify, RITE_BINARY_IDENTIFIER, sizeof(header->binary_identify)) != 0) {
00536     return MRB_DUMP_INVALID_FILE_HEADER;
00537   }
00538 
00539   if (memcmp(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)) != 0) {
00540     return MRB_DUMP_INVALID_FILE_HEADER;
00541   }
00542 
00543   if (crc) {
00544     *crc = bin_to_uint16(header->binary_crc);
00545   }
00546   *bin_size = (size_t)bin_to_uint32(header->binary_size);
00547 
00548   return MRB_DUMP_OK;
00549 }
00550 
00551 MRB_API mrb_irep*
00552 read_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags)
00553 {
00554   int result;
00555   mrb_irep *irep = NULL;
00556   const struct rite_section_header *section_header;
00557   uint16_t crc;
00558   size_t bin_size = 0;
00559   size_t n;
00560 
00561   if ((mrb == NULL) || (bin == NULL)) {
00562     return NULL;
00563   }
00564 
00565   result = read_binary_header(bin, &bin_size, &crc, &flags);
00566   if (result != MRB_DUMP_OK) {
00567     return NULL;
00568   }
00569 
00570   n = offset_crc_body();
00571   if (crc != calc_crc_16_ccitt(bin + n, bin_size - n, 0)) {
00572     return NULL;
00573   }
00574 
00575   bin += sizeof(struct rite_binary_header);
00576   do {
00577     section_header = (const struct rite_section_header *)bin;
00578     if (memcmp(section_header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
00579       irep = read_section_irep(mrb, bin, flags);
00580       if (!irep) return NULL;
00581     }
00582     else if (memcmp(section_header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
00583       if (!irep) return NULL;   /* corrupted data */
00584       result = read_section_lineno(mrb, bin, irep);
00585       if (result < MRB_DUMP_OK) {
00586         return NULL;
00587       }
00588     }
00589     else if (memcmp(section_header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
00590       if (!irep) return NULL;   /* corrupted data */
00591       result = read_section_debug(mrb, bin, irep, flags);
00592       if (result < MRB_DUMP_OK) {
00593         return NULL;
00594       }
00595     }
00596     else if (memcmp(section_header->section_identify, RITE_SECTION_LV_IDENTIFIER, sizeof(section_header->section_identify)) == 0) {
00597       if (!irep) return NULL;
00598       result = read_section_lv(mrb, bin, irep, flags);
00599       if (result < MRB_DUMP_OK) {
00600         return NULL;
00601       }
00602     }
00603     bin += bin_to_uint32(section_header->section_size);
00604   } while (memcmp(section_header->section_identify, RITE_BINARY_EOF, sizeof(section_header->section_identify)) != 0);
00605 
00606   return irep;
00607 }
00608 
00609 MRB_API mrb_irep*
00610 mrb_read_irep(mrb_state *mrb, const uint8_t *bin)
00611 {
00612 #ifdef MRB_USE_ETEXT_EDATA
00613   uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC;
00614 #else
00615   uint8_t flags = FLAG_SRC_STATIC;
00616 #endif
00617 
00618   return read_irep(mrb, bin, flags);
00619 }
00620 
00621 static void
00622 irep_error(mrb_state *mrb)
00623 {
00624   mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error"));
00625 }
00626 
00627 MRB_API mrb_value
00628 mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c)
00629 {
00630   mrb_irep *irep = mrb_read_irep(mrb, bin);
00631   struct RProc *proc;
00632 
00633   if (!irep) {
00634     irep_error(mrb);
00635     return mrb_nil_value();
00636   }
00637   proc = mrb_proc_new(mrb, irep);
00638   mrb_irep_decref(mrb, irep);
00639   if (c && c->no_exec) return mrb_obj_value(proc);
00640   return mrb_toplevel_run(mrb, proc);
00641 }
00642 
00643 MRB_API mrb_value
00644 mrb_load_irep(mrb_state *mrb, const uint8_t *bin)
00645 {
00646   return mrb_load_irep_cxt(mrb, bin, NULL);
00647 }
00648 
00649 #ifdef ENABLE_STDIO
00650 
00651 MRB_API mrb_irep*
00652 mrb_read_irep_file(mrb_state *mrb, FILE* fp)
00653 {
00654   mrb_irep *irep = NULL;
00655   uint8_t *buf;
00656   const size_t header_size = sizeof(struct rite_binary_header);
00657   size_t buf_size = 0;
00658   uint8_t flags;
00659   int result;
00660 
00661   if ((mrb == NULL) || (fp == NULL)) {
00662     return NULL;
00663   }
00664 
00665   /* You don't need use SIZE_ERROR as buf_size is enough small. */
00666   buf = (uint8_t*)mrb_malloc(mrb, header_size);
00667   if (fread(buf, header_size, 1, fp) == 0) {
00668     mrb_free(mrb, buf);
00669     return NULL;
00670   }
00671   result = read_binary_header(buf, &buf_size, NULL, &flags);
00672   if (result != MRB_DUMP_OK) {
00673     mrb_free(mrb, buf);
00674     return NULL;
00675   }
00676 
00677   buf = (uint8_t*)mrb_realloc(mrb, buf, buf_size);
00678   if (fread(buf+header_size, buf_size-header_size, 1, fp) == 0) {
00679     mrb_free(mrb, buf);
00680     return NULL;
00681   }
00682   irep = read_irep(mrb, buf, FLAG_SRC_MALLOC);
00683   mrb_free(mrb, buf);
00684 
00685   return irep;
00686 }
00687 
00688 void mrb_codedump_all(mrb_state*, struct RProc*);
00689 
00690 MRB_API mrb_value
00691 mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrbc_context *c)
00692 {
00693   mrb_irep *irep = mrb_read_irep_file(mrb, fp);
00694   mrb_value val;
00695   struct RProc *proc;
00696 
00697   if (!irep) {
00698     irep_error(mrb);
00699     return mrb_nil_value();
00700   }
00701   proc = mrb_proc_new(mrb, irep);
00702   mrb_irep_decref(mrb, irep);
00703   if (c && c->dump_result) mrb_codedump_all(mrb, proc);
00704   if (c && c->no_exec) return mrb_obj_value(proc);
00705   val = mrb_toplevel_run(mrb, proc);
00706   return val;
00707 }
00708 
00709 MRB_API mrb_value
00710 mrb_load_irep_file(mrb_state *mrb, FILE* fp)
00711 {
00712   return mrb_load_irep_file_cxt(mrb, fp, NULL);
00713 }
00714 #endif /* ENABLE_STDIO */
00715