mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

Committer:
mzta
Date:
Mon Apr 13 05:20:15 2015 +0000
Revision:
1:8ccd1d494a4b
Parent:
0:158c61bb030f
- code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:158c61bb030f 1 /*
mzta 0:158c61bb030f 2 ** dump.c - mruby binary dumper (mrbc binary format)
mzta 0:158c61bb030f 3 **
mzta 0:158c61bb030f 4 ** See Copyright Notice in mruby.h
mzta 0:158c61bb030f 5 */
mzta 0:158c61bb030f 6
mzta 0:158c61bb030f 7 #include <ctype.h>
mzta 0:158c61bb030f 8 #include <string.h>
mzta 0:158c61bb030f 9 #include <limits.h>
mzta 0:158c61bb030f 10 #include "mruby/dump.h"
mzta 0:158c61bb030f 11 #include "mruby/string.h"
mzta 0:158c61bb030f 12 #include "mruby/irep.h"
mzta 0:158c61bb030f 13 #include "mruby/numeric.h"
mzta 0:158c61bb030f 14 #include "mruby/debug.h"
mzta 0:158c61bb030f 15
mzta 0:158c61bb030f 16 #define FLAG_BYTEORDER_NATIVE 2
mzta 0:158c61bb030f 17 #define FLAG_BYTEORDER_NONATIVE 0
mzta 0:158c61bb030f 18
mzta 0:158c61bb030f 19 #ifdef ENABLE_STDIO
mzta 0:158c61bb030f 20
mzta 0:158c61bb030f 21 static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep);
mzta 0:158c61bb030f 22
mzta 0:158c61bb030f 23 #if UINT32_MAX > SIZE_MAX
mzta 0:158c61bb030f 24 # error This code cannot be built on your environment.
mzta 0:158c61bb030f 25 #endif
mzta 0:158c61bb030f 26
mzta 0:158c61bb030f 27 static size_t
mzta 0:158c61bb030f 28 write_padding(uint8_t *buf)
mzta 0:158c61bb030f 29 {
mzta 0:158c61bb030f 30 const size_t align = MRB_DUMP_ALIGNMENT;
mzta 0:158c61bb030f 31 size_t pad_len = -(intptr_t)buf & (align-1);
mzta 0:158c61bb030f 32 if (pad_len > 0) {
mzta 0:158c61bb030f 33 memset(buf, 0, pad_len);
mzta 0:158c61bb030f 34 }
mzta 0:158c61bb030f 35 return pad_len;
mzta 0:158c61bb030f 36 }
mzta 0:158c61bb030f 37
mzta 0:158c61bb030f 38 static size_t
mzta 0:158c61bb030f 39 get_irep_header_size(mrb_state *mrb)
mzta 0:158c61bb030f 40 {
mzta 0:158c61bb030f 41 size_t size = 0;
mzta 0:158c61bb030f 42
mzta 0:158c61bb030f 43 size += sizeof(uint32_t) * 1;
mzta 0:158c61bb030f 44 size += sizeof(uint16_t) * 3;
mzta 0:158c61bb030f 45
mzta 0:158c61bb030f 46 return size;
mzta 0:158c61bb030f 47 }
mzta 0:158c61bb030f 48
mzta 0:158c61bb030f 49 static ptrdiff_t
mzta 0:158c61bb030f 50 write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
mzta 0:158c61bb030f 51 {
mzta 0:158c61bb030f 52 uint8_t *cur = buf;
mzta 0:158c61bb030f 53
mzta 0:158c61bb030f 54 cur += uint32_to_bin(get_irep_record_size_1(mrb, irep), cur); /* record size */
mzta 0:158c61bb030f 55 cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */
mzta 0:158c61bb030f 56 cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */
mzta 0:158c61bb030f 57 cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */
mzta 0:158c61bb030f 58
mzta 0:158c61bb030f 59 return cur - buf;
mzta 0:158c61bb030f 60 }
mzta 0:158c61bb030f 61
mzta 0:158c61bb030f 62
mzta 0:158c61bb030f 63 static size_t
mzta 0:158c61bb030f 64 get_iseq_block_size(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 65 {
mzta 0:158c61bb030f 66 size_t size = 0;
mzta 0:158c61bb030f 67
mzta 0:158c61bb030f 68 size += sizeof(uint32_t); /* ilen */
mzta 0:158c61bb030f 69 size += sizeof(uint32_t); /* max padding */
mzta 0:158c61bb030f 70 size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */
mzta 0:158c61bb030f 71
mzta 0:158c61bb030f 72 return size;
mzta 0:158c61bb030f 73 }
mzta 0:158c61bb030f 74
mzta 0:158c61bb030f 75 static ptrdiff_t
mzta 0:158c61bb030f 76 write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf, uint8_t flags)
mzta 0:158c61bb030f 77 {
mzta 0:158c61bb030f 78 uint8_t *cur = buf;
mzta 0:158c61bb030f 79 uint32_t iseq_no;
mzta 0:158c61bb030f 80
mzta 0:158c61bb030f 81 cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */
mzta 0:158c61bb030f 82 cur += write_padding(cur);
mzta 0:158c61bb030f 83 if (flags & FLAG_BYTEORDER_NATIVE) {
mzta 0:158c61bb030f 84 memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code));
mzta 0:158c61bb030f 85 cur += irep->ilen * sizeof(mrb_code);
mzta 0:158c61bb030f 86 }
mzta 0:158c61bb030f 87 else {
mzta 0:158c61bb030f 88 for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
mzta 0:158c61bb030f 89 cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */
mzta 0:158c61bb030f 90 }
mzta 0:158c61bb030f 91 }
mzta 0:158c61bb030f 92
mzta 0:158c61bb030f 93 return cur - buf;
mzta 0:158c61bb030f 94 }
mzta 0:158c61bb030f 95
mzta 0:158c61bb030f 96
mzta 0:158c61bb030f 97 static size_t
mzta 0:158c61bb030f 98 get_pool_block_size(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 99 {
mzta 0:158c61bb030f 100 size_t size = 0;
mzta 0:158c61bb030f 101 size_t pool_no;
mzta 0:158c61bb030f 102 mrb_value str;
mzta 0:158c61bb030f 103 char buf[32];
mzta 0:158c61bb030f 104
mzta 0:158c61bb030f 105 size += sizeof(uint32_t); /* plen */
mzta 0:158c61bb030f 106 size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */
mzta 0:158c61bb030f 107
mzta 0:158c61bb030f 108 for (pool_no = 0; pool_no < irep->plen; pool_no++) {
mzta 0:158c61bb030f 109 int ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 110
mzta 0:158c61bb030f 111 switch (mrb_type(irep->pool[pool_no])) {
mzta 0:158c61bb030f 112 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 113 str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
mzta 0:158c61bb030f 114 {
mzta 0:158c61bb030f 115 mrb_int len = RSTRING_LEN(str);
mzta 0:158c61bb030f 116 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
mzta 0:158c61bb030f 117 size += (size_t)len;
mzta 0:158c61bb030f 118 }
mzta 0:158c61bb030f 119 break;
mzta 0:158c61bb030f 120
mzta 0:158c61bb030f 121 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 122 {
mzta 0:158c61bb030f 123 int len;
mzta 0:158c61bb030f 124 len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no]));
mzta 0:158c61bb030f 125 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
mzta 0:158c61bb030f 126 size += (size_t)len;
mzta 0:158c61bb030f 127 }
mzta 0:158c61bb030f 128 break;
mzta 0:158c61bb030f 129
mzta 0:158c61bb030f 130 case MRB_TT_STRING:
mzta 0:158c61bb030f 131 {
mzta 0:158c61bb030f 132 mrb_int len = RSTRING_LEN(irep->pool[pool_no]);
mzta 0:158c61bb030f 133 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
mzta 0:158c61bb030f 134 size += (size_t)len;
mzta 0:158c61bb030f 135 }
mzta 0:158c61bb030f 136 break;
mzta 0:158c61bb030f 137
mzta 0:158c61bb030f 138 default:
mzta 0:158c61bb030f 139 break;
mzta 0:158c61bb030f 140 }
mzta 0:158c61bb030f 141 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 142 }
mzta 0:158c61bb030f 143
mzta 0:158c61bb030f 144 return size;
mzta 0:158c61bb030f 145 }
mzta 0:158c61bb030f 146
mzta 0:158c61bb030f 147 static ptrdiff_t
mzta 0:158c61bb030f 148 write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
mzta 0:158c61bb030f 149 {
mzta 0:158c61bb030f 150 size_t pool_no;
mzta 0:158c61bb030f 151 uint8_t *cur = buf;
mzta 0:158c61bb030f 152 uint16_t len;
mzta 0:158c61bb030f 153 mrb_value str;
mzta 0:158c61bb030f 154 const char *char_ptr;
mzta 0:158c61bb030f 155 char char_buf[30];
mzta 0:158c61bb030f 156
mzta 0:158c61bb030f 157 cur += uint32_to_bin(irep->plen, cur); /* number of pool */
mzta 0:158c61bb030f 158
mzta 0:158c61bb030f 159 for (pool_no = 0; pool_no < irep->plen; pool_no++) {
mzta 0:158c61bb030f 160 int ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 161
mzta 0:158c61bb030f 162 switch (mrb_type(irep->pool[pool_no])) {
mzta 0:158c61bb030f 163 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 164 cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */
mzta 0:158c61bb030f 165 str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
mzta 0:158c61bb030f 166 char_ptr = RSTRING_PTR(str);
mzta 0:158c61bb030f 167 {
mzta 0:158c61bb030f 168 mrb_int tlen;
mzta 0:158c61bb030f 169
mzta 0:158c61bb030f 170 tlen = RSTRING_LEN(str);
mzta 0:158c61bb030f 171 mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX);
mzta 0:158c61bb030f 172 len = (uint16_t)tlen;
mzta 0:158c61bb030f 173 }
mzta 0:158c61bb030f 174 break;
mzta 0:158c61bb030f 175
mzta 0:158c61bb030f 176 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 177 cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */
mzta 0:158c61bb030f 178 {
mzta 0:158c61bb030f 179 int tlen;
mzta 0:158c61bb030f 180 tlen = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no]));
mzta 0:158c61bb030f 181 mrb_assert_int_fit(int, tlen, uint16_t, UINT16_MAX);
mzta 0:158c61bb030f 182 len = (uint16_t)tlen;
mzta 0:158c61bb030f 183 }
mzta 0:158c61bb030f 184 char_ptr = &char_buf[0];
mzta 0:158c61bb030f 185 break;
mzta 0:158c61bb030f 186
mzta 0:158c61bb030f 187 case MRB_TT_STRING:
mzta 0:158c61bb030f 188 cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */
mzta 0:158c61bb030f 189 char_ptr = RSTRING_PTR(irep->pool[pool_no]);
mzta 0:158c61bb030f 190 {
mzta 0:158c61bb030f 191 mrb_int tlen;
mzta 0:158c61bb030f 192
mzta 0:158c61bb030f 193 tlen = RSTRING_LEN(irep->pool[pool_no]);
mzta 0:158c61bb030f 194 mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX);
mzta 0:158c61bb030f 195 len = (uint16_t)tlen;
mzta 0:158c61bb030f 196 }
mzta 0:158c61bb030f 197 break;
mzta 0:158c61bb030f 198
mzta 0:158c61bb030f 199 default:
mzta 0:158c61bb030f 200 continue;
mzta 0:158c61bb030f 201 }
mzta 0:158c61bb030f 202
mzta 0:158c61bb030f 203 cur += uint16_to_bin(len, cur); /* data length */
mzta 0:158c61bb030f 204 memcpy(cur, char_ptr, (size_t)len);
mzta 0:158c61bb030f 205 cur += len;
mzta 0:158c61bb030f 206
mzta 0:158c61bb030f 207 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 208 }
mzta 0:158c61bb030f 209
mzta 0:158c61bb030f 210 return cur - buf;
mzta 0:158c61bb030f 211 }
mzta 0:158c61bb030f 212
mzta 0:158c61bb030f 213
mzta 0:158c61bb030f 214 static size_t
mzta 0:158c61bb030f 215 get_syms_block_size(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 216 {
mzta 0:158c61bb030f 217 size_t size = 0;
mzta 0:158c61bb030f 218 uint32_t sym_no;
mzta 0:158c61bb030f 219 mrb_int len;
mzta 0:158c61bb030f 220
mzta 0:158c61bb030f 221 size += sizeof(uint32_t); /* slen */
mzta 0:158c61bb030f 222 for (sym_no = 0; sym_no < irep->slen; sym_no++) {
mzta 0:158c61bb030f 223 size += sizeof(uint16_t); /* snl(n) */
mzta 0:158c61bb030f 224 if (irep->syms[sym_no] != 0) {
mzta 0:158c61bb030f 225 mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
mzta 0:158c61bb030f 226 size += len + 1; /* sn(n) + null char */
mzta 0:158c61bb030f 227 }
mzta 0:158c61bb030f 228 }
mzta 0:158c61bb030f 229
mzta 0:158c61bb030f 230 return size;
mzta 0:158c61bb030f 231 }
mzta 0:158c61bb030f 232
mzta 0:158c61bb030f 233 static ptrdiff_t
mzta 0:158c61bb030f 234 write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
mzta 0:158c61bb030f 235 {
mzta 0:158c61bb030f 236 uint32_t sym_no;
mzta 0:158c61bb030f 237 uint8_t *cur = buf;
mzta 0:158c61bb030f 238 const char *name;
mzta 0:158c61bb030f 239
mzta 0:158c61bb030f 240 cur += uint32_to_bin(irep->slen, cur); /* number of symbol */
mzta 0:158c61bb030f 241
mzta 0:158c61bb030f 242 for (sym_no = 0; sym_no < irep->slen; sym_no++) {
mzta 0:158c61bb030f 243 if (irep->syms[sym_no] != 0) {
mzta 0:158c61bb030f 244 mrb_int len;
mzta 0:158c61bb030f 245
mzta 0:158c61bb030f 246 name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
mzta 0:158c61bb030f 247
mzta 0:158c61bb030f 248 mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX);
mzta 0:158c61bb030f 249 cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */
mzta 0:158c61bb030f 250 memcpy(cur, name, len); /* symbol name */
mzta 0:158c61bb030f 251 cur += (uint16_t)len;
mzta 0:158c61bb030f 252 *cur++ = '\0';
mzta 0:158c61bb030f 253 }
mzta 0:158c61bb030f 254 else {
mzta 0:158c61bb030f 255 cur += uint16_to_bin(MRB_DUMP_NULL_SYM_LEN, cur); /* length of symbol name */
mzta 0:158c61bb030f 256 }
mzta 0:158c61bb030f 257 }
mzta 0:158c61bb030f 258
mzta 0:158c61bb030f 259 return cur - buf;
mzta 0:158c61bb030f 260 }
mzta 0:158c61bb030f 261
mzta 0:158c61bb030f 262 static size_t
mzta 0:158c61bb030f 263 get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 264 {
mzta 0:158c61bb030f 265 size_t size = 0;
mzta 0:158c61bb030f 266
mzta 0:158c61bb030f 267 size += get_irep_header_size(mrb);
mzta 0:158c61bb030f 268 size += get_iseq_block_size(mrb, irep);
mzta 0:158c61bb030f 269 size += get_pool_block_size(mrb, irep);
mzta 0:158c61bb030f 270 size += get_syms_block_size(mrb, irep);
mzta 0:158c61bb030f 271 return size;
mzta 0:158c61bb030f 272 }
mzta 0:158c61bb030f 273
mzta 0:158c61bb030f 274 static size_t
mzta 0:158c61bb030f 275 get_irep_record_size(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 276 {
mzta 0:158c61bb030f 277 size_t size = 0;
mzta 0:158c61bb030f 278 size_t irep_no;
mzta 0:158c61bb030f 279
mzta 0:158c61bb030f 280 size = get_irep_record_size_1(mrb, irep);
mzta 0:158c61bb030f 281 for (irep_no = 0; irep_no < irep->rlen; irep_no++) {
mzta 0:158c61bb030f 282 size += get_irep_record_size(mrb, irep->reps[irep_no]);
mzta 0:158c61bb030f 283 }
mzta 0:158c61bb030f 284 return size;
mzta 0:158c61bb030f 285 }
mzta 0:158c61bb030f 286
mzta 0:158c61bb030f 287 static int
mzta 0:158c61bb030f 288 write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags)
mzta 0:158c61bb030f 289 {
mzta 0:158c61bb030f 290 uint32_t i;
mzta 0:158c61bb030f 291 uint8_t *src = bin;
mzta 0:158c61bb030f 292
mzta 0:158c61bb030f 293 if (irep == NULL) {
mzta 0:158c61bb030f 294 return MRB_DUMP_INVALID_IREP;
mzta 0:158c61bb030f 295 }
mzta 0:158c61bb030f 296
mzta 0:158c61bb030f 297 *irep_record_size = get_irep_record_size_1(mrb, irep);
mzta 0:158c61bb030f 298 if (*irep_record_size == 0) {
mzta 0:158c61bb030f 299 return MRB_DUMP_GENERAL_FAILURE;
mzta 0:158c61bb030f 300 }
mzta 0:158c61bb030f 301
mzta 0:158c61bb030f 302 bin += write_irep_header(mrb, irep, bin);
mzta 0:158c61bb030f 303 bin += write_iseq_block(mrb, irep, bin, flags);
mzta 0:158c61bb030f 304 bin += write_pool_block(mrb, irep, bin);
mzta 0:158c61bb030f 305 bin += write_syms_block(mrb, irep, bin);
mzta 0:158c61bb030f 306
mzta 0:158c61bb030f 307 for (i = 0; i < irep->rlen; i++) {
mzta 0:158c61bb030f 308 int result;
mzta 0:158c61bb030f 309 size_t rsize;
mzta 0:158c61bb030f 310
mzta 0:158c61bb030f 311 result = write_irep_record(mrb, irep->reps[i], bin, &rsize, flags);
mzta 0:158c61bb030f 312 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 313 return result;
mzta 0:158c61bb030f 314 }
mzta 0:158c61bb030f 315 bin += rsize;
mzta 0:158c61bb030f 316 }
mzta 0:158c61bb030f 317 *irep_record_size = bin - src;
mzta 0:158c61bb030f 318 return MRB_DUMP_OK;
mzta 0:158c61bb030f 319 }
mzta 0:158c61bb030f 320
mzta 0:158c61bb030f 321 static uint32_t
mzta 0:158c61bb030f 322 write_footer(mrb_state *mrb, uint8_t *bin)
mzta 0:158c61bb030f 323 {
mzta 0:158c61bb030f 324 struct rite_binary_footer footer;
mzta 0:158c61bb030f 325
mzta 0:158c61bb030f 326 memcpy(footer.section_identify, RITE_BINARY_EOF, sizeof(footer.section_identify));
mzta 0:158c61bb030f 327 uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size);
mzta 0:158c61bb030f 328 memcpy(bin, &footer, sizeof(struct rite_binary_footer));
mzta 0:158c61bb030f 329
mzta 0:158c61bb030f 330 return sizeof(struct rite_binary_footer);
mzta 0:158c61bb030f 331 }
mzta 0:158c61bb030f 332
mzta 0:158c61bb030f 333
mzta 0:158c61bb030f 334 static int
mzta 0:158c61bb030f 335 write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin)
mzta 0:158c61bb030f 336 {
mzta 0:158c61bb030f 337 struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin;
mzta 0:158c61bb030f 338
mzta 0:158c61bb030f 339 memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify));
mzta 0:158c61bb030f 340
mzta 0:158c61bb030f 341 mrb_assert_int_fit(size_t, section_size, uint32_t, UINT32_MAX);
mzta 0:158c61bb030f 342 uint32_to_bin((uint32_t)section_size, header->section_size);
mzta 0:158c61bb030f 343 memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version));
mzta 0:158c61bb030f 344
mzta 0:158c61bb030f 345 return MRB_DUMP_OK;
mzta 0:158c61bb030f 346 }
mzta 0:158c61bb030f 347
mzta 0:158c61bb030f 348 static int
mzta 0:158c61bb030f 349 write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *len_p, uint8_t flags)
mzta 0:158c61bb030f 350 {
mzta 0:158c61bb030f 351 int result;
mzta 0:158c61bb030f 352 size_t rsize = 0;
mzta 0:158c61bb030f 353 uint8_t *cur = bin;
mzta 0:158c61bb030f 354
mzta 0:158c61bb030f 355 if (mrb == NULL || bin == NULL) {
mzta 0:158c61bb030f 356 return MRB_DUMP_INVALID_ARGUMENT;
mzta 0:158c61bb030f 357 }
mzta 0:158c61bb030f 358
mzta 0:158c61bb030f 359 cur += sizeof(struct rite_section_irep_header);
mzta 0:158c61bb030f 360
mzta 0:158c61bb030f 361 result = write_irep_record(mrb, irep, cur, &rsize, flags);
mzta 0:158c61bb030f 362 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 363 return result;
mzta 0:158c61bb030f 364 }
mzta 0:158c61bb030f 365 *len_p = cur - bin + rsize;
mzta 0:158c61bb030f 366 write_section_irep_header(mrb, *len_p, bin);
mzta 0:158c61bb030f 367
mzta 0:158c61bb030f 368 return MRB_DUMP_OK;
mzta 0:158c61bb030f 369 }
mzta 0:158c61bb030f 370
mzta 0:158c61bb030f 371 static int
mzta 0:158c61bb030f 372 write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin)
mzta 0:158c61bb030f 373 {
mzta 0:158c61bb030f 374 struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin;
mzta 0:158c61bb030f 375
mzta 0:158c61bb030f 376 memcpy(header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(header->section_identify));
mzta 0:158c61bb030f 377 uint32_to_bin((uint32_t)section_size, header->section_size);
mzta 0:158c61bb030f 378
mzta 0:158c61bb030f 379 return MRB_DUMP_OK;
mzta 0:158c61bb030f 380 }
mzta 0:158c61bb030f 381
mzta 0:158c61bb030f 382 static size_t
mzta 0:158c61bb030f 383 get_lineno_record_size(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 384 {
mzta 0:158c61bb030f 385 size_t size = 0;
mzta 0:158c61bb030f 386
mzta 0:158c61bb030f 387 size += sizeof(uint32_t); /* record size */
mzta 0:158c61bb030f 388 size += sizeof(uint16_t); /* filename size */
mzta 0:158c61bb030f 389 if (irep->filename) {
mzta 0:158c61bb030f 390 size += strlen(irep->filename); /* filename */
mzta 0:158c61bb030f 391 }
mzta 0:158c61bb030f 392 size += sizeof(uint32_t); /* niseq */
mzta 0:158c61bb030f 393 if (irep->lines) {
mzta 0:158c61bb030f 394 size += sizeof(uint16_t) * irep->ilen; /* lineno */
mzta 0:158c61bb030f 395 }
mzta 0:158c61bb030f 396
mzta 0:158c61bb030f 397 return size;
mzta 0:158c61bb030f 398 }
mzta 0:158c61bb030f 399
mzta 0:158c61bb030f 400 static size_t
mzta 0:158c61bb030f 401 write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
mzta 0:158c61bb030f 402 {
mzta 0:158c61bb030f 403 uint8_t *cur = bin;
mzta 0:158c61bb030f 404 size_t iseq_no;
mzta 0:158c61bb030f 405 size_t filename_len;
mzta 0:158c61bb030f 406 ptrdiff_t diff;
mzta 0:158c61bb030f 407
mzta 0:158c61bb030f 408 cur += sizeof(uint32_t); /* record size */
mzta 0:158c61bb030f 409
mzta 0:158c61bb030f 410 if (irep->filename) {
mzta 0:158c61bb030f 411 filename_len = strlen(irep->filename);
mzta 0:158c61bb030f 412 } else {
mzta 0:158c61bb030f 413 filename_len = 0;
mzta 0:158c61bb030f 414 }
mzta 0:158c61bb030f 415 mrb_assert_int_fit(size_t, filename_len, uint16_t, UINT16_MAX);
mzta 0:158c61bb030f 416 cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */
mzta 0:158c61bb030f 417
mzta 0:158c61bb030f 418 if (filename_len) {
mzta 0:158c61bb030f 419 memcpy(cur, irep->filename, filename_len);
mzta 0:158c61bb030f 420 cur += filename_len; /* filename */
mzta 0:158c61bb030f 421 }
mzta 0:158c61bb030f 422
mzta 0:158c61bb030f 423 if (irep->lines) {
mzta 0:158c61bb030f 424 mrb_assert_int_fit(size_t, irep->ilen, uint32_t, UINT32_MAX);
mzta 0:158c61bb030f 425 cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */
mzta 0:158c61bb030f 426 for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
mzta 0:158c61bb030f 427 cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */
mzta 0:158c61bb030f 428 }
mzta 0:158c61bb030f 429 }
mzta 0:158c61bb030f 430 else {
mzta 0:158c61bb030f 431 cur += uint32_to_bin(0, cur); /* niseq */
mzta 0:158c61bb030f 432 }
mzta 0:158c61bb030f 433
mzta 0:158c61bb030f 434 diff = cur - bin;
mzta 0:158c61bb030f 435 mrb_assert_int_fit(ptrdiff_t, diff, uint32_t, UINT32_MAX);
mzta 0:158c61bb030f 436
mzta 0:158c61bb030f 437 uint32_to_bin((uint32_t)diff, bin); /* record size */
mzta 0:158c61bb030f 438
mzta 0:158c61bb030f 439 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
mzta 0:158c61bb030f 440 return (size_t)diff;
mzta 0:158c61bb030f 441 }
mzta 0:158c61bb030f 442
mzta 0:158c61bb030f 443 static size_t
mzta 0:158c61bb030f 444 write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
mzta 0:158c61bb030f 445 {
mzta 0:158c61bb030f 446 size_t i;
mzta 0:158c61bb030f 447 size_t rlen, size = 0;
mzta 0:158c61bb030f 448
mzta 0:158c61bb030f 449 rlen = write_lineno_record_1(mrb, irep, bin);
mzta 0:158c61bb030f 450 bin += rlen;
mzta 0:158c61bb030f 451 size += rlen;
mzta 0:158c61bb030f 452 for (i=0; i<irep->rlen; i++) {
mzta 0:158c61bb030f 453 rlen = write_lineno_record(mrb, irep, bin);
mzta 0:158c61bb030f 454 bin += rlen;
mzta 0:158c61bb030f 455 size += rlen;
mzta 0:158c61bb030f 456 }
mzta 0:158c61bb030f 457 return size;
mzta 0:158c61bb030f 458 }
mzta 0:158c61bb030f 459
mzta 0:158c61bb030f 460 static int
mzta 0:158c61bb030f 461 write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin)
mzta 0:158c61bb030f 462 {
mzta 0:158c61bb030f 463 size_t section_size = 0;
mzta 0:158c61bb030f 464 size_t rlen = 0; /* size of irep record */
mzta 0:158c61bb030f 465 uint8_t *cur = bin;
mzta 0:158c61bb030f 466
mzta 0:158c61bb030f 467 if (mrb == NULL || bin == NULL) {
mzta 0:158c61bb030f 468 return MRB_DUMP_INVALID_ARGUMENT;
mzta 0:158c61bb030f 469 }
mzta 0:158c61bb030f 470
mzta 0:158c61bb030f 471 cur += sizeof(struct rite_section_lineno_header);
mzta 0:158c61bb030f 472 section_size += sizeof(struct rite_section_lineno_header);
mzta 0:158c61bb030f 473
mzta 0:158c61bb030f 474 rlen = write_lineno_record(mrb, irep, cur);
mzta 0:158c61bb030f 475 section_size += rlen;
mzta 0:158c61bb030f 476
mzta 0:158c61bb030f 477 write_section_lineno_header(mrb, section_size, bin);
mzta 0:158c61bb030f 478
mzta 0:158c61bb030f 479 return MRB_DUMP_OK;
mzta 0:158c61bb030f 480 }
mzta 0:158c61bb030f 481
mzta 0:158c61bb030f 482 static size_t
mzta 0:158c61bb030f 483 get_debug_record_size(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 484 {
mzta 0:158c61bb030f 485 size_t ret = 0;
mzta 0:158c61bb030f 486 uint16_t f_idx;
mzta 0:158c61bb030f 487 size_t i;
mzta 0:158c61bb030f 488
mzta 0:158c61bb030f 489 ret += sizeof(uint32_t); /* record size */
mzta 0:158c61bb030f 490 ret += sizeof(uint16_t); /* file count */
mzta 0:158c61bb030f 491
mzta 0:158c61bb030f 492 for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
mzta 0:158c61bb030f 493 mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx];
mzta 0:158c61bb030f 494
mzta 0:158c61bb030f 495 ret += sizeof(uint32_t); /* position */
mzta 0:158c61bb030f 496 ret += sizeof(uint16_t); /* filename index */
mzta 0:158c61bb030f 497
mzta 0:158c61bb030f 498 /* lines */
mzta 0:158c61bb030f 499 ret += sizeof(uint32_t); /* entry count */
mzta 0:158c61bb030f 500 ret += sizeof(uint8_t); /* line type */
mzta 0:158c61bb030f 501 switch (file->line_type) {
mzta 0:158c61bb030f 502 case mrb_debug_line_ary:
mzta 0:158c61bb030f 503 ret += sizeof(uint16_t) * (size_t)(file->line_entry_count);
mzta 0:158c61bb030f 504 break;
mzta 0:158c61bb030f 505
mzta 0:158c61bb030f 506 case mrb_debug_line_flat_map:
mzta 0:158c61bb030f 507 ret += (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file->line_entry_count);
mzta 0:158c61bb030f 508 break;
mzta 0:158c61bb030f 509
mzta 0:158c61bb030f 510 default: mrb_assert(0); break;
mzta 0:158c61bb030f 511 }
mzta 0:158c61bb030f 512 }
mzta 0:158c61bb030f 513 for (i=0; i<irep->rlen; i++) {
mzta 0:158c61bb030f 514 ret += get_debug_record_size(mrb, irep->reps[i]);
mzta 0:158c61bb030f 515 }
mzta 0:158c61bb030f 516
mzta 0:158c61bb030f 517 return ret;
mzta 0:158c61bb030f 518 }
mzta 0:158c61bb030f 519
mzta 0:158c61bb030f 520 static int
mzta 0:158c61bb030f 521 find_filename_index(const mrb_sym *ary, int ary_len, mrb_sym s)
mzta 0:158c61bb030f 522 {
mzta 0:158c61bb030f 523 int i;
mzta 0:158c61bb030f 524
mzta 0:158c61bb030f 525 for (i = 0; i < ary_len; ++i) {
mzta 0:158c61bb030f 526 if (ary[i] == s) { return i; }
mzta 0:158c61bb030f 527 }
mzta 0:158c61bb030f 528 return -1;
mzta 0:158c61bb030f 529 }
mzta 0:158c61bb030f 530
mzta 0:158c61bb030f 531 static size_t
mzta 0:158c61bb030f 532 get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp)
mzta 0:158c61bb030f 533 {
mzta 0:158c61bb030f 534 mrb_sym *filenames = *fp;
mzta 0:158c61bb030f 535 size_t i, size = 0;
mzta 0:158c61bb030f 536 mrb_irep_debug_info *di = irep->debug_info;
mzta 0:158c61bb030f 537
mzta 0:158c61bb030f 538 mrb_assert(lp);
mzta 0:158c61bb030f 539 for (i = 0; i < di->flen; ++i) {
mzta 0:158c61bb030f 540 mrb_irep_debug_info_file *file;
mzta 0:158c61bb030f 541 mrb_int filename_len;
mzta 0:158c61bb030f 542
mzta 0:158c61bb030f 543 file = di->files[i];
mzta 0:158c61bb030f 544 if (find_filename_index(filenames, *lp, file->filename_sym) == -1) {
mzta 0:158c61bb030f 545 /* register filename */
mzta 0:158c61bb030f 546 *lp += 1;
mzta 0:158c61bb030f 547 *fp = filenames = (mrb_sym *)mrb_realloc(mrb, filenames, sizeof(mrb_sym) * (*lp));
mzta 0:158c61bb030f 548 filenames[*lp - 1] = file->filename_sym;
mzta 0:158c61bb030f 549
mzta 0:158c61bb030f 550 /* filename */
mzta 0:158c61bb030f 551 mrb_sym2name_len(mrb, file->filename_sym, &filename_len);
mzta 0:158c61bb030f 552 size += sizeof(uint16_t) + (size_t)filename_len;
mzta 0:158c61bb030f 553 }
mzta 0:158c61bb030f 554 }
mzta 0:158c61bb030f 555 for (i=0; i<irep->rlen; i++) {
mzta 0:158c61bb030f 556 size += get_filename_table_size(mrb, irep->reps[i], fp, lp);
mzta 0:158c61bb030f 557 }
mzta 0:158c61bb030f 558 return size;
mzta 0:158c61bb030f 559 }
mzta 0:158c61bb030f 560
mzta 0:158c61bb030f 561 static size_t
mzta 0:158c61bb030f 562 write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len)
mzta 0:158c61bb030f 563 {
mzta 0:158c61bb030f 564 uint8_t *cur;
mzta 0:158c61bb030f 565 uint16_t f_idx;
mzta 0:158c61bb030f 566 ptrdiff_t ret;
mzta 0:158c61bb030f 567
mzta 0:158c61bb030f 568 cur = bin + sizeof(uint32_t); /* skip record size */
mzta 0:158c61bb030f 569 cur += uint16_to_bin(irep->debug_info->flen, cur); /* file count */
mzta 0:158c61bb030f 570
mzta 0:158c61bb030f 571 for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
mzta 0:158c61bb030f 572 int filename_idx;
mzta 0:158c61bb030f 573 const mrb_irep_debug_info_file *file = irep->debug_info->files[f_idx];
mzta 0:158c61bb030f 574
mzta 0:158c61bb030f 575 /* position */
mzta 0:158c61bb030f 576 cur += uint32_to_bin(file->start_pos, cur);
mzta 0:158c61bb030f 577
mzta 0:158c61bb030f 578 /* filename index */
mzta 0:158c61bb030f 579 filename_idx = find_filename_index(filenames, filenames_len,
mzta 0:158c61bb030f 580 file->filename_sym);
mzta 0:158c61bb030f 581 mrb_assert_int_fit(int, filename_idx, uint16_t, UINT16_MAX);
mzta 0:158c61bb030f 582 cur += uint16_to_bin((uint16_t)filename_idx, cur);
mzta 0:158c61bb030f 583
mzta 0:158c61bb030f 584 /* lines */
mzta 0:158c61bb030f 585 cur += uint32_to_bin(file->line_entry_count, cur);
mzta 0:158c61bb030f 586 cur += uint8_to_bin(file->line_type, cur);
mzta 0:158c61bb030f 587 switch (file->line_type) {
mzta 0:158c61bb030f 588 case mrb_debug_line_ary: {
mzta 0:158c61bb030f 589 uint32_t l;
mzta 0:158c61bb030f 590 for (l = 0; l < file->line_entry_count; ++l) {
mzta 0:158c61bb030f 591 cur += uint16_to_bin(file->lines.ary[l], cur);
mzta 0:158c61bb030f 592 }
mzta 0:158c61bb030f 593 } break;
mzta 0:158c61bb030f 594
mzta 0:158c61bb030f 595 case mrb_debug_line_flat_map: {
mzta 0:158c61bb030f 596 uint32_t line;
mzta 0:158c61bb030f 597 for (line = 0; line < file->line_entry_count; ++line) {
mzta 0:158c61bb030f 598 cur += uint32_to_bin(file->lines.flat_map[line].start_pos, cur);
mzta 0:158c61bb030f 599 cur += uint16_to_bin(file->lines.flat_map[line].line, cur);
mzta 0:158c61bb030f 600 }
mzta 0:158c61bb030f 601 } break;
mzta 0:158c61bb030f 602
mzta 0:158c61bb030f 603 default: mrb_assert(0); break;
mzta 0:158c61bb030f 604 }
mzta 0:158c61bb030f 605 }
mzta 0:158c61bb030f 606
mzta 0:158c61bb030f 607 ret = cur - bin;
mzta 0:158c61bb030f 608 mrb_assert_int_fit(ptrdiff_t, ret, uint32_t, UINT32_MAX);
mzta 0:158c61bb030f 609 uint32_to_bin(ret, bin);
mzta 0:158c61bb030f 610
mzta 0:158c61bb030f 611 mrb_assert_int_fit(ptrdiff_t, ret, size_t, SIZE_MAX);
mzta 0:158c61bb030f 612 return (size_t)ret;
mzta 0:158c61bb030f 613 }
mzta 0:158c61bb030f 614
mzta 0:158c61bb030f 615 static size_t
mzta 0:158c61bb030f 616 write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len)
mzta 0:158c61bb030f 617 {
mzta 0:158c61bb030f 618 size_t size, len;
mzta 0:158c61bb030f 619 size_t irep_no;
mzta 0:158c61bb030f 620
mzta 0:158c61bb030f 621 size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len);
mzta 0:158c61bb030f 622 bin += len;
mzta 0:158c61bb030f 623 for (irep_no = 0; irep_no < irep->rlen; irep_no++) {
mzta 0:158c61bb030f 624 len = write_debug_record(mrb, irep->reps[irep_no], bin, filenames, filenames_len);
mzta 0:158c61bb030f 625 bin += len;
mzta 0:158c61bb030f 626 size += len;
mzta 0:158c61bb030f 627 }
mzta 0:158c61bb030f 628
mzta 0:158c61bb030f 629 mrb_assert(size == get_debug_record_size(mrb, irep));
mzta 0:158c61bb030f 630 return size;
mzta 0:158c61bb030f 631 }
mzta 0:158c61bb030f 632
mzta 0:158c61bb030f 633 static int
mzta 0:158c61bb030f 634 write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur, mrb_sym const *filenames, uint16_t filenames_len)
mzta 0:158c61bb030f 635 {
mzta 0:158c61bb030f 636 size_t section_size = 0;
mzta 0:158c61bb030f 637 const uint8_t *bin = cur;
mzta 0:158c61bb030f 638 struct rite_section_debug_header *header;
mzta 0:158c61bb030f 639 size_t dlen;
mzta 0:158c61bb030f 640 uint16_t i;
mzta 0:158c61bb030f 641 char const *sym; mrb_int sym_len;
mzta 0:158c61bb030f 642
mzta 0:158c61bb030f 643 if (mrb == NULL || cur == NULL) {
mzta 0:158c61bb030f 644 return MRB_DUMP_INVALID_ARGUMENT;
mzta 0:158c61bb030f 645 }
mzta 0:158c61bb030f 646
mzta 0:158c61bb030f 647 header = (struct rite_section_debug_header *)bin;
mzta 0:158c61bb030f 648 cur += sizeof(struct rite_section_debug_header);
mzta 0:158c61bb030f 649 section_size += sizeof(struct rite_section_debug_header);
mzta 0:158c61bb030f 650
mzta 0:158c61bb030f 651 /* filename table */
mzta 0:158c61bb030f 652 cur += uint16_to_bin(filenames_len, cur);
mzta 0:158c61bb030f 653 section_size += sizeof(uint16_t);
mzta 0:158c61bb030f 654 for (i = 0; i < filenames_len; ++i) {
mzta 0:158c61bb030f 655 sym = mrb_sym2name_len(mrb, filenames[i], &sym_len);
mzta 0:158c61bb030f 656 mrb_assert(sym);
mzta 0:158c61bb030f 657 cur += uint16_to_bin(sym_len, cur);
mzta 0:158c61bb030f 658 memcpy(cur, sym, sym_len);
mzta 0:158c61bb030f 659 cur += sym_len;
mzta 0:158c61bb030f 660 section_size += sizeof(uint16_t) + sym_len;
mzta 0:158c61bb030f 661 }
mzta 0:158c61bb030f 662
mzta 0:158c61bb030f 663 /* debug records */
mzta 0:158c61bb030f 664 dlen = write_debug_record(mrb, irep, cur, filenames, filenames_len);
mzta 0:158c61bb030f 665 section_size += dlen;
mzta 0:158c61bb030f 666
mzta 0:158c61bb030f 667 memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify));
mzta 0:158c61bb030f 668 mrb_assert(section_size <= INT32_MAX);
mzta 0:158c61bb030f 669 uint32_to_bin(section_size, header->section_size);
mzta 0:158c61bb030f 670
mzta 0:158c61bb030f 671 return MRB_DUMP_OK;
mzta 0:158c61bb030f 672 }
mzta 0:158c61bb030f 673
mzta 0:158c61bb030f 674 static void
mzta 0:158c61bb030f 675 create_lv_sym_table(mrb_state *mrb, const mrb_irep *irep, mrb_sym **syms, uint32_t *syms_len)
mzta 0:158c61bb030f 676 {
mzta 0:158c61bb030f 677 size_t i;
mzta 0:158c61bb030f 678
mzta 0:158c61bb030f 679 if (*syms == NULL) {
mzta 0:158c61bb030f 680 *syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * 1);
mzta 0:158c61bb030f 681 }
mzta 0:158c61bb030f 682
mzta 0:158c61bb030f 683 for (i = 0; i + 1 < irep->nlocals; ++i) {
mzta 0:158c61bb030f 684 mrb_sym const name = irep->lv[i].name;
mzta 0:158c61bb030f 685 if (name == 0) continue;
mzta 0:158c61bb030f 686 if (find_filename_index(*syms, *syms_len, name) != -1) continue;
mzta 0:158c61bb030f 687
mzta 0:158c61bb030f 688 ++(*syms_len);
mzta 0:158c61bb030f 689 *syms = (mrb_sym*)mrb_realloc(mrb, *syms, sizeof(mrb_sym) * (*syms_len));
mzta 0:158c61bb030f 690 (*syms)[*syms_len - 1] = name;
mzta 0:158c61bb030f 691 }
mzta 0:158c61bb030f 692
mzta 0:158c61bb030f 693 for (i = 0; i < irep->rlen; ++i) {
mzta 0:158c61bb030f 694 create_lv_sym_table(mrb, irep->reps[i], syms, syms_len);
mzta 0:158c61bb030f 695 }
mzta 0:158c61bb030f 696 }
mzta 0:158c61bb030f 697
mzta 0:158c61bb030f 698 static int
mzta 0:158c61bb030f 699 write_lv_sym_table(mrb_state *mrb, uint8_t **start, mrb_sym const *syms, uint32_t syms_len)
mzta 0:158c61bb030f 700 {
mzta 0:158c61bb030f 701 uint8_t *cur = *start;
mzta 0:158c61bb030f 702 uint32_t i;
mzta 0:158c61bb030f 703 const char *str;
mzta 0:158c61bb030f 704 mrb_int str_len;
mzta 0:158c61bb030f 705
mzta 0:158c61bb030f 706 cur += uint32_to_bin(syms_len, cur);
mzta 0:158c61bb030f 707
mzta 0:158c61bb030f 708 for (i = 0; i < syms_len; ++i) {
mzta 0:158c61bb030f 709 str = mrb_sym2name_len(mrb, syms[i], &str_len);
mzta 0:158c61bb030f 710 cur += uint16_to_bin(str_len, cur);
mzta 0:158c61bb030f 711 memcpy(cur, str, str_len);
mzta 0:158c61bb030f 712 cur += str_len;
mzta 0:158c61bb030f 713 }
mzta 0:158c61bb030f 714
mzta 0:158c61bb030f 715 *start = cur;
mzta 0:158c61bb030f 716
mzta 0:158c61bb030f 717 return MRB_DUMP_OK;
mzta 0:158c61bb030f 718 }
mzta 0:158c61bb030f 719
mzta 0:158c61bb030f 720 static int
mzta 0:158c61bb030f 721 write_lv_record(mrb_state *mrb, const mrb_irep *irep, uint8_t **start, mrb_sym const *syms, uint32_t syms_len)
mzta 0:158c61bb030f 722 {
mzta 0:158c61bb030f 723 uint8_t *cur = *start;
mzta 0:158c61bb030f 724 size_t i;
mzta 0:158c61bb030f 725
mzta 0:158c61bb030f 726 for (i = 0; i + 1 < irep->nlocals; ++i) {
mzta 0:158c61bb030f 727 if (irep->lv[i].name == 0) {
mzta 0:158c61bb030f 728 cur += uint16_to_bin(RITE_LV_NULL_MARK, cur);
mzta 0:158c61bb030f 729 cur += uint16_to_bin(0, cur);
mzta 0:158c61bb030f 730 }
mzta 0:158c61bb030f 731 else {
mzta 0:158c61bb030f 732 int const sym_idx = find_filename_index(syms, syms_len, irep->lv[i].name);
mzta 0:158c61bb030f 733 mrb_assert(sym_idx != -1); /* local variable name must be in syms */
mzta 0:158c61bb030f 734
mzta 0:158c61bb030f 735 cur += uint16_to_bin(sym_idx, cur);
mzta 0:158c61bb030f 736 cur += uint16_to_bin(irep->lv[i].r, cur);
mzta 0:158c61bb030f 737 }
mzta 0:158c61bb030f 738 }
mzta 0:158c61bb030f 739
mzta 0:158c61bb030f 740 for (i = 0; i < irep->rlen; ++i) {
mzta 0:158c61bb030f 741 write_lv_record(mrb, irep->reps[i], &cur, syms, syms_len);
mzta 0:158c61bb030f 742 }
mzta 0:158c61bb030f 743
mzta 0:158c61bb030f 744 *start = cur;
mzta 0:158c61bb030f 745
mzta 0:158c61bb030f 746 return MRB_DUMP_OK;
mzta 0:158c61bb030f 747 }
mzta 0:158c61bb030f 748
mzta 0:158c61bb030f 749 static size_t
mzta 0:158c61bb030f 750 get_lv_record_size(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 751 {
mzta 0:158c61bb030f 752 size_t ret = 0, i;
mzta 0:158c61bb030f 753
mzta 0:158c61bb030f 754 ret += (sizeof(uint16_t) + sizeof(uint16_t)) * (irep->nlocals - 1);
mzta 0:158c61bb030f 755
mzta 0:158c61bb030f 756 for (i = 0; i < irep->rlen; ++i) {
mzta 0:158c61bb030f 757 ret += get_lv_record_size(mrb, irep->reps[i]);
mzta 0:158c61bb030f 758 }
mzta 0:158c61bb030f 759
mzta 0:158c61bb030f 760 return ret;
mzta 0:158c61bb030f 761 }
mzta 0:158c61bb030f 762
mzta 0:158c61bb030f 763 static size_t
mzta 0:158c61bb030f 764 get_lv_section_size(mrb_state *mrb, mrb_irep *irep, mrb_sym const *syms, uint32_t syms_len)
mzta 0:158c61bb030f 765 {
mzta 0:158c61bb030f 766 size_t ret = 0, i;
mzta 0:158c61bb030f 767
mzta 0:158c61bb030f 768 ret += sizeof(uint32_t); /* syms_len */
mzta 0:158c61bb030f 769 ret += sizeof(uint16_t) * syms_len; /* symbol name lengths */
mzta 0:158c61bb030f 770 for (i = 0; i < syms_len; ++i) {
mzta 0:158c61bb030f 771 mrb_int str_len;
mzta 0:158c61bb030f 772 mrb_sym2name_len(mrb, syms[i], &str_len);
mzta 0:158c61bb030f 773 ret += str_len;
mzta 0:158c61bb030f 774 }
mzta 0:158c61bb030f 775
mzta 0:158c61bb030f 776 ret += get_lv_record_size(mrb, irep);
mzta 0:158c61bb030f 777
mzta 0:158c61bb030f 778 return ret;
mzta 0:158c61bb030f 779 }
mzta 0:158c61bb030f 780
mzta 0:158c61bb030f 781 static int
mzta 0:158c61bb030f 782 write_section_lv(mrb_state *mrb, mrb_irep *irep, uint8_t *start, mrb_sym const *syms, uint32_t const syms_len)
mzta 0:158c61bb030f 783 {
mzta 0:158c61bb030f 784 uint8_t *cur = start;
mzta 0:158c61bb030f 785 struct rite_section_lv_header *header;
mzta 0:158c61bb030f 786 ptrdiff_t diff;
mzta 0:158c61bb030f 787 int result = MRB_DUMP_OK;
mzta 0:158c61bb030f 788
mzta 0:158c61bb030f 789 if (mrb == NULL || cur == NULL) {
mzta 0:158c61bb030f 790 return MRB_DUMP_INVALID_ARGUMENT;
mzta 0:158c61bb030f 791 }
mzta 0:158c61bb030f 792
mzta 0:158c61bb030f 793 header = (struct rite_section_lv_header*)cur;
mzta 0:158c61bb030f 794 cur += sizeof(struct rite_section_lv_header);
mzta 0:158c61bb030f 795
mzta 0:158c61bb030f 796 result = write_lv_sym_table(mrb, &cur, syms, syms_len);
mzta 0:158c61bb030f 797 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 798 goto lv_section_exit;
mzta 0:158c61bb030f 799 }
mzta 0:158c61bb030f 800
mzta 0:158c61bb030f 801 result = write_lv_record(mrb, irep, &cur, syms, syms_len);
mzta 0:158c61bb030f 802 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 803 goto lv_section_exit;
mzta 0:158c61bb030f 804 }
mzta 0:158c61bb030f 805
mzta 0:158c61bb030f 806 memcpy(header->section_identify, RITE_SECTION_LV_IDENTIFIER, sizeof(header->section_identify));
mzta 0:158c61bb030f 807
mzta 0:158c61bb030f 808 diff = cur - start;
mzta 0:158c61bb030f 809 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
mzta 0:158c61bb030f 810 uint32_to_bin(diff, header->section_size);
mzta 0:158c61bb030f 811
mzta 0:158c61bb030f 812 lv_section_exit:
mzta 0:158c61bb030f 813 return result;
mzta 0:158c61bb030f 814 }
mzta 0:158c61bb030f 815
mzta 0:158c61bb030f 816 static int
mzta 0:158c61bb030f 817 write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8_t flags)
mzta 0:158c61bb030f 818 {
mzta 0:158c61bb030f 819 struct rite_binary_header *header = (struct rite_binary_header *)bin;
mzta 0:158c61bb030f 820 uint16_t crc;
mzta 0:158c61bb030f 821 uint32_t offset;
mzta 0:158c61bb030f 822
mzta 0:158c61bb030f 823 if (flags & FLAG_BYTEORDER_NATIVE) {
mzta 0:158c61bb030f 824 uint32_t ident = 0;
mzta 0:158c61bb030f 825 size_t i;
mzta 0:158c61bb030f 826
mzta 0:158c61bb030f 827 for(i=0; i<sizeof(ident); i++) {
mzta 0:158c61bb030f 828 ident<<=8;
mzta 0:158c61bb030f 829 ident|=RITE_BINARY_IDENTIFIER[i];
mzta 0:158c61bb030f 830 }
mzta 0:158c61bb030f 831 memcpy(header->binary_identify, (char*)&ident, sizeof(uint32_t));
mzta 0:158c61bb030f 832 }
mzta 0:158c61bb030f 833 else {
mzta 0:158c61bb030f 834 memcpy(header->binary_identify, RITE_BINARY_IDENTIFIER, sizeof(header->binary_identify));
mzta 0:158c61bb030f 835 }
mzta 0:158c61bb030f 836 memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
mzta 0:158c61bb030f 837 memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
mzta 0:158c61bb030f 838 memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
mzta 0:158c61bb030f 839 mrb_assert(binary_size <= UINT32_MAX);
mzta 0:158c61bb030f 840 uint32_to_bin((uint32_t)binary_size, header->binary_size);
mzta 0:158c61bb030f 841
mzta 0:158c61bb030f 842 offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t);
mzta 0:158c61bb030f 843 crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0);
mzta 0:158c61bb030f 844 uint16_to_bin(crc, header->binary_crc);
mzta 0:158c61bb030f 845
mzta 0:158c61bb030f 846 return MRB_DUMP_OK;
mzta 0:158c61bb030f 847 }
mzta 0:158c61bb030f 848
mzta 0:158c61bb030f 849 static mrb_bool
mzta 0:158c61bb030f 850 is_debug_info_defined(mrb_irep *irep)
mzta 0:158c61bb030f 851 {
mzta 0:158c61bb030f 852 size_t i;
mzta 0:158c61bb030f 853
mzta 0:158c61bb030f 854 if (!irep->debug_info) return FALSE;
mzta 0:158c61bb030f 855 for (i=0; i<irep->rlen; i++) {
mzta 0:158c61bb030f 856 if (!is_debug_info_defined(irep->reps[i])) return FALSE;
mzta 0:158c61bb030f 857 }
mzta 0:158c61bb030f 858 return TRUE;
mzta 0:158c61bb030f 859 }
mzta 0:158c61bb030f 860
mzta 0:158c61bb030f 861 static mrb_bool
mzta 0:158c61bb030f 862 is_lv_defined(mrb_irep *irep)
mzta 0:158c61bb030f 863 {
mzta 0:158c61bb030f 864 size_t i;
mzta 0:158c61bb030f 865
mzta 0:158c61bb030f 866 if (irep->lv) { return TRUE; }
mzta 0:158c61bb030f 867
mzta 0:158c61bb030f 868 for (i = 0; i < irep->rlen; ++i) {
mzta 0:158c61bb030f 869 if (is_lv_defined(irep->reps[i])) { return TRUE; }
mzta 0:158c61bb030f 870 }
mzta 0:158c61bb030f 871
mzta 0:158c61bb030f 872 return FALSE;
mzta 0:158c61bb030f 873 }
mzta 0:158c61bb030f 874
mzta 0:158c61bb030f 875 static int
mzta 0:158c61bb030f 876 dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size, uint8_t flags)
mzta 0:158c61bb030f 877 {
mzta 0:158c61bb030f 878 int result = MRB_DUMP_GENERAL_FAILURE;
mzta 0:158c61bb030f 879 size_t malloc_size;
mzta 0:158c61bb030f 880 size_t section_irep_size;
mzta 0:158c61bb030f 881 size_t section_lineno_size = 0, section_lv_size = 0;
mzta 0:158c61bb030f 882 uint8_t *cur = NULL;
mzta 0:158c61bb030f 883 mrb_bool const debug_info_defined = is_debug_info_defined(irep), lv_defined = is_lv_defined(irep);
mzta 0:158c61bb030f 884 mrb_sym *lv_syms = NULL; uint32_t lv_syms_len = 0;
mzta 0:158c61bb030f 885 mrb_sym *filenames = NULL; uint16_t filenames_len = 0;
mzta 0:158c61bb030f 886
mzta 0:158c61bb030f 887 if (mrb == NULL) {
mzta 0:158c61bb030f 888 *bin = NULL;
mzta 0:158c61bb030f 889 return MRB_DUMP_GENERAL_FAILURE;
mzta 0:158c61bb030f 890 }
mzta 0:158c61bb030f 891
mzta 0:158c61bb030f 892 section_irep_size = sizeof(struct rite_section_irep_header);
mzta 0:158c61bb030f 893 section_irep_size += get_irep_record_size(mrb, irep);
mzta 0:158c61bb030f 894
mzta 0:158c61bb030f 895 /* DEBUG section size */
mzta 0:158c61bb030f 896 if (debug_info) {
mzta 0:158c61bb030f 897 if (debug_info_defined) {
mzta 0:158c61bb030f 898 section_lineno_size += sizeof(struct rite_section_debug_header);
mzta 0:158c61bb030f 899 /* filename table */
mzta 0:158c61bb030f 900 filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) + 1);
mzta 0:158c61bb030f 901
mzta 0:158c61bb030f 902 /* filename table size */
mzta 0:158c61bb030f 903 section_lineno_size += sizeof(uint16_t);
mzta 0:158c61bb030f 904 section_lineno_size += get_filename_table_size(mrb, irep, &filenames, &filenames_len);
mzta 0:158c61bb030f 905
mzta 0:158c61bb030f 906 section_lineno_size += get_debug_record_size(mrb, irep);
mzta 0:158c61bb030f 907 }
mzta 0:158c61bb030f 908 else {
mzta 0:158c61bb030f 909 section_lineno_size += sizeof(struct rite_section_lineno_header);
mzta 0:158c61bb030f 910 section_lineno_size += get_lineno_record_size(mrb, irep);
mzta 0:158c61bb030f 911 }
mzta 0:158c61bb030f 912 }
mzta 0:158c61bb030f 913
mzta 0:158c61bb030f 914 if (lv_defined) {
mzta 0:158c61bb030f 915 section_lv_size += sizeof(struct rite_section_lv_header);
mzta 0:158c61bb030f 916 create_lv_sym_table(mrb, irep, &lv_syms, &lv_syms_len);
mzta 0:158c61bb030f 917 section_lv_size += get_lv_section_size(mrb, irep, lv_syms, lv_syms_len);
mzta 0:158c61bb030f 918 }
mzta 0:158c61bb030f 919
mzta 0:158c61bb030f 920 malloc_size = sizeof(struct rite_binary_header) +
mzta 0:158c61bb030f 921 section_irep_size + section_lineno_size + section_lv_size +
mzta 0:158c61bb030f 922 sizeof(struct rite_binary_footer);
mzta 0:158c61bb030f 923 cur = *bin = (uint8_t*)mrb_malloc(mrb, malloc_size);
mzta 0:158c61bb030f 924 cur += sizeof(struct rite_binary_header);
mzta 0:158c61bb030f 925
mzta 0:158c61bb030f 926 result = write_section_irep(mrb, irep, cur, &section_irep_size, flags);
mzta 0:158c61bb030f 927 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 928 goto error_exit;
mzta 0:158c61bb030f 929 }
mzta 0:158c61bb030f 930 cur += section_irep_size;
mzta 0:158c61bb030f 931 *bin_size = sizeof(struct rite_binary_header) +
mzta 0:158c61bb030f 932 section_irep_size + section_lineno_size + section_lv_size +
mzta 0:158c61bb030f 933 sizeof(struct rite_binary_footer);
mzta 0:158c61bb030f 934
mzta 0:158c61bb030f 935 /* write DEBUG section */
mzta 0:158c61bb030f 936 if (debug_info) {
mzta 0:158c61bb030f 937 if (debug_info_defined) {
mzta 0:158c61bb030f 938 result = write_section_debug(mrb, irep, cur, filenames, filenames_len);
mzta 0:158c61bb030f 939 }
mzta 0:158c61bb030f 940 else {
mzta 0:158c61bb030f 941 result = write_section_lineno(mrb, irep, cur);
mzta 0:158c61bb030f 942 }
mzta 0:158c61bb030f 943 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 944 goto error_exit;
mzta 0:158c61bb030f 945 }
mzta 0:158c61bb030f 946 cur += section_lineno_size;
mzta 0:158c61bb030f 947 }
mzta 0:158c61bb030f 948
mzta 0:158c61bb030f 949 if (lv_defined) {
mzta 0:158c61bb030f 950 result = write_section_lv(mrb, irep, cur, lv_syms, lv_syms_len);
mzta 0:158c61bb030f 951 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 952 goto error_exit;
mzta 0:158c61bb030f 953 }
mzta 0:158c61bb030f 954 cur += section_lv_size;
mzta 0:158c61bb030f 955 }
mzta 0:158c61bb030f 956
mzta 0:158c61bb030f 957 write_footer(mrb, cur);
mzta 0:158c61bb030f 958 write_rite_binary_header(mrb, *bin_size, *bin, flags);
mzta 0:158c61bb030f 959
mzta 0:158c61bb030f 960 error_exit:
mzta 0:158c61bb030f 961 if (result != MRB_DUMP_OK) {
mzta 0:158c61bb030f 962 mrb_free(mrb, *bin);
mzta 0:158c61bb030f 963 *bin = NULL;
mzta 0:158c61bb030f 964 }
mzta 0:158c61bb030f 965 if (lv_syms) {
mzta 0:158c61bb030f 966 mrb_free(mrb, lv_syms);
mzta 0:158c61bb030f 967 }
mzta 0:158c61bb030f 968 if (filenames) {
mzta 0:158c61bb030f 969 mrb_free(mrb, filenames);
mzta 0:158c61bb030f 970 }
mzta 0:158c61bb030f 971 return result;
mzta 0:158c61bb030f 972 }
mzta 0:158c61bb030f 973
mzta 0:158c61bb030f 974 int
mzta 0:158c61bb030f 975 mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size)
mzta 0:158c61bb030f 976 {
mzta 0:158c61bb030f 977 return dump_irep(mrb, irep, debug_info, bin, bin_size, FLAG_BYTEORDER_NONATIVE);
mzta 0:158c61bb030f 978 }
mzta 0:158c61bb030f 979
mzta 0:158c61bb030f 980 int
mzta 0:158c61bb030f 981 mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp)
mzta 0:158c61bb030f 982 {
mzta 0:158c61bb030f 983 uint8_t *bin = NULL;
mzta 0:158c61bb030f 984 size_t bin_size = 0;
mzta 0:158c61bb030f 985 int result;
mzta 0:158c61bb030f 986
mzta 0:158c61bb030f 987 if (fp == NULL) {
mzta 0:158c61bb030f 988 return MRB_DUMP_INVALID_ARGUMENT;
mzta 0:158c61bb030f 989 }
mzta 0:158c61bb030f 990
mzta 0:158c61bb030f 991 result = dump_irep(mrb, irep, debug_info, &bin, &bin_size, FLAG_BYTEORDER_NONATIVE);
mzta 0:158c61bb030f 992 if (result == MRB_DUMP_OK) {
mzta 0:158c61bb030f 993 if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) {
mzta 0:158c61bb030f 994 result = MRB_DUMP_WRITE_FAULT;
mzta 0:158c61bb030f 995 }
mzta 0:158c61bb030f 996 }
mzta 0:158c61bb030f 997
mzta 0:158c61bb030f 998 mrb_free(mrb, bin);
mzta 0:158c61bb030f 999 return result;
mzta 0:158c61bb030f 1000 }
mzta 0:158c61bb030f 1001
mzta 0:158c61bb030f 1002 static mrb_bool
mzta 0:158c61bb030f 1003 is_valid_c_symbol_name(const char *name)
mzta 0:158c61bb030f 1004 {
mzta 0:158c61bb030f 1005 const char *c = NULL;
mzta 0:158c61bb030f 1006
mzta 0:158c61bb030f 1007 if (name == NULL || name[0] == '\0') return FALSE;
mzta 0:158c61bb030f 1008 if (!ISALPHA(name[0]) && name[0] != '_') return FALSE;
mzta 0:158c61bb030f 1009
mzta 0:158c61bb030f 1010 c = &name[1];
mzta 0:158c61bb030f 1011 for (; *c != '\0'; ++c) {
mzta 0:158c61bb030f 1012 if (!ISALNUM(*c) && *c != '_') return FALSE;
mzta 0:158c61bb030f 1013 }
mzta 0:158c61bb030f 1014
mzta 0:158c61bb030f 1015 return TRUE;
mzta 0:158c61bb030f 1016 }
mzta 0:158c61bb030f 1017
mzta 0:158c61bb030f 1018 int
mzta 0:158c61bb030f 1019 mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE *fp, const char *initname)
mzta 0:158c61bb030f 1020 {
mzta 0:158c61bb030f 1021 uint8_t *bin = NULL;
mzta 0:158c61bb030f 1022 size_t bin_size = 0, bin_idx = 0;
mzta 0:158c61bb030f 1023 int result;
mzta 0:158c61bb030f 1024
mzta 0:158c61bb030f 1025 if (fp == NULL || initname == NULL || !is_valid_c_symbol_name(initname)) {
mzta 0:158c61bb030f 1026 return MRB_DUMP_INVALID_ARGUMENT;
mzta 0:158c61bb030f 1027 }
mzta 0:158c61bb030f 1028
mzta 0:158c61bb030f 1029 result = dump_irep(mrb, irep, debug_info, &bin, &bin_size, FLAG_BYTEORDER_NATIVE);
mzta 0:158c61bb030f 1030 if (result == MRB_DUMP_OK) {
mzta 0:158c61bb030f 1031 if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */
mzta 0:158c61bb030f 1032 mrb_free(mrb, bin);
mzta 0:158c61bb030f 1033 return MRB_DUMP_WRITE_FAULT;
mzta 0:158c61bb030f 1034 }
mzta 0:158c61bb030f 1035 if (fprintf(fp,
mzta 0:158c61bb030f 1036 "const uint8_t\n"
mzta 0:158c61bb030f 1037 "#if defined __GNUC__\n"
mzta 0:158c61bb030f 1038 "__attribute__((aligned(%u)))\n"
mzta 0:158c61bb030f 1039 "#elif defined _MSC_VER\n"
mzta 0:158c61bb030f 1040 "__declspec(align(%u))\n"
mzta 0:158c61bb030f 1041 "#endif\n"
mzta 0:158c61bb030f 1042 "%s[] = {",
mzta 0:158c61bb030f 1043 (uint16_t)MRB_DUMP_ALIGNMENT, (uint16_t)MRB_DUMP_ALIGNMENT, initname) < 0) {
mzta 0:158c61bb030f 1044 mrb_free(mrb, bin);
mzta 0:158c61bb030f 1045 return MRB_DUMP_WRITE_FAULT;
mzta 0:158c61bb030f 1046 }
mzta 0:158c61bb030f 1047 while (bin_idx < bin_size) {
mzta 0:158c61bb030f 1048 if (bin_idx % 16 == 0) {
mzta 0:158c61bb030f 1049 if (fputs("\n", fp) == EOF) {
mzta 0:158c61bb030f 1050 mrb_free(mrb, bin);
mzta 0:158c61bb030f 1051 return MRB_DUMP_WRITE_FAULT;
mzta 0:158c61bb030f 1052 }
mzta 0:158c61bb030f 1053 }
mzta 0:158c61bb030f 1054 if (fprintf(fp, "0x%02x,", bin[bin_idx++]) < 0) {
mzta 0:158c61bb030f 1055 mrb_free(mrb, bin);
mzta 0:158c61bb030f 1056 return MRB_DUMP_WRITE_FAULT;
mzta 0:158c61bb030f 1057 }
mzta 0:158c61bb030f 1058 }
mzta 0:158c61bb030f 1059 if (fputs("\n};\n", fp) == EOF) {
mzta 0:158c61bb030f 1060 mrb_free(mrb, bin);
mzta 0:158c61bb030f 1061 return MRB_DUMP_WRITE_FAULT;
mzta 0:158c61bb030f 1062 }
mzta 0:158c61bb030f 1063 }
mzta 0:158c61bb030f 1064
mzta 0:158c61bb030f 1065 mrb_free(mrb, bin);
mzta 0:158c61bb030f 1066 return result;
mzta 0:158c61bb030f 1067 }
mzta 0:158c61bb030f 1068
mzta 0:158c61bb030f 1069 #endif /* ENABLE_STDIO */
mzta 0:158c61bb030f 1070