This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.

Dependencies:   mbed

For details, refer to the following.

http://www.s-itoc.jp/activity/research/mrubyc/mrubyc_tutorial/436

Note:There is a change in rtt0.h from the original source in the mruby/c. It was necessary for inclusion in C ++ source.

Committer:
tk_takateku
Date:
Wed Feb 15 01:03:35 2017 +0000
Revision:
0:33feccbba3ff
Commit before publishing

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tk_takateku 0:33feccbba3ff 1 /*! @file
tk_takateku 0:33feccbba3ff 2 @brief
tk_takateku 0:33feccbba3ff 3 mruby bytecode loader.
tk_takateku 0:33feccbba3ff 4
tk_takateku 0:33feccbba3ff 5 <pre>
tk_takateku 0:33feccbba3ff 6 Copyright (C) 2015 Kyushu Institute of Technology.
tk_takateku 0:33feccbba3ff 7 Copyright (C) 2015 Shimane IT Open-Innovation Center.
tk_takateku 0:33feccbba3ff 8
tk_takateku 0:33feccbba3ff 9 This file is distributed under BSD 3-Clause License.
tk_takateku 0:33feccbba3ff 10
tk_takateku 0:33feccbba3ff 11 </pre>
tk_takateku 0:33feccbba3ff 12 */
tk_takateku 0:33feccbba3ff 13
tk_takateku 0:33feccbba3ff 14 #include <stdlib.h>
tk_takateku 0:33feccbba3ff 15 #include <stdint.h>
tk_takateku 0:33feccbba3ff 16 #include <string.h>
tk_takateku 0:33feccbba3ff 17 #include "vm.h"
tk_takateku 0:33feccbba3ff 18 #include "vm_config.h"
tk_takateku 0:33feccbba3ff 19 #include "load.h"
tk_takateku 0:33feccbba3ff 20 #include "errorcode.h"
tk_takateku 0:33feccbba3ff 21 #include "static.h"
tk_takateku 0:33feccbba3ff 22 #include "value.h"
tk_takateku 0:33feccbba3ff 23
tk_takateku 0:33feccbba3ff 24
tk_takateku 0:33feccbba3ff 25 //================================================================
tk_takateku 0:33feccbba3ff 26 /*!@brief
tk_takateku 0:33feccbba3ff 27 Parse header section.
tk_takateku 0:33feccbba3ff 28
tk_takateku 0:33feccbba3ff 29 @param vm A pointer of VM.
tk_takateku 0:33feccbba3ff 30 @param pos A pointer of pointer of RITE header.
tk_takateku 0:33feccbba3ff 31 @return int zero if no error.
tk_takateku 0:33feccbba3ff 32
tk_takateku 0:33feccbba3ff 33 <pre>
tk_takateku 0:33feccbba3ff 34 Structure
tk_takateku 0:33feccbba3ff 35 "RITE" identifier
tk_takateku 0:33feccbba3ff 36 "0003" version
tk_takateku 0:33feccbba3ff 37 0000 CRC
tk_takateku 0:33feccbba3ff 38 0000_0000 total size
tk_takateku 0:33feccbba3ff 39 "MATZ" compiler name
tk_takateku 0:33feccbba3ff 40 "0000" compiler version
tk_takateku 0:33feccbba3ff 41 </pre>
tk_takateku 0:33feccbba3ff 42 */
tk_takateku 0:33feccbba3ff 43 static int load_header(struct VM *vm, const uint8_t **pos)
tk_takateku 0:33feccbba3ff 44 {
tk_takateku 0:33feccbba3ff 45 const uint8_t *p = *pos;
tk_takateku 0:33feccbba3ff 46
tk_takateku 0:33feccbba3ff 47 if( memcmp(p + 4, "0003", 4) != 0 ) {
tk_takateku 0:33feccbba3ff 48 vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION;
tk_takateku 0:33feccbba3ff 49 return -1;
tk_takateku 0:33feccbba3ff 50 }
tk_takateku 0:33feccbba3ff 51
tk_takateku 0:33feccbba3ff 52 /* Ignore CRC */
tk_takateku 0:33feccbba3ff 53
tk_takateku 0:33feccbba3ff 54 /* Ignore size */
tk_takateku 0:33feccbba3ff 55
tk_takateku 0:33feccbba3ff 56 if( memcmp(p + 14, "MATZ", 4) != 0 ) {
tk_takateku 0:33feccbba3ff 57 vm->error_code = LOAD_FILE_HEADER_ERROR_MATZ;
tk_takateku 0:33feccbba3ff 58 return -1;
tk_takateku 0:33feccbba3ff 59 }
tk_takateku 0:33feccbba3ff 60 if( memcmp(p + 18, "0000", 4) != 0 ) {
tk_takateku 0:33feccbba3ff 61 vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION;
tk_takateku 0:33feccbba3ff 62 return -1;
tk_takateku 0:33feccbba3ff 63 }
tk_takateku 0:33feccbba3ff 64
tk_takateku 0:33feccbba3ff 65 *pos += 22;
tk_takateku 0:33feccbba3ff 66 return 0;
tk_takateku 0:33feccbba3ff 67 }
tk_takateku 0:33feccbba3ff 68
tk_takateku 0:33feccbba3ff 69
tk_takateku 0:33feccbba3ff 70 //================================================================
tk_takateku 0:33feccbba3ff 71 /*!@brief
tk_takateku 0:33feccbba3ff 72 Parse IREP section.
tk_takateku 0:33feccbba3ff 73
tk_takateku 0:33feccbba3ff 74 @param vm A pointer of VM.
tk_takateku 0:33feccbba3ff 75 @param pos A pointer of pointer of IREP section.
tk_takateku 0:33feccbba3ff 76 @return int zero if no error.
tk_takateku 0:33feccbba3ff 77
tk_takateku 0:33feccbba3ff 78 <pre>
tk_takateku 0:33feccbba3ff 79 Structure
tk_takateku 0:33feccbba3ff 80 "IREP" section identifier
tk_takateku 0:33feccbba3ff 81 0000_0000 section size
tk_takateku 0:33feccbba3ff 82 "0000" rite version
tk_takateku 0:33feccbba3ff 83
tk_takateku 0:33feccbba3ff 84 (loop n of child irep bellow)
tk_takateku 0:33feccbba3ff 85 0000_0000 record size
tk_takateku 0:33feccbba3ff 86 0000 n of local variable
tk_takateku 0:33feccbba3ff 87 0000 n of register
tk_takateku 0:33feccbba3ff 88 0000 n of child irep
tk_takateku 0:33feccbba3ff 89
tk_takateku 0:33feccbba3ff 90 0000_0000 n of byte code (ISEQ BLOCK)
tk_takateku 0:33feccbba3ff 91 ... byte codes
tk_takateku 0:33feccbba3ff 92
tk_takateku 0:33feccbba3ff 93 0000_0000 n of pool (POOL BLOCK)
tk_takateku 0:33feccbba3ff 94 (loop n of pool)
tk_takateku 0:33feccbba3ff 95 00 type
tk_takateku 0:33feccbba3ff 96 0000 length
tk_takateku 0:33feccbba3ff 97 ... pool data
tk_takateku 0:33feccbba3ff 98
tk_takateku 0:33feccbba3ff 99 0000_0000 n of symbol (SYMS BLOCK)
tk_takateku 0:33feccbba3ff 100 (loop n of symbol)
tk_takateku 0:33feccbba3ff 101 0000 length
tk_takateku 0:33feccbba3ff 102 ... symbol data
tk_takateku 0:33feccbba3ff 103 </pre>
tk_takateku 0:33feccbba3ff 104 */
tk_takateku 0:33feccbba3ff 105 static int load_irep(struct VM *vm, const uint8_t **pos)
tk_takateku 0:33feccbba3ff 106 {
tk_takateku 0:33feccbba3ff 107 const uint8_t *p = *pos;
tk_takateku 0:33feccbba3ff 108 p += 4;
tk_takateku 0:33feccbba3ff 109 int section_size = bin_to_uint32(p);
tk_takateku 0:33feccbba3ff 110 p += 4;
tk_takateku 0:33feccbba3ff 111
tk_takateku 0:33feccbba3ff 112 if( memcmp(p, "0000", 4) != 0 ) {
tk_takateku 0:33feccbba3ff 113 vm->error_code = LOAD_FILE_IREP_ERROR_VERSION;
tk_takateku 0:33feccbba3ff 114 return -1;
tk_takateku 0:33feccbba3ff 115 }
tk_takateku 0:33feccbba3ff 116 p += 4;
tk_takateku 0:33feccbba3ff 117
tk_takateku 0:33feccbba3ff 118 int cnt = 0;
tk_takateku 0:33feccbba3ff 119 while( cnt < section_size ) {
tk_takateku 0:33feccbba3ff 120 cnt += bin_to_uint32(p) + 8;
tk_takateku 0:33feccbba3ff 121 p += 4;
tk_takateku 0:33feccbba3ff 122
tk_takateku 0:33feccbba3ff 123 // new irep
tk_takateku 0:33feccbba3ff 124 mrb_irep *irep = new_irep(vm);
tk_takateku 0:33feccbba3ff 125 if( irep == 0 ) {
tk_takateku 0:33feccbba3ff 126 vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION;
tk_takateku 0:33feccbba3ff 127 return -1;
tk_takateku 0:33feccbba3ff 128 }
tk_takateku 0:33feccbba3ff 129
tk_takateku 0:33feccbba3ff 130 // add irep into vm->irep (at tail)
tk_takateku 0:33feccbba3ff 131 // TODO: Optimize this process
tk_takateku 0:33feccbba3ff 132 if( vm->irep == 0 ) {
tk_takateku 0:33feccbba3ff 133 vm->irep = irep;
tk_takateku 0:33feccbba3ff 134 } else {
tk_takateku 0:33feccbba3ff 135 mrb_irep *p = vm->irep;
tk_takateku 0:33feccbba3ff 136 while( p->next != 0 ) {
tk_takateku 0:33feccbba3ff 137 p = p->next;
tk_takateku 0:33feccbba3ff 138 }
tk_takateku 0:33feccbba3ff 139 p->next = irep;
tk_takateku 0:33feccbba3ff 140 }
tk_takateku 0:33feccbba3ff 141 irep->next = 0;
tk_takateku 0:33feccbba3ff 142
tk_takateku 0:33feccbba3ff 143 // nlocals,nregs,rlen
tk_takateku 0:33feccbba3ff 144 irep->nlocals = bin_to_uint16(p); p += 2;
tk_takateku 0:33feccbba3ff 145 irep->nregs = bin_to_uint16(p); p += 2;
tk_takateku 0:33feccbba3ff 146 irep->rlen = bin_to_uint16(p); p += 2;
tk_takateku 0:33feccbba3ff 147 irep->ilen = bin_to_uint32(p); p += 4;
tk_takateku 0:33feccbba3ff 148
tk_takateku 0:33feccbba3ff 149 // padding
tk_takateku 0:33feccbba3ff 150 p += (-(p - *pos + 2) & 0x03); // +2 = (RITE(22) + IREP(12)) & 0x03
tk_takateku 0:33feccbba3ff 151
tk_takateku 0:33feccbba3ff 152 // ISEQ (code) BLOCK
tk_takateku 0:33feccbba3ff 153 irep->code = (uint8_t *)p;
tk_takateku 0:33feccbba3ff 154 p += irep->ilen * 4;
tk_takateku 0:33feccbba3ff 155
tk_takateku 0:33feccbba3ff 156 // POOL BLOCK
tk_takateku 0:33feccbba3ff 157 irep->ptr_to_pool = 0;
tk_takateku 0:33feccbba3ff 158 int plen = bin_to_uint32(p); p += 4;
tk_takateku 0:33feccbba3ff 159 int i;
tk_takateku 0:33feccbba3ff 160 for( i=0 ; i<plen ; i++ ){
tk_takateku 0:33feccbba3ff 161 int tt = (int)*p++;
tk_takateku 0:33feccbba3ff 162 int obj_size = bin_to_uint16(p); p += 2;
tk_takateku 0:33feccbba3ff 163 mrb_object *ptr = mrbc_obj_alloc(vm, MRB_TT_FALSE);
tk_takateku 0:33feccbba3ff 164 if( ptr == 0 ){
tk_takateku 0:33feccbba3ff 165 vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION;
tk_takateku 0:33feccbba3ff 166 return -1;
tk_takateku 0:33feccbba3ff 167 }
tk_takateku 0:33feccbba3ff 168 switch( tt ){
tk_takateku 0:33feccbba3ff 169 #if MRBC_USE_STRING
tk_takateku 0:33feccbba3ff 170 case 0: { // IREP_TT_STRING
tk_takateku 0:33feccbba3ff 171 ptr->tt = MRB_TT_STRING;
tk_takateku 0:33feccbba3ff 172 ptr->value.str = (char*)p;
tk_takateku 0:33feccbba3ff 173 } break;
tk_takateku 0:33feccbba3ff 174 #endif
tk_takateku 0:33feccbba3ff 175 case 1: { // IREP_TT_FIXNUM
tk_takateku 0:33feccbba3ff 176 char buf[obj_size+1];
tk_takateku 0:33feccbba3ff 177 memcpy(buf, p, obj_size);
tk_takateku 0:33feccbba3ff 178 buf[obj_size] = '\0';
tk_takateku 0:33feccbba3ff 179 ptr->tt = MRB_TT_FIXNUM;
tk_takateku 0:33feccbba3ff 180 ptr->value.i = atoi(buf);
tk_takateku 0:33feccbba3ff 181 } break;
tk_takateku 0:33feccbba3ff 182 #if MRBC_USE_FLOAT
tk_takateku 0:33feccbba3ff 183 case 2: { // IREP_TT_FLOAT
tk_takateku 0:33feccbba3ff 184 char buf[obj_size+1];
tk_takateku 0:33feccbba3ff 185 memcpy(buf, p, obj_size);
tk_takateku 0:33feccbba3ff 186 buf[obj_size] = '\0';
tk_takateku 0:33feccbba3ff 187 ptr->tt = MRB_TT_FLOAT;
tk_takateku 0:33feccbba3ff 188 ptr->value.d = atof(buf);
tk_takateku 0:33feccbba3ff 189 } break;
tk_takateku 0:33feccbba3ff 190 #endif
tk_takateku 0:33feccbba3ff 191 default:
tk_takateku 0:33feccbba3ff 192 break;
tk_takateku 0:33feccbba3ff 193 }
tk_takateku 0:33feccbba3ff 194 if( irep->ptr_to_pool == 0 ){
tk_takateku 0:33feccbba3ff 195 irep->ptr_to_pool = ptr;
tk_takateku 0:33feccbba3ff 196 } else {
tk_takateku 0:33feccbba3ff 197 mrb_object *pp = irep->ptr_to_pool;
tk_takateku 0:33feccbba3ff 198 while( pp->next != 0 ) pp = pp->next;
tk_takateku 0:33feccbba3ff 199 pp->next = ptr;
tk_takateku 0:33feccbba3ff 200 }
tk_takateku 0:33feccbba3ff 201 p += obj_size;
tk_takateku 0:33feccbba3ff 202 }
tk_takateku 0:33feccbba3ff 203
tk_takateku 0:33feccbba3ff 204 // SYMS BLOCK
tk_takateku 0:33feccbba3ff 205 irep->ptr_to_sym = (uint8_t*)p;
tk_takateku 0:33feccbba3ff 206 int slen = bin_to_uint32(p); p += 4;
tk_takateku 0:33feccbba3ff 207 for( i=0 ; i<slen ; i++ ){
tk_takateku 0:33feccbba3ff 208 int s = bin_to_uint16(p); p += 2;
tk_takateku 0:33feccbba3ff 209 p += s+1;
tk_takateku 0:33feccbba3ff 210 }
tk_takateku 0:33feccbba3ff 211 }
tk_takateku 0:33feccbba3ff 212
tk_takateku 0:33feccbba3ff 213 /* TODO: size */
tk_takateku 0:33feccbba3ff 214 *pos += section_size;
tk_takateku 0:33feccbba3ff 215 return 0;
tk_takateku 0:33feccbba3ff 216 }
tk_takateku 0:33feccbba3ff 217
tk_takateku 0:33feccbba3ff 218
tk_takateku 0:33feccbba3ff 219 //================================================================
tk_takateku 0:33feccbba3ff 220 /*!@brief
tk_takateku 0:33feccbba3ff 221 Parse LVAR section.
tk_takateku 0:33feccbba3ff 222
tk_takateku 0:33feccbba3ff 223 @param vm A pointer of VM.
tk_takateku 0:33feccbba3ff 224 @param pos A pointer of pointer of LVAR section.
tk_takateku 0:33feccbba3ff 225 @return int zero if no error.
tk_takateku 0:33feccbba3ff 226 */
tk_takateku 0:33feccbba3ff 227 static int load_lvar(struct VM *vm, const uint8_t **pos)
tk_takateku 0:33feccbba3ff 228 {
tk_takateku 0:33feccbba3ff 229 const uint8_t *p = *pos;
tk_takateku 0:33feccbba3ff 230
tk_takateku 0:33feccbba3ff 231 /* size */
tk_takateku 0:33feccbba3ff 232 *pos += bin_to_uint32(p+4);
tk_takateku 0:33feccbba3ff 233
tk_takateku 0:33feccbba3ff 234 return 0;
tk_takateku 0:33feccbba3ff 235 }
tk_takateku 0:33feccbba3ff 236
tk_takateku 0:33feccbba3ff 237
tk_takateku 0:33feccbba3ff 238 //================================================================
tk_takateku 0:33feccbba3ff 239 /*!@brief
tk_takateku 0:33feccbba3ff 240 Setup mrb program
tk_takateku 0:33feccbba3ff 241
tk_takateku 0:33feccbba3ff 242 @param vm A pointer of VM.
tk_takateku 0:33feccbba3ff 243 @return int zero if no error.
tk_takateku 0:33feccbba3ff 244 */
tk_takateku 0:33feccbba3ff 245 int load_mrb(struct VM *vm)
tk_takateku 0:33feccbba3ff 246 {
tk_takateku 0:33feccbba3ff 247 int ret = -1;
tk_takateku 0:33feccbba3ff 248 const uint8_t *pos = vm->mrb;
tk_takateku 0:33feccbba3ff 249
tk_takateku 0:33feccbba3ff 250 if( memcmp(pos, "RITE", 4) == 0 ) {
tk_takateku 0:33feccbba3ff 251 ret = load_header(vm, &pos);
tk_takateku 0:33feccbba3ff 252 }
tk_takateku 0:33feccbba3ff 253 while( ret == 0 ) {
tk_takateku 0:33feccbba3ff 254 if( memcmp(pos, "IREP", 4) == 0 ) {
tk_takateku 0:33feccbba3ff 255 ret = load_irep(vm, &pos);
tk_takateku 0:33feccbba3ff 256 }
tk_takateku 0:33feccbba3ff 257 else if( memcmp(pos, "LVAR", 4) == 0 ) {
tk_takateku 0:33feccbba3ff 258 ret = load_lvar(vm, &pos);
tk_takateku 0:33feccbba3ff 259 }
tk_takateku 0:33feccbba3ff 260 else if( memcmp(pos, "END\0", 4) == 0 ) {
tk_takateku 0:33feccbba3ff 261 break;
tk_takateku 0:33feccbba3ff 262 }
tk_takateku 0:33feccbba3ff 263 }
tk_takateku 0:33feccbba3ff 264
tk_takateku 0:33feccbba3ff 265 return ret;
tk_takateku 0:33feccbba3ff 266 }
tk_takateku 0:33feccbba3ff 267
tk_takateku 0:33feccbba3ff 268
tk_takateku 0:33feccbba3ff 269 //================================================================
tk_takateku 0:33feccbba3ff 270 /*!@brief
tk_takateku 0:33feccbba3ff 271
tk_takateku 0:33feccbba3ff 272
tk_takateku 0:33feccbba3ff 273 @param vm A pointer of VM.
tk_takateku 0:33feccbba3ff 274 @param ptr A pointer of RITE (.mrb) code.
tk_takateku 0:33feccbba3ff 275
tk_takateku 0:33feccbba3ff 276 */
tk_takateku 0:33feccbba3ff 277 int loca_mrb_array(struct VM *vm, const uint8_t *ptr)
tk_takateku 0:33feccbba3ff 278 {
tk_takateku 0:33feccbba3ff 279 vm->mrb = ptr;
tk_takateku 0:33feccbba3ff 280 return load_mrb(vm);
tk_takateku 0:33feccbba3ff 281 }
tk_takateku 0:33feccbba3ff 282