Merge pull request #6288 from dearblue/closing
[mruby.git] / src / load.c
blob3008a4cd163337536dd2bdf563bb7cab739231f2
1 /*
2 ** load.c - mruby binary loader
3 **
4 ** See Copyright Notice in mruby.h
5 */
7 #include <mruby.h>
8 #include <mruby/dump.h>
9 #include <mruby/irep.h>
10 #include <mruby/proc.h>
11 #include <mruby/string.h>
12 #include <mruby/debug.h>
13 #include <mruby/error.h>
14 #include <mruby/data.h>
15 #include <mruby/endian.h>
16 #include <mruby/internal.h>
17 #include <string.h>
19 #if SIZE_MAX < UINT32_MAX
20 # error size_t must be at least 32 bits wide
21 #endif
23 #define FLAG_SRC_MALLOC 1
24 #define FLAG_SRC_STATIC 0
26 #define SIZE_ERROR_MUL(nmemb, size) ((size_t)(nmemb) > SIZE_MAX / (size))
28 #define DEFINE_READ_IREP_FUNC(funcdecl, basecall) \
29 funcdecl \
30 { \
31 int ai = mrb_gc_arena_save(mrb); \
32 struct RProc *proc = basecall; \
33 struct mrb_irep *irep = (mrb_irep*)(proc ? proc->body.irep : NULL); \
34 if (irep) proc->body.irep = NULL; \
35 mrb_gc_arena_restore(mrb, ai); \
36 return irep; \
39 #ifndef MRB_NO_FLOAT
40 static double
41 str_to_double(mrb_state *mrb, const char *p)
43 /* dump IEEE754 little endian binary */
44 union {
45 char s[sizeof(double)];
46 double f;
47 } u;
49 if (littleendian) {
50 memcpy(u.s, p, sizeof(double));
52 else {
53 size_t i;
54 for (i=0; i<sizeof(double); i++) {
55 u.s[i] = p[sizeof(double)-i-1];
58 return u.f;
60 #endif
62 static mrb_bool
63 read_irep_record_1(mrb_state *mrb, const uint8_t *bin, const uint8_t *end, size_t *len, uint8_t flags, mrb_irep **irepp)
65 int i;
66 const uint8_t *src = bin;
67 ptrdiff_t diff;
68 uint16_t tt, pool_data_len, snl;
69 int plen;
70 mrb_pool_value *pool;
71 mrb_sym *syms;
72 int ai = mrb_gc_arena_save(mrb);
73 mrb_irep *irep = mrb_add_irep(mrb);
75 *irepp = irep;
77 /* skip record size */
78 src += sizeof(uint32_t);
80 /* number of local variable */
81 irep->nlocals = bin_to_uint16(src);
82 src += sizeof(uint16_t);
84 /* number of register variable */
85 irep->nregs = bin_to_uint16(src);
86 src += sizeof(uint16_t);
88 /* number of child irep */
89 irep->rlen = bin_to_uint16(src);
90 src += sizeof(uint16_t);
92 /* Binary Data Section */
93 /* ISEQ BLOCK (and CATCH HANDLER TABLE BLOCK) */
94 irep->clen = bin_to_uint16(src); /* number of catch handler */
95 src += sizeof(uint16_t);
96 irep->ilen = bin_to_uint32(src);
97 src += sizeof(uint32_t);
99 if (irep->ilen > 0) {
100 size_t data_len = sizeof(mrb_code) * irep->ilen +
101 sizeof(struct mrb_irep_catch_handler) * irep->clen;
102 mrb_static_assert(sizeof(struct mrb_irep_catch_handler) == 13);
103 if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
104 return FALSE;
106 if (src + data_len > end) return FALSE;
107 if ((flags & FLAG_SRC_MALLOC) == 0) {
108 irep->iseq = (mrb_code*)src;
109 irep->flags |= MRB_ISEQ_NO_FREE;
111 else {
112 void *buf = mrb_malloc(mrb, data_len);
113 irep->iseq = (mrb_code*)buf;
114 memcpy(buf, src, data_len);
116 src += data_len;
119 /* POOL BLOCK */
120 plen = bin_to_uint16(src); /* number of pool */
121 src += sizeof(uint16_t);
122 if (src > end) return FALSE;
123 if (plen > 0) {
124 if (SIZE_ERROR_MUL(plen, sizeof(mrb_value))) {
125 return FALSE;
127 irep->pool = pool = (mrb_pool_value*)mrb_calloc(mrb, sizeof(mrb_pool_value), plen);
129 for (i = 0; i < plen; i++) {
130 mrb_bool st = (flags & FLAG_SRC_MALLOC)==0;
132 tt = *src++; /* pool TT */
133 switch (tt) { /* pool data */
134 case IREP_TT_INT32:
136 if (src + sizeof(uint32_t) > end) return FALSE;
137 mrb_int v = (int32_t)bin_to_uint32(src);
138 src += sizeof(uint32_t);
139 #ifdef MRB_64BIT
140 pool[i].tt = IREP_TT_INT64;
141 pool[i].u.i64 = (int64_t)v;
142 #else
143 pool[i].tt = IREP_TT_INT32;
144 pool[i].u.i32 = v;
145 #endif
147 break;
148 case IREP_TT_INT64:
149 #ifdef MRB_INT64
151 if (src + sizeof(uint32_t)*2 > end) return FALSE;
152 uint64_t i64 = bin_to_uint32(src);
153 src += sizeof(uint32_t);
154 i64 <<= 32;
155 i64 |= bin_to_uint32(src);
156 src += sizeof(uint32_t);
157 pool[i].tt = tt;
158 pool[i].u.i64 = (int64_t)i64;
160 break;
161 #else
162 return FALSE;
163 #endif
165 case IREP_TT_BIGINT:
166 pool_data_len = bin_to_uint8(src) + 2; /* pool data length */
167 if (src + pool_data_len > end) return FALSE;
168 else {
169 char *p;
170 pool[i].tt = IREP_TT_BIGINT;
171 p = (char*)mrb_malloc(mrb, pool_data_len);
172 memcpy(p, src, pool_data_len);
173 pool[i].u.str = (const char*)p;
175 src += pool_data_len;
176 break;
178 case IREP_TT_FLOAT:
179 #ifndef MRB_NO_FLOAT
180 if (src + sizeof(double) > end) return FALSE;
181 pool[i].tt = tt;
182 pool[i].u.f = str_to_double(mrb, (const char*)src);
183 src += sizeof(double);
184 break;
185 #else
186 return FALSE; /* MRB_NO_FLOAT */
187 #endif
189 case IREP_TT_STR:
190 pool_data_len = bin_to_uint16(src); /* pool data length */
191 src += sizeof(uint16_t);
192 if (src + pool_data_len > end) return FALSE;
193 if (st) {
194 pool[i].tt = (pool_data_len<<2) | IREP_TT_SSTR;
195 pool[i].u.str = (const char*)src;
197 else {
198 char *p;
199 pool[i].tt = (pool_data_len<<2) | IREP_TT_STR;
200 p = (char*)mrb_malloc(mrb, pool_data_len+1);
201 memcpy(p, src, pool_data_len+1);
202 pool[i].u.str = (const char*)p;
204 src += pool_data_len + 1;
205 break;
207 default:
208 /* should not happen */
209 return FALSE;
211 irep->plen = i+1;
215 /* SYMS BLOCK */
216 irep->slen = bin_to_uint16(src); /* syms length */
217 src += sizeof(uint16_t);
218 if (src > end) return FALSE;
219 if (irep->slen > 0) {
220 if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) {
221 return FALSE;
223 irep->syms = syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen);
225 for (i = 0; i < irep->slen; i++) {
226 snl = bin_to_uint16(src); /* symbol name length */
227 src += sizeof(uint16_t);
229 if (snl == MRB_DUMP_NULL_SYM_LEN) {
230 syms[i] = 0;
231 continue;
234 if (src + snl > end) return FALSE;
235 if (flags & FLAG_SRC_MALLOC) {
236 syms[i] = mrb_intern(mrb, (char*)src, snl);
238 else {
239 syms[i] = mrb_intern_static(mrb, (char*)src, snl);
241 src += snl + 1;
242 mrb_gc_arena_restore(mrb, ai);
246 diff = src - bin;
247 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
248 *len = (size_t)diff;
250 return TRUE;
253 static mrb_bool
254 read_irep_record(mrb_state *mrb, const uint8_t *bin, const uint8_t *end, size_t *len, uint8_t flags, mrb_irep **irepp)
256 int ai = mrb_gc_arena_save(mrb);
257 mrb_bool readsuccess = read_irep_record_1(mrb, bin, end, len, flags, irepp);
258 mrb_irep **reps;
259 int i;
261 mrb_gc_arena_restore(mrb, ai);
262 if (!readsuccess) {
263 return FALSE;
266 reps = (mrb_irep**)mrb_calloc(mrb, (*irepp)->rlen, sizeof(mrb_irep*));
267 (*irepp)->reps = (const mrb_irep**)reps;
269 bin += *len;
270 for (i=0; i<(*irepp)->rlen; i++) {
271 size_t rlen;
273 readsuccess = read_irep_record(mrb, bin, end, &rlen, flags, &reps[i]);
274 mrb_gc_arena_restore(mrb, ai);
275 if (!readsuccess) {
276 return FALSE;
278 bin += rlen;
279 *len += rlen;
282 return TRUE;
285 static mrb_irep*
286 read_section_irep(mrb_state *mrb, const uint8_t *bin, size_t size, uint8_t flags, struct RProc **proc)
288 if (size < sizeof(struct rite_section_irep_header)) return NULL;
290 * This proc object keeps all the data in progress to avoid memory leaks
291 * if something goes wrong while reading irep.
293 *proc = mrb_proc_new(mrb, NULL);
295 mrb_irep **irepp = (mrb_irep**)&(*proc)->body.irep;
296 size_t len;
297 bin += sizeof(struct rite_section_irep_header);
298 if (read_irep_record(mrb, bin, bin+size, &len, flags, irepp)) {
299 return *irepp;
301 else {
302 return NULL;
306 static int
307 read_debug_record(mrb_state *mrb, const uint8_t *start, const uint8_t *end, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len)
309 const uint8_t *bin = start;
310 ptrdiff_t diff;
311 size_t record_size;
312 uint16_t f_idx;
313 int i;
314 mrb_irep_debug_info *debug;
316 if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
318 irep->debug_info = debug = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info));
319 debug->pc_count = (uint32_t)irep->ilen;
321 record_size = (size_t)bin_to_uint32(bin);
322 bin += sizeof(uint32_t);
324 debug->flen = bin_to_uint16(bin);
325 bin += sizeof(uint16_t);
326 if (bin > end) return MRB_DUMP_GENERAL_FAILURE;
327 debug->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*));
329 for (f_idx = 0; f_idx < debug->flen; f_idx++) {
330 mrb_irep_debug_info_file *file;
331 uint16_t filename_idx;
333 if (bin > end) return MRB_DUMP_GENERAL_FAILURE;
334 file = (mrb_irep_debug_info_file*)mrb_calloc(mrb, 1, sizeof(*file));
335 debug->files[f_idx] = file;
337 file->start_pos = bin_to_uint32(bin);
338 bin += sizeof(uint32_t);
340 /* filename */
341 filename_idx = bin_to_uint16(bin);
342 bin += sizeof(uint16_t);
343 mrb_assert(filename_idx < filenames_len);
344 file->filename_sym = filenames[filename_idx];
346 file->line_entry_count = bin_to_uint32(bin);
347 bin += sizeof(uint32_t);
348 file->line_type = (mrb_debug_line_type)bin_to_uint8(bin);
349 bin += sizeof(uint8_t);
350 switch (file->line_type) {
351 case mrb_debug_line_ary: {
352 size_t l = sizeof(uint16_t) * (size_t)file->line_entry_count;
354 if (bin + l > end) return MRB_DUMP_GENERAL_FAILURE;
355 uint16_t *ary = (uint16_t*)mrb_malloc(mrb, l);
356 for (l = 0; l < file->line_entry_count; l++) {
357 ary[l] = bin_to_uint16(bin);
358 bin += sizeof(uint16_t);
360 file->lines.ary = ary;
361 } break;
363 case mrb_debug_line_flat_map: {
364 size_t c = (size_t)file->line_entry_count;
365 size_t n = sizeof(mrb_irep_debug_info_line);
367 if (bin + c*n > end) return MRB_DUMP_GENERAL_FAILURE;
368 mrb_irep_debug_info_line *flat_map = (mrb_irep_debug_info_line*)mrb_calloc(mrb, c, n);
369 for (size_t l = 0; l < file->line_entry_count; l++) {
370 flat_map[l].start_pos = bin_to_uint32(bin);
371 bin += sizeof(uint32_t);
372 flat_map[l].line = bin_to_uint16(bin);
373 bin += sizeof(uint16_t);
375 file->lines.flat_map = flat_map;
376 } break;
378 case mrb_debug_line_packed_map: {
379 size_t l = (size_t)file->line_entry_count;
381 if (bin + l > end) return MRB_DUMP_GENERAL_FAILURE;
382 uint8_t *packed_map = (uint8_t*)mrb_malloc(mrb, l);
383 memcpy(packed_map, bin, file->line_entry_count);
384 file->lines.packed_map = packed_map;
385 bin += file->line_entry_count;
386 } break;
388 default: return MRB_DUMP_GENERAL_FAILURE;
392 diff = bin - start;
393 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
395 if (record_size != (size_t)diff) {
396 return MRB_DUMP_GENERAL_FAILURE;
399 for (i = 0; i < irep->rlen; i++) {
400 size_t len;
401 int ret;
403 ret = read_debug_record(mrb, bin, end, (mrb_irep*)irep->reps[i], &len, filenames, filenames_len);
404 if (ret != MRB_DUMP_OK) return ret;
405 bin += len;
408 diff = bin - start;
409 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
410 *record_len = (size_t)diff;
412 return MRB_DUMP_OK;
415 static int
416 read_section_debug(mrb_state *mrb, const uint8_t *start, size_t size, mrb_irep *irep, uint8_t flags)
418 const uint8_t *bin;
419 const uint8_t *end = start + size;
420 ptrdiff_t diff;
421 struct rite_section_debug_header *header;
422 uint16_t i;
423 size_t len = 0;
424 int result;
425 uint16_t filenames_len;
426 mrb_sym *filenames;
427 mrb_value filenames_obj;
429 bin = start;
430 header = (struct rite_section_debug_header*)bin;
431 bin += sizeof(struct rite_section_debug_header);
433 filenames_len = bin_to_uint16(bin);
434 bin += sizeof(uint16_t);
435 if (bin > end) return MRB_DUMP_GENERAL_FAILURE;
436 filenames_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)filenames_len);
437 filenames = (mrb_sym*)RSTRING_PTR(filenames_obj);
438 for (i = 0; i < filenames_len; i++) {
439 uint16_t f_len = bin_to_uint16(bin);
440 bin += sizeof(uint16_t);
441 if (bin + f_len > end) {
442 result = MRB_DUMP_GENERAL_FAILURE;
443 goto debug_exit;
445 if (flags & FLAG_SRC_MALLOC) {
446 filenames[i] = mrb_intern(mrb, (const char*)bin, (size_t)f_len);
448 else {
449 filenames[i] = mrb_intern_static(mrb, (const char*)bin, (size_t)f_len);
451 bin += f_len;
454 result = read_debug_record(mrb, bin, end, irep, &len, filenames, filenames_len);
455 if (result != MRB_DUMP_OK) goto debug_exit;
457 bin += len;
458 diff = bin - start;
459 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
460 if ((uint32_t)diff != bin_to_uint32(header->section_size)) {
461 result = MRB_DUMP_GENERAL_FAILURE;
464 debug_exit:
465 mrb_str_resize(mrb, filenames_obj, 0);
466 return result;
469 static int
470 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)
472 const uint8_t *bin = start;
473 mrb_sym *lv;
474 ptrdiff_t diff;
475 int i;
477 if (irep->nlocals == 0) return MRB_DUMP_GENERAL_FAILURE;
478 irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (irep->nlocals - 1));
480 for (i = 0; i + 1 < irep->nlocals; i++) {
481 uint16_t const sym_idx = bin_to_uint16(bin);
482 bin += sizeof(uint16_t);
483 if (sym_idx == RITE_LV_NULL_MARK) {
484 lv[i] = 0;
486 else {
487 if (sym_idx >= syms_len) {
488 return MRB_DUMP_GENERAL_FAILURE;
490 lv[i] = syms[sym_idx];
494 for (i = 0; i < irep->rlen; i++) {
495 size_t len;
496 int ret;
498 ret = read_lv_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, syms, syms_len);
499 if (ret != MRB_DUMP_OK) return ret;
500 bin += len;
503 diff = bin - start;
504 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
505 *record_len = (size_t)diff;
507 return MRB_DUMP_OK;
510 static int
511 read_section_lv(mrb_state *mrb, const uint8_t *start, size_t size, mrb_irep *irep, uint8_t flags)
513 const uint8_t *bin;
514 const uint8_t *end = start + size;
515 ptrdiff_t diff;
516 struct rite_section_lv_header const *header;
517 uint32_t i;
518 size_t len = 0;
519 int result;
520 uint32_t syms_len;
521 mrb_sym *syms;
522 mrb_value syms_obj;
523 mrb_sym (*intern_func)(mrb_state*, const char*, size_t) =
524 (flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static;
526 bin = start;
527 header = (struct rite_section_lv_header const*)bin;
528 bin += sizeof(struct rite_section_lv_header);
530 syms_len = bin_to_uint32(bin);
531 bin += sizeof(uint32_t);
532 if (bin > end) return MRB_DUMP_READ_FAULT;
533 syms_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)syms_len);
534 syms = (mrb_sym*)RSTRING_PTR(syms_obj);
535 for (i = 0; i < syms_len; i++) {
536 uint16_t const str_len = bin_to_uint16(bin);
537 bin += sizeof(uint16_t);
538 if (bin > end) return MRB_DUMP_READ_FAULT;
539 syms[i] = intern_func(mrb, (const char*)bin, str_len);
540 bin += str_len;
543 result = read_lv_record(mrb, bin, irep, &len, syms, syms_len);
544 if (result != MRB_DUMP_OK) goto lv_exit;
546 bin += len;
547 diff = bin - start;
548 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
549 if ((uint32_t)diff != bin_to_uint32(header->section_size)) {
550 result = MRB_DUMP_GENERAL_FAILURE;
553 lv_exit:
554 mrb_str_resize(mrb, syms_obj, 0);
555 return result;
558 static int
559 read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint8_t *flags)
561 const struct rite_binary_header *header = (const struct rite_binary_header*)bin;
563 if (bufsize < sizeof(struct rite_binary_header)) {
564 return MRB_DUMP_READ_FAULT;
567 if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) != 0) {
568 return MRB_DUMP_INVALID_FILE_HEADER;
571 /* if major version is different, they are incompatible */
572 if (memcmp(header->major_version, RITE_BINARY_MAJOR_VER, sizeof(header->major_version)) != 0) {
573 return MRB_DUMP_INVALID_FILE_HEADER;
575 /* if minor version is different, we can accept the older version */
576 if (memcmp(header->minor_version, RITE_BINARY_MINOR_VER, sizeof(header->minor_version)) > 0) {
577 return MRB_DUMP_INVALID_FILE_HEADER;
580 *bin_size = (size_t)bin_to_uint32(header->binary_size);
582 if (bufsize < *bin_size) {
583 return MRB_DUMP_READ_FAULT;
586 return MRB_DUMP_OK;
589 static struct RProc*
590 read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
592 int result;
593 struct RProc *proc = NULL;
594 mrb_irep *irep = NULL;
595 const struct rite_section_header *section_header;
596 size_t bin_size = 0;
598 if ((mrb == NULL) || (bin == NULL)) {
599 return NULL;
602 result = read_binary_header(bin, bufsize, &bin_size, &flags);
603 if (result != MRB_DUMP_OK) {
604 return NULL;
607 bin += sizeof(struct rite_binary_header);
608 bin_size -= sizeof(struct rite_binary_header);
609 while (bin_size > sizeof(struct rite_section_header)) {
610 section_header = (const struct rite_section_header*)bin;
611 uint32_t section_size = bin_to_uint32(section_header->section_size);
612 if (bin_size < section_size) return NULL;
613 if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) {
614 irep = read_section_irep(mrb, bin, bin_size, flags, &proc);
615 if (!irep) return NULL;
617 else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) {
618 if (!irep) return NULL; /* corrupted data */
619 result = read_section_debug(mrb, bin, bin_size, irep, flags);
620 if (result < MRB_DUMP_OK) {
621 return NULL;
624 else if (memcmp(section_header->section_ident, RITE_SECTION_LV_IDENT, sizeof(section_header->section_ident)) == 0) {
625 if (!irep) return NULL;
626 result = read_section_lv(mrb, bin, bin_size, irep, flags);
627 if (result < MRB_DUMP_OK) {
628 return NULL;
631 else if (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0) {
632 break;
635 bin += section_size;
636 bin_size -= section_size;
639 return proc;
642 static struct RProc*
643 mrb_proc_read_irep(mrb_state *mrb, const uint8_t *bin)
645 uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC;
647 return read_irep(mrb, bin, (size_t)UINT32_MAX, flags);
650 DEFINE_READ_IREP_FUNC(
651 mrb_irep *mrb_read_irep(mrb_state *mrb, const uint8_t *bin),
652 mrb_proc_read_irep(mrb, bin))
654 static struct RProc*
655 mrb_proc_read_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize)
657 return read_irep(mrb, (const uint8_t*)buf, bufsize, FLAG_SRC_MALLOC);
660 DEFINE_READ_IREP_FUNC(
661 MRB_API mrb_irep *mrb_read_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize),
662 mrb_proc_read_irep_buf(mrb, buf, bufsize))
664 void mrb_exc_set(mrb_state *mrb, mrb_value exc);
666 static void
667 irep_error(mrb_state *mrb)
669 mrb_exc_set(mrb, mrb_exc_new_lit(mrb, E_SCRIPT_ERROR, "irep load error"));
672 static mrb_value
673 load_irep(mrb_state *mrb, struct RProc *proc, mrb_ccontext *c)
675 if (!proc || !proc->body.irep) {
676 irep_error(mrb);
677 return mrb_nil_value();
679 proc->c = NULL;
680 if (c && c->dump_result) mrb_codedump_all(mrb, proc);
681 if (c && c->no_exec) return mrb_obj_value(proc);
682 return mrb_top_run(mrb, proc, mrb_top_self(mrb), 0);
685 MRB_API mrb_value
686 mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrb_ccontext *c)
688 struct RProc *proc = mrb_proc_read_irep(mrb, bin);
689 if (!proc) return mrb_undef_value();
690 return load_irep(mrb, proc, c);
693 MRB_API mrb_value
694 mrb_load_irep_buf_cxt(mrb_state *mrb, const void *buf, size_t bufsize, mrb_ccontext *c)
696 return load_irep(mrb, mrb_proc_read_irep_buf(mrb, buf, bufsize), c);
699 MRB_API mrb_value
700 mrb_load_irep(mrb_state *mrb, const uint8_t *bin)
702 return mrb_load_irep_cxt(mrb, bin, NULL);
705 MRB_API mrb_value
706 mrb_load_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize)
708 return mrb_load_irep_buf_cxt(mrb, buf, bufsize, NULL);
711 MRB_API mrb_value
712 mrb_load_proc(mrb_state *mrb, const struct RProc *proc)
714 return mrb_top_run(mrb, proc, mrb_top_self(mrb), 0);
717 #ifndef MRB_NO_STDIO
719 static struct RProc*
720 mrb_proc_read_irep_file(mrb_state *mrb, FILE *fp)
722 struct RProc *proc = NULL;
723 uint8_t *buf;
724 const size_t header_size = sizeof(struct rite_binary_header);
725 size_t buf_size = 0;
726 uint8_t flags = 0;
727 int result;
729 if ((mrb == NULL) || (fp == NULL)) {
730 return NULL;
733 buf = (uint8_t*)mrb_malloc(mrb, header_size);
734 if (fread(buf, header_size, 1, fp) == 0) {
735 goto irep_exit;
737 result = read_binary_header(buf, (size_t)-1, &buf_size, &flags);
738 if (result != MRB_DUMP_OK || buf_size <= header_size) {
739 goto irep_exit;
742 buf = (uint8_t*)mrb_realloc(mrb, buf, buf_size);
743 if (fread(buf+header_size, buf_size-header_size, 1, fp) == 0) {
744 goto irep_exit;
746 proc = read_irep(mrb, buf, (size_t)-1, FLAG_SRC_MALLOC);
748 irep_exit:
749 mrb_free(mrb, buf);
750 return proc;
753 DEFINE_READ_IREP_FUNC(
754 mrb_irep *mrb_read_irep_file(mrb_state *mrb, FILE *fp),
755 mrb_proc_read_irep_file(mrb, fp))
757 MRB_API mrb_value
758 mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrb_ccontext *c)
760 return load_irep(mrb, mrb_proc_read_irep_file(mrb, fp), c);
763 MRB_API mrb_value
764 mrb_load_irep_file(mrb_state *mrb, FILE* fp)
766 return mrb_load_irep_file_cxt(mrb, fp, NULL);
768 #endif /* MRB_NO_STDIO */