mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
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
Generated on Tue Jul 12 2022 18:00:34 by 1.7.2