diff options
| author | Yuichiro MASUI <[email protected]> | 2013-03-02 23:40:34 +0900 |
|---|---|---|
| committer | Yuichiro MASUI <[email protected]> | 2013-03-08 03:14:21 +0900 |
| commit | 284258367881d74f784485c2e5d282f4f5d490a5 (patch) | |
| tree | a160d3c745f14e600edaed724f67d3107b362049 /src/load.c | |
| parent | 7d47096434994d9eb9712546879e3b52b04d3443 (diff) | |
| download | mruby-284258367881d74f784485c2e5d282f4f5d490a5.tar.gz mruby-284258367881d74f784485c2e5d282f4f5d490a5.zip | |
New mrb format. The detail is in https://github.com/mruby/mruby/issues/944
Diffstat (limited to 'src/load.c')
| -rw-r--r-- | src/load.c | 768 |
1 files changed, 225 insertions, 543 deletions
diff --git a/src/load.c b/src/load.c index 84c21c186..82b6b7b6f 100644 --- a/src/load.c +++ b/src/load.c @@ -11,405 +11,63 @@ #include "mruby/proc.h" #include "mruby/irep.h" -#ifdef ENABLE_STDIO -typedef struct _RiteFILE -{ - FILE* fp; - unsigned char buf[256]; - int cnt; - int readlen; -} RiteFILE; -#endif - -const char hex2bin[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //00-0f - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10-1f - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-2f - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, //30-3f - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40-4f - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50-5f - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0 //60-6f - //70-ff -}; - -static uint16_t hex_to_bin8(unsigned char*,unsigned char*); -static uint16_t hex_to_bin16(unsigned char*,unsigned char*); -static uint16_t hex_to_bin32(unsigned char*,unsigned char*); -static uint8_t hex_to_uint8(unsigned char*); -static uint16_t hex_to_uint16(unsigned char*); -static uint32_t hex_to_uint32(unsigned char*); -static char* hex_to_str(char*,char*,uint16_t*); -uint16_t calc_crc_16_ccitt(unsigned char*,int); -#ifdef ENABLE_STDIO -static unsigned char rite_fgetcSub(RiteFILE*); -static unsigned char rite_fgetc(RiteFILE*,int); -static unsigned char* rite_fgets(RiteFILE*,unsigned char*,int,int); -static int load_rite_header(FILE*,rite_binary_header*,unsigned char*); -static int load_rite_irep_record(mrb_state*, RiteFILE*,unsigned char*,uint32_t*); -#endif -static int read_rite_header(mrb_state*,unsigned char*,rite_binary_header*); -static int read_rite_irep_record(mrb_state*,unsigned char*,uint32_t*); - - -#ifdef ENABLE_STDIO -static unsigned char -rite_fgetcSub(RiteFILE* rfp) -{ - //only first call - if (rfp->buf[0] == '\0') { - rfp->readlen = fread(rfp->buf, 1, sizeof(rfp->buf), rfp->fp); - rfp->cnt = 0; - } - - if (rfp->readlen == rfp->cnt) { - rfp->readlen = fread(rfp->buf, 1, sizeof(rfp->buf), rfp->fp); - rfp->cnt = 0; - if (rfp->readlen == 0) { - return '\0'; - } - } - return rfp->buf[(rfp->cnt)++]; -} -#endif /* ENABLE_STDIO */ - -#ifdef ENABLE_STDIO -static unsigned char -rite_fgetc(RiteFILE* rfp, int ignorecomment) -{ - unsigned char tmp; - - for (;;) { - tmp = rite_fgetcSub(rfp); - if (tmp == '\n' || tmp == '\r') { - continue; - } - else if (ignorecomment && tmp == '#') { - while (tmp != '\n' && tmp != '\r' && tmp != '\0') - tmp = rite_fgetcSub(rfp); - if (tmp == '\0') - return '\0'; - } - else { - return tmp; - } - } -} -#endif /* ENABLE_STDIO */ - -#ifdef ENABLE_STDIO -static unsigned char* -rite_fgets(RiteFILE* rfp, unsigned char* dst, int len, int ignorecomment) -{ - int i; - - for (i=0; i<len; i++) { - if ('\0' == (dst[i] = rite_fgetc(rfp, ignorecomment))) { - return NULL; - } - } - return dst; -} -#endif /* ENABLE_STDIO */ - -#ifdef ENABLE_STDIO -static int -load_rite_header(FILE* fp, rite_binary_header* bin_header, unsigned char* hcrc) -{ - rite_file_header file_header; - - if (fread(&file_header, 1, sizeof(file_header), fp) < sizeof(file_header)) { - return MRB_DUMP_READ_FAULT; - } - memcpy(bin_header->rbfi, file_header.rbfi, sizeof(file_header.rbfi)); - if (memcmp(bin_header->rbfi, RITE_FILE_IDENFIFIER, sizeof(bin_header->rbfi)) != 0) { - return MRB_DUMP_INVALID_FILE_HEADER; //File identifier error - } - memcpy(bin_header->rbfv, file_header.rbfv, sizeof(file_header.rbfv)); - if (memcmp(bin_header->rbfv, RITE_FILE_FORMAT_VER, sizeof(bin_header->rbfv)) != 0) { - return MRB_DUMP_INVALID_FILE_HEADER; //File format version error - } - memcpy(bin_header->risv, file_header.risv, sizeof(file_header.risv)); - memcpy(bin_header->rct, file_header.rct, sizeof(file_header.rct)); - memcpy(bin_header->rcv, file_header.rcv, sizeof(file_header.rcv)); - hex_to_bin32(bin_header->rbds, file_header.rbds); - hex_to_bin16(bin_header->nirep, file_header.nirep); - hex_to_bin16(bin_header->sirep, file_header.sirep); - memcpy(bin_header->rsv, file_header.rsv, sizeof(file_header.rsv)); - memcpy(hcrc, file_header.hcrc, sizeof(file_header.hcrc)); - - return MRB_DUMP_OK; -} -#endif /* ENABLE_STDIO */ - -#ifdef ENABLE_STDIO -static int -load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_t* len) -{ - int i; - uint32_t blocklen; - uint16_t offset, pdl, snl, clen; - unsigned char hex2[2] = {0}, hex4[4] = {0}, hex8[8] = {0}, hcrc[4] = {0}; - unsigned char *pStart; - char *char_buf; - uint16_t buf_size =0; - int result; - - buf_size = MRB_DUMP_DEFAULT_STR_LEN; - char_buf = (char *)mrb_malloc(mrb, buf_size); - if (char_buf == NULL) { - result = MRB_DUMP_GENERAL_FAILURE; - goto error_exit; - } - - pStart = dst; - - //IREP HEADER BLOCK - *dst = rite_fgetc(rfp, TRUE); //record identifier - if (*dst != RITE_IREP_IDENFIFIER) { - result = MRB_DUMP_INVALID_IREP; - goto error_exit; - } - dst += sizeof(unsigned char); - *dst = rite_fgetc(rfp, TRUE); //class or module - dst += sizeof(unsigned char); - rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //number of local variable - dst += hex_to_bin16(dst, hex4); - rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //number of register variable - dst += hex_to_bin16(dst, hex4); - rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //offset of isec block - offset = hex_to_uint16(hex4); - rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //header CRC - memset( char_buf, '\0', buf_size); - rite_fgets(rfp, (unsigned char*)char_buf, (offset - (MRB_DUMP_SIZE_OF_SHORT * RITE_FILE_HEX_SIZE)), TRUE); //class or module name - hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT + MRB_DUMP_SIZE_OF_SHORT), &clen); //class or module name - dst += uint16_to_bin((MRB_DUMP_SIZE_OF_SHORT/*crc*/ + clen), (char*)dst); //offset of isec block - dst += hex_to_bin16(dst, hcrc); //header CRC - dst += clen; - - //ISEQ BLOCK - rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //iseq length - dst += hex_to_bin32(dst, hex8); - blocklen = hex_to_uint32(hex8); - for (i=0; i<blocklen; i++) { - rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //iseq - dst += hex_to_bin32(dst, hex8); - } - rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //iseq CRC - dst += hex_to_bin16(dst, hcrc); - - //POOL BLOCK - rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //pool length - dst += hex_to_bin32(dst, hex8); - blocklen = hex_to_uint32(hex8); - for (i=0; i<blocklen; i++) { - rite_fgets(rfp, hex2, sizeof(hex2), TRUE); //TT - dst += hex_to_bin8(dst, hex2); - rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //pool data length - pdl = hex_to_uint16(hex4); - - if ( pdl > buf_size - 1) { - buf_size = pdl + 1; - char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size); - if (char_buf == NULL) { - result = MRB_DUMP_GENERAL_FAILURE; - goto error_exit; - } - } - memset(char_buf, '\0', buf_size); - rite_fgets(rfp, (unsigned char*)char_buf, pdl, FALSE); //pool - hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT), &clen); - dst += uint16_to_bin(clen, (char*)dst); - dst += clen; - } - rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //pool CRC - dst += hex_to_bin16(dst, hcrc); - - //SYMS BLOCK - rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //syms length - dst += hex_to_bin32(dst, hex8); - blocklen = hex_to_uint32(hex8); - for (i=0; i<blocklen; i++) { - rite_fgets(rfp, hex4, sizeof(hex4), TRUE); //symbol name length - snl = hex_to_uint16(hex4); - - if (snl == MRB_DUMP_NULL_SYM_LEN) { - dst += uint16_to_bin(snl, (char*)dst); - continue; - } - - if ( snl > buf_size - 1) { - buf_size = snl + 1; - char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size); - if (char_buf == NULL) { - result = MRB_DUMP_GENERAL_FAILURE; - goto error_exit; - } - } - memset(char_buf, '\0', buf_size); - rite_fgets(rfp, (unsigned char*)char_buf, snl, FALSE); //symbol name - hex_to_str(char_buf, (char*)(dst + MRB_DUMP_SIZE_OF_SHORT), &clen); - dst += uint16_to_bin(clen, (char*)dst); - dst += clen; - } - rite_fgets(rfp, hcrc, sizeof(hcrc), TRUE); //syms CRC - dst += hex_to_bin16(dst, hcrc); - - *len = dst - pStart; - - result = MRB_DUMP_OK; -error_exit: - mrb_free(mrb, char_buf); - - return result; -} -#endif /* ENABLE_STDIO */ - -#ifdef ENABLE_STDIO -int -mrb_read_irep_file(mrb_state *mrb, FILE* fp) -{ - int ret, i; - uint32_t len, rlen = 0; - unsigned char hex8[8], hcrc[4]; - unsigned char *dst, *rite_dst = NULL; - rite_binary_header bin_header; - RiteFILE ritefp = { 0 }; - RiteFILE *rfp; - - if ((mrb == NULL) || (fp == NULL)) { - return MRB_DUMP_INVALID_ARGUMENT; - } - ritefp.fp = fp; - rfp = &ritefp; - - //Read File Header Section - ret = load_rite_header(fp, &bin_header, hcrc); - if (ret != MRB_DUMP_OK) - return ret; - - len = sizeof(rite_binary_header) + bin_to_uint32(bin_header.rbds); - rite_dst = (unsigned char *)mrb_malloc(mrb, len); - if (rite_dst == NULL) - return MRB_DUMP_GENERAL_FAILURE; - - dst = rite_dst; - memset(dst, 0x00, len); - *(rite_binary_header *)dst = bin_header; - dst += sizeof(rite_binary_header); - dst += hex_to_bin16(dst, hcrc); - - //Read Binary Data Section - len = bin_to_uint16(bin_header.nirep); - for (i=0; i<len; i++) { - rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //record len - dst += hex_to_bin32(dst, hex8); - ret = load_rite_irep_record(mrb, rfp, dst, &rlen); - if (ret != MRB_DUMP_OK) //irep info - goto error_exit; - dst += rlen; - } - rite_fgets(rfp, hex8, sizeof(hex8), TRUE); //dummy record len - hex_to_bin32(dst, hex8); /* dst += hex_to_bin32(dst, hex8); */ - if (0 != hex_to_uint32(hex8)) { - ret = MRB_DUMP_INVALID_IREP; - goto error_exit; - } - - if (ret == MRB_DUMP_OK) - ret = mrb_read_irep(mrb, (char*)rite_dst); -error_exit: - mrb_free(mrb, rite_dst); - - return ret; -} -#endif /* ENABLE_STDIO */ - -static int -read_rite_header(mrb_state *mrb, unsigned char *bin, rite_binary_header* bin_header) +static size_t +offset_crc_body() { - uint16_t crc; - - *bin_header = *(rite_binary_header *)bin; - bin += sizeof(rite_binary_header); - if (memcmp(bin_header->rbfi, RITE_FILE_IDENFIFIER, sizeof(bin_header->rbfi)) != 0) { - return MRB_DUMP_INVALID_FILE_HEADER; //File identifier error - } - if (memcmp(bin_header->risv, RITE_VM_VER, sizeof(bin_header->risv)) != 0) { - return MRB_DUMP_INVALID_FILE_HEADER; //Instruction set version check - } - - crc = calc_crc_16_ccitt((unsigned char*)bin_header, sizeof(*bin_header)); //Calculate CRC - if (crc != bin_to_uint16(bin)) { - return MRB_DUMP_INVALID_FILE_HEADER; //CRC error - } - - return bin_to_uint16(bin_header->nirep); + struct rite_binary_header header; + return ((void*)header.binary_crc - (void*)&header) + sizeof(header.binary_crc); } static int -read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len) +read_rite_irep_record(mrb_state *mrb, const unsigned char *bin, uint32_t *len) { int i, ret = MRB_DUMP_OK; char *buf; - unsigned char *recordStart, *pStart; - uint16_t crc, tt, pdl, snl, offset, bufsize=MRB_DUMP_DEFAULT_STR_LEN; + const unsigned char *src = bin; + uint16_t tt, pool_data_len, snl, buf_size = MRB_DUMP_DEFAULT_STR_LEN; mrb_int fix_num; mrb_float f; int plen; int ai = mrb_gc_arena_save(mrb); mrb_irep *irep = mrb_add_irep(mrb); - recordStart = src; - buf = (char *)mrb_malloc(mrb, bufsize); + buf = (char *)mrb_malloc(mrb, buf_size); if (buf == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } - //Header Section - pStart = src; - if (*src != RITE_IREP_IDENFIFIER) - return MRB_DUMP_INVALID_IREP; - src += (sizeof(unsigned char) * 2); - irep->nlocals = bin_to_uint16(src); //number of local variable - src += MRB_DUMP_SIZE_OF_SHORT; - irep->nregs = bin_to_uint16(src); //number of register variable - src += MRB_DUMP_SIZE_OF_SHORT; - offset = bin_to_uint16(src); //offset of isec block - src += MRB_DUMP_SIZE_OF_SHORT; - crc = calc_crc_16_ccitt(pStart, src - pStart); //Calculate CRC - if (crc != bin_to_uint16(src)) //header CRC - return MRB_DUMP_INVALID_IREP; - src += offset; - - //Binary Data Section - //ISEQ BLOCK - pStart = src; - irep->ilen = bin_to_uint32(src); //iseq length - src += MRB_DUMP_SIZE_OF_LONG; + // skip record size + src += sizeof(uint32_t); + + // number of local variable + irep->nlocals = bin_to_uint16(src); + src += sizeof(uint16_t); + + // number of register variable + irep->nregs = bin_to_uint16(src); + src += sizeof(uint16_t); + + // Binary Data Section + // ISEQ BLOCK + irep->ilen = bin_to_uint32(src); + src += sizeof(uint32_t); if (irep->ilen > 0) { irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen); if (irep->iseq == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } - for (i=0; i<irep->ilen; i++) { + for (i = 0; i < irep->ilen; i++) { irep->iseq[i] = bin_to_uint32(src); //iseq - src += MRB_DUMP_SIZE_OF_LONG; + src += sizeof(uint32_t); } } - crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC - if (crc != bin_to_uint16(src)) { //iseq CRC - ret = MRB_DUMP_INVALID_IREP; - goto error_exit; - } - src += MRB_DUMP_SIZE_OF_SHORT; //POOL BLOCK - pStart = src; - plen = bin_to_uint32(src); //pool length - src += MRB_DUMP_SIZE_OF_LONG; + plen = bin_to_uint32(src); /* number of pool */ + src += sizeof(uint32_t); if (plen > 0) { irep->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value) * plen); if (irep->pool == NULL) { @@ -417,25 +75,23 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len) goto error_exit; } - for (i=0; i<plen; i++) { - tt = *src; //pool TT - src += sizeof(unsigned char); - pdl = bin_to_uint16(src); //pool data length - src += MRB_DUMP_SIZE_OF_SHORT; - if (pdl > bufsize - 1) { + for (i = 0; i < plen; i++) { + tt = *src++; //pool TT + pool_data_len = bin_to_uint16(src); //pool data length + src += sizeof(uint16_t); + if (pool_data_len > buf_size - 1) { mrb_free(mrb, buf); - bufsize = pdl + 1; - buf = (char *)mrb_malloc(mrb, bufsize); + buf_size = pool_data_len + 1; + buf = (char *)mrb_malloc(mrb, buf_size); if (buf == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } } - memcpy(buf, src, pdl); - src += pdl; - buf[pdl] = '\0'; - - switch (tt) { //pool data + memcpy(buf, src, pool_data_len); + src += pool_data_len; + buf[pool_data_len] = '\0'; + switch (tt) { //pool data case MRB_TT_FIXNUM: fix_num = str_to_mrb_int(buf); irep->pool[i] = mrb_fixnum_value(fix_num); @@ -447,7 +103,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len) break; case MRB_TT_STRING: - irep->pool[i] = mrb_str_new(mrb, buf, pdl); + irep->pool[i] = mrb_str_new(mrb, buf, pool_data_len); break; default: @@ -458,17 +114,10 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len) mrb_gc_arena_restore(mrb, ai); } } - crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC - if (crc != bin_to_uint16(src)) { //pool CRC - ret = MRB_DUMP_INVALID_IREP; - goto error_exit; - } - src += MRB_DUMP_SIZE_OF_SHORT; //SYMS BLOCK - pStart = src; - irep->slen = bin_to_uint32(src); //syms length - src += MRB_DUMP_SIZE_OF_LONG; + irep->slen = bin_to_uint32(src); //syms length + src += sizeof(uint32_t); if (irep->slen > 0) { irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen); if (irep->syms == NULL) { @@ -480,80 +129,62 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, uint32_t* len) static const mrb_sym mrb_sym_zero = { 0 }; *irep->syms = mrb_sym_zero; } - for (i=0; i<irep->slen; i++) { + for (i = 0; i < irep->slen; i++) { snl = bin_to_uint16(src); //symbol name length - src += MRB_DUMP_SIZE_OF_SHORT; + src += sizeof(uint16_t); if (snl == MRB_DUMP_NULL_SYM_LEN) { irep->syms[i] = 0; continue; } - if (snl > bufsize - 1) { + if (snl > buf_size - 1) { mrb_free(mrb, buf); - bufsize = snl + 1; - buf = (char *)mrb_malloc(mrb, bufsize); + buf_size = snl + 1; + buf = (char *)mrb_malloc(mrb, buf_size); if (buf == NULL) { ret = MRB_DUMP_GENERAL_FAILURE; goto error_exit; } } - memcpy(buf, src, snl); //symbol name + memcpy(buf, src, snl); //symbol name src += snl; buf[snl] = '\0'; irep->syms[i] = mrb_intern2(mrb, buf, snl); } } - crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC - if (crc != bin_to_uint16(src)) { //syms CRC - ret = MRB_DUMP_INVALID_IREP; - goto error_exit; - } - src += MRB_DUMP_SIZE_OF_SHORT; + *len = src - bin; - *len = src - recordStart; error_exit: mrb_free(mrb, buf); - return ret; } -int -mrb_read_irep(mrb_state *mrb, const char *bin) +static int +read_rite_section_irep(mrb_state *mrb, const unsigned char *bin) { - int ret = MRB_DUMP_OK, i, n, nirep, sirep; - uint32_t len = 0; - unsigned char *src; - rite_binary_header bin_header; - - if ((mrb == NULL) || (bin == NULL)) { - return MRB_DUMP_INVALID_ARGUMENT; - } - src = (unsigned char*)bin; - sirep = mrb->irep_len; + int n, i, result = MRB_DUMP_OK; + uint32_t len, sirep; + uint16_t nirep; + const struct rite_section_irep_header *header; - //Read File Header Section - nirep = read_rite_header(mrb, src, &bin_header); - if (nirep < 0) - return nirep; + header = (const struct rite_section_irep_header*)bin; + bin += sizeof(struct rite_section_irep_header); - src += sizeof(bin_header) + MRB_DUMP_SIZE_OF_SHORT; //header + crc + sirep = mrb->irep_len; + nirep = bin_to_uint16(header->nirep); //Read Binary Data Section - for (n=0,i=sirep; n<nirep; n++,i++) { - src += MRB_DUMP_SIZE_OF_LONG; //record ren - ret = read_rite_irep_record(mrb, src, &len); - if (ret != MRB_DUMP_OK) + for (n = 0, i = sirep; n < nirep; n++, i++) { + result = read_rite_irep_record(mrb, bin, &len); + if (result != MRB_DUMP_OK) goto error_exit; - src += len; - } - if (0 != bin_to_uint32(src)) { //dummy record len - ret = MRB_DUMP_GENERAL_FAILURE; + bin += len; } error_exit: - if (ret != MRB_DUMP_OK) { - for (n=0,i=sirep; i<mrb->irep_len; n++,i++) { + if (result != MRB_DUMP_OK) { + for (n = 0, i = sirep; i < mrb->irep_len; n++, i++) { if (mrb->irep[i]) { if (mrb->irep[i]->iseq) mrb_free(mrb, mrb->irep[i]->iseq); @@ -567,147 +198,198 @@ error_exit: mrb_free(mrb, mrb->irep[i]); } } - // mrb->irep_len = sirep; - return ret; + return result; } - return sirep + hex_to_uint8(bin_header.sirep); + return sirep + bin_to_uint16(header->sirep); } -static uint16_t -hex_to_bin8(unsigned char *dst, unsigned char *src) +static int +read_rite_binary_header(const unsigned char *bin, uint32_t *bin_size, uint16_t *crc) { - dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]); - return 1; -} + const struct rite_binary_header *header = (const struct rite_binary_header *)bin; -static uint16_t -hex_to_bin16(unsigned char *dst, unsigned char *src) -{ - dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]); - dst[1] = (hex2bin[src[2]] << 4) | (hex2bin[src[3]]); - return 2; -} + if(memcmp(header->binary_identify, RITE_BINARY_IDENFIFIER, sizeof(header->binary_identify)) != 0) { + return MRB_DUMP_INVALID_FILE_HEADER; + } + + if(memcmp(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)) != 0) { + return MRB_DUMP_INVALID_FILE_HEADER; + } -static uint16_t -hex_to_bin32(unsigned char *dst, unsigned char *src) -{ - dst[0] = (hex2bin[src[0]] << 4) | (hex2bin[src[1]]); - dst[1] = (hex2bin[src[2]] << 4) | (hex2bin[src[3]]); - dst[2] = (hex2bin[src[4]] << 4) | (hex2bin[src[5]]); - dst[3] = (hex2bin[src[6]] << 4) | (hex2bin[src[7]]); - return 4; -} + *crc = bin_to_uint16(header->binary_crc); + *bin_size = bin_to_uint32(header->binary_size); -static uint8_t -hex_to_uint8(unsigned char *hex) -{ - return (unsigned char)hex2bin[hex[0]] << 4 | - (unsigned char)hex2bin[hex[1]]; + return MRB_DUMP_OK; } -static uint16_t -hex_to_uint16(unsigned char *hex) +int +mrb_read_irep(mrb_state *mrb, const unsigned char *bin) { - return (uint16_t)hex2bin[hex[0]] << 12 | - (uint16_t)hex2bin[hex[1]] << 8 | - (uint16_t)hex2bin[hex[2]] << 4 | - (uint16_t)hex2bin[hex[3]]; -} + int total_nirep = 0, result = MRB_DUMP_OK; + const struct rite_section_header *section_header; + uint16_t crc; + uint32_t bin_size = 0, n; -static uint32_t -hex_to_uint32(unsigned char *hex) -{ - return (uint32_t)hex2bin[hex[0]] << 28 | - (uint32_t)hex2bin[hex[1]] << 24 | - (uint32_t)hex2bin[hex[2]] << 20 | - (uint32_t)hex2bin[hex[3]] << 16 | - (uint32_t)hex2bin[hex[4]] << 12 | - (uint32_t)hex2bin[hex[5]] << 8 | - (uint32_t)hex2bin[hex[6]] << 4 | - (uint32_t)hex2bin[hex[7]]; -} + if ((mrb == NULL) || (bin == NULL)) { + return MRB_DUMP_INVALID_ARGUMENT; + } -static char* -hex_to_str(char *hex, char *str, uint16_t *str_len) -{ - char *src, *dst, buf[4]; - int escape = 0, base = 0; - char *err_ptr; - - *str_len = 0; - for (src = hex, dst = str; *src != '\0'; src++) { - if (escape) { - switch(*src) { - case 'a': *dst++ = '\a'/* BEL */; break; - case 'b': *dst++ = '\b'/* BS */; break; - case 't': *dst++ = '\t'/* HT */; break; - case 'n': *dst++ = '\n'/* LF */; break; - case 'v': *dst++ = '\v'/* VT */; break; - case 'f': *dst++ = '\f'/* FF */; break; - case 'r': *dst++ = '\r'/* CR */; break; - case '\"': /* fall through */ - case '\'': /* fall through */ - case '\?': /* fall through */ - case '\\': *dst++ = *src; break; - default: - if (*src >= '0' && *src <= '7') { - base = 8; - strncpy(buf, src, 3); - } else if (*src == 'x' || *src == 'X') { - base = 16; - src++; - strncpy(buf, src, 2); - } + result = read_rite_binary_header(bin, &bin_size, &crc); + if(result != MRB_DUMP_OK) { + return result; + } - *dst++ = (unsigned char) strtol(buf, &err_ptr, base) & 0xff; - src += (err_ptr - buf - 1); - break; - } - escape = 0; - } else { - if (*src == '\\') { - escape = 1; - } else { - escape = 0; - *dst++ = *src; + n = offset_crc_body(); + if(crc != calc_crc_16_ccitt(bin + n, bin_size - n, 0)) { + return MRB_DUMP_INVALID_FILE_HEADER; + } + + bin += sizeof(struct rite_binary_header); + + do { + section_header = (const struct rite_section_header *)bin; + if(memcmp(section_header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header->section_identify)) == 0) { + result = read_rite_section_irep(mrb, bin); + if(result < MRB_DUMP_OK) { + return result; } + total_nirep += result; } - if (!escape) { - (*str_len)++; - } - } - return str; + bin += bin_to_uint32(section_header->section_size); + } while(memcmp(section_header->section_identify, RITE_BINARY_EOF, sizeof(section_header->section_identify)) != 0); + + return total_nirep; } static void -irep_error(mrb_state *mrb, int n) +irep_error(mrb_state *mrb, const char *msg) { - static const char msg[] = "irep load error"; - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, strlen(msg))); } -#ifdef ENABLE_STDIO mrb_value -mrb_load_irep_file(mrb_state *mrb, FILE* fp) +mrb_load_irep(mrb_state *mrb, const unsigned char *bin) { - int n = mrb_read_irep_file(mrb, fp); + int n; + n = mrb_read_irep(mrb, bin); if (n < 0) { - irep_error(mrb, n); + irep_error(mrb, "irep load error"); return mrb_nil_value(); } return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); } -#endif -mrb_value -mrb_load_irep(mrb_state *mrb, const char *bin) +#ifdef ENABLE_STDIO + +static int +read_rite_section_irep_file(mrb_state *mrb, FILE *fp) { - int n = mrb_read_irep(mrb, bin); + int n, i, result = MRB_DUMP_OK; + uint16_t sirep, nirep; + uint32_t len, buf_size; + unsigned char *buf = NULL; + const int record_header_size = 1 + 4; - if (n < 0) { - irep_error(mrb, n); - return mrb_nil_value(); + struct rite_section_irep_header header; + fread(&header, sizeof(struct rite_section_irep_header), 1, fp); + + sirep = mrb->irep_len; + nirep = bin_to_uint16(header.nirep); + + buf_size = record_header_size; + buf = mrb_malloc(mrb, buf_size); + + //Read Binary Data Section + for (n = 0, i = sirep; n < nirep; n++, i++) { + fread(buf, record_header_size, 1, fp); + buf_size = bin_to_uint32(&buf[0]); + buf = mrb_realloc(mrb, buf, buf_size); + fread(&buf[record_header_size], buf_size - record_header_size, 1, fp); + result = read_rite_irep_record(mrb, buf, &len); + if (result != MRB_DUMP_OK) + goto error_exit; } - return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); + +error_exit: + mrb_free(mrb, buf); + if (result != MRB_DUMP_OK) { + for (n = 0, i = sirep; i < mrb->irep_len; n++, i++) { + if (mrb->irep[i]) { + if (mrb->irep[i]->iseq) + mrb_free(mrb, mrb->irep[i]->iseq); + + if (mrb->irep[i]->pool) + mrb_free(mrb, mrb->irep[i]->pool); + + if (mrb->irep[i]->syms) + mrb_free(mrb, mrb->irep[i]->syms); + + mrb_free(mrb, mrb->irep[i]); + } + } + return result; + } + return sirep + bin_to_uint16(header.sirep); +} + +int +mrb_read_irep_file(mrb_state *mrb, FILE* fp) +{ + int total_nirep = 0, result = MRB_DUMP_OK; + unsigned char *buf; + uint16_t crc, crcwk = 0; + uint32_t bin_size = 0, buf_size = 0, section_size = 0; + size_t nbytes; + struct rite_section_header section_header; + long fpos; + const size_t block_size = 1 << 14; + + if ((mrb == NULL) || (fp == NULL)) { + return MRB_DUMP_INVALID_ARGUMENT; + } + + buf_size = sizeof(struct rite_binary_header); + buf = mrb_malloc(mrb, buf_size); + fread(buf, sizeof(struct rite_binary_header), 1, fp); + result = read_rite_binary_header(buf, &bin_size, &crc); + mrb_free(mrb, buf); + if(result != MRB_DUMP_OK) { + return result; + } + + /* verify CRC */ + fpos = ftell(fp); + buf = mrb_malloc(mrb, block_size); + fseek(fp, offset_crc_body(), SEEK_SET); + while((nbytes = fread(buf, 1, block_size, fp)) > 0) { + crcwk = calc_crc_16_ccitt(buf, nbytes, crcwk); + } + mrb_free(mrb, buf); + if(crcwk != crc) { + return MRB_DUMP_INVALID_FILE_HEADER; + } + fseek(fp, fpos + section_size, SEEK_SET); + + // read sections + do { + fpos = ftell(fp); + fread(§ion_header, sizeof(struct rite_section_header), 1, fp); + section_size = bin_to_uint32(section_header.section_size); + + if(memcmp(section_header.section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header.section_identify)) == 0) { + fseek(fp, fpos, SEEK_SET); + result = read_rite_section_irep_file(mrb, fp); + if(result < MRB_DUMP_OK) { + return result; + } + total_nirep += result; + } + + fseek(fp, fpos + section_size, SEEK_SET); + } while(memcmp(section_header.section_identify, RITE_BINARY_EOF, sizeof(section_header.section_identify)) != 0); + + return total_nirep; } + +#endif /* ENABLE_STDIO */ |
