mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers state.c Source File

state.c

00001 /*
00002 ** state.c - mrb_state open/close functions
00003 **
00004 ** See Copyright Notice in mruby.h
00005 */
00006 
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include "mruby.h"
00010 #include "mruby/irep.h"
00011 #include "mruby/variable.h"
00012 #include "mruby/debug.h"
00013 #include "mruby/string.h"
00014 
00015 void mrb_init_heap(mrb_state*);
00016 void mrb_init_core(mrb_state*);
00017 void mrb_init_mrbgems(mrb_state*);
00018 
00019 static mrb_value
00020 inspect_main(mrb_state *mrb, mrb_value mod)
00021 {
00022   return mrb_str_new_lit(mrb, "main");
00023 }
00024 
00025 MRB_API mrb_state*
00026 mrb_open_core(mrb_allocf f, void *ud)
00027 {
00028   static const mrb_state mrb_state_zero = { 0 };
00029   static const struct mrb_context mrb_context_zero = { 0 };
00030   mrb_state *mrb;
00031 
00032   mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
00033   if (mrb == NULL) return NULL;
00034 
00035   *mrb = mrb_state_zero;
00036   mrb->allocf_ud = ud;
00037   mrb->allocf = f;
00038   mrb->current_white_part = MRB_GC_WHITE_A;
00039   mrb->atexit_stack_len = 0;
00040 
00041 #ifndef MRB_GC_FIXED_ARENA
00042   mrb->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE);
00043   mrb->arena_capa = MRB_GC_ARENA_SIZE;
00044 #endif
00045 
00046   mrb_init_heap(mrb);
00047   mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
00048   *mrb->c = mrb_context_zero;
00049   mrb->root_c = mrb->c;
00050 
00051   mrb_init_core(mrb);
00052 
00053   return mrb;
00054 }
00055 
00056 void*
00057 mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud)
00058 {
00059   if (size == 0) {
00060     free(p);
00061     return NULL;
00062   }
00063   else {
00064     return realloc(p, size);
00065   }
00066 }
00067 
00068 struct alloca_header {
00069   struct alloca_header *next;
00070   char buf[];
00071 };
00072 
00073 MRB_API void*
00074 mrb_alloca(mrb_state *mrb, size_t size)
00075 {
00076   struct alloca_header *p;
00077 
00078   p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size);
00079   p->next = mrb->mems;
00080   mrb->mems = p;
00081   return (void*)p->buf;
00082 }
00083 
00084 static void
00085 mrb_alloca_free(mrb_state *mrb)
00086 {
00087   struct alloca_header *p;
00088   struct alloca_header *tmp;
00089 
00090   if (mrb == NULL) return;
00091   p = mrb->mems;
00092 
00093   while (p) {
00094     tmp = p;
00095     p = p->next;
00096     mrb_free(mrb, tmp);
00097   }
00098 }
00099 
00100 MRB_API mrb_state*
00101 mrb_open(void)
00102 {
00103   mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL);
00104 
00105   return mrb;
00106 }
00107 
00108 MRB_API mrb_state*
00109 mrb_open_allocf(mrb_allocf f, void *ud)
00110 {
00111   mrb_state *mrb = mrb_open_core(f, ud);
00112 
00113   if (mrb == NULL) {
00114     return NULL;
00115   }
00116 
00117 #ifndef DISABLE_GEMS
00118   mrb_init_mrbgems(mrb);
00119   mrb_gc_arena_restore(mrb, 0);
00120 #endif
00121   return mrb;
00122 }
00123 
00124 void mrb_free_symtbl(mrb_state *mrb);
00125 void mrb_free_heap(mrb_state *mrb);
00126 
00127 void
00128 mrb_irep_incref(mrb_state *mrb, mrb_irep *irep)
00129 {
00130   irep->refcnt++;
00131 }
00132 
00133 void
00134 mrb_irep_decref(mrb_state *mrb, mrb_irep *irep)
00135 {
00136   irep->refcnt--;
00137   if (irep->refcnt == 0) {
00138     mrb_irep_free(mrb, irep);
00139   }
00140 }
00141 
00142 void
00143 mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
00144 {
00145   size_t i;
00146 
00147   if (!(irep->flags & MRB_ISEQ_NO_FREE))
00148     mrb_free(mrb, irep->iseq);
00149   for (i=0; i<irep->plen; i++) {
00150     if (mrb_type(irep->pool[i]) == MRB_TT_STRING) {
00151       mrb_gc_free_str(mrb, RSTRING(irep->pool[i]));
00152       mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
00153     }
00154 #ifdef MRB_WORD_BOXING
00155     else if (mrb_type(irep->pool[i]) == MRB_TT_FLOAT) {
00156       mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
00157     }
00158 #endif
00159   }
00160   mrb_free(mrb, irep->pool);
00161   mrb_free(mrb, irep->syms);
00162   for (i=0; i<irep->rlen; i++) {
00163     mrb_irep_decref(mrb, irep->reps[i]);
00164   }
00165   mrb_free(mrb, irep->reps);
00166   mrb_free(mrb, irep->lv);
00167   mrb_free(mrb, (void *)irep->filename);
00168   mrb_free(mrb, irep->lines);
00169   mrb_debug_info_free(mrb, irep->debug_info);
00170   mrb_free(mrb, irep);
00171 }
00172 
00173 mrb_value
00174 mrb_str_pool(mrb_state *mrb, mrb_value str)
00175 {
00176   struct RString *s = mrb_str_ptr(str);
00177   struct RString *ns;
00178   char *ptr;
00179   mrb_int len;
00180 
00181   ns = (struct RString *)mrb_malloc(mrb, sizeof(struct RString));
00182   ns->tt = MRB_TT_STRING;
00183   ns->c = mrb->string_class;
00184 
00185   if (RSTR_NOFREE_P(s)) {
00186     ns->flags = MRB_STR_NOFREE;
00187     ns->as.heap.ptr = s->as.heap.ptr;
00188     ns->as.heap.len = s->as.heap.len;
00189     ns->as.heap.aux.capa = 0;
00190   }
00191   else {
00192     ns->flags = 0;
00193     if (RSTR_EMBED_P(s)) {
00194       ptr = s->as.ary;
00195       len = RSTR_EMBED_LEN(s);
00196     }
00197     else {
00198       ptr = s->as.heap.ptr;
00199       len = s->as.heap.len;
00200     }
00201 
00202     if (len < RSTRING_EMBED_LEN_MAX) {
00203       RSTR_SET_EMBED_FLAG(ns);
00204       RSTR_SET_EMBED_LEN(ns, len);
00205       if (ptr) {
00206         memcpy(ns->as.ary, ptr, len);
00207       }
00208       ns->as.ary[len] = '\0';
00209     }
00210     else {
00211       ns->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
00212       ns->as.heap.len = len;
00213       ns->as.heap.aux.capa = len;
00214       if (ptr) {
00215         memcpy(ns->as.heap.ptr, ptr, len);
00216       }
00217       ns->as.heap.ptr[len] = '\0';
00218     }
00219   }
00220   return mrb_obj_value(ns);
00221 }
00222 
00223 MRB_API void
00224 mrb_free_context(mrb_state *mrb, struct mrb_context *c)
00225 {
00226   if (!c) return;
00227   mrb_free(mrb, c->stbase);
00228   mrb_free(mrb, c->cibase);
00229   mrb_free(mrb, c->rescue);
00230   mrb_free(mrb, c->ensure);
00231   mrb_free(mrb, c);
00232 }
00233 
00234 MRB_API void
00235 mrb_close(mrb_state *mrb)
00236 {
00237   if (mrb->atexit_stack_len > 0) {
00238     mrb_int i;
00239     for (i = mrb->atexit_stack_len; i > 0; --i) {
00240       mrb->atexit_stack[i - 1](mrb);
00241     }
00242 #ifndef MRB_FIXED_STATE_ATEXIT_STACK
00243     mrb_free(mrb, mrb->atexit_stack);
00244 #endif
00245   }
00246 
00247   /* free */
00248   mrb_gc_free_gv(mrb);
00249   mrb_free_context(mrb, mrb->root_c);
00250   mrb_free_symtbl(mrb);
00251   mrb_free_heap(mrb);
00252   mrb_alloca_free(mrb);
00253 #ifndef MRB_GC_FIXED_ARENA
00254   mrb_free(mrb, mrb->arena);
00255 #endif
00256   mrb_free(mrb, mrb);
00257 }
00258 
00259 MRB_API mrb_irep*
00260 mrb_add_irep(mrb_state *mrb)
00261 {
00262   static const mrb_irep mrb_irep_zero = { 0 };
00263   mrb_irep *irep;
00264 
00265   irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
00266   *irep = mrb_irep_zero;
00267   irep->refcnt = 1;
00268 
00269   return irep;
00270 }
00271 
00272 MRB_API mrb_value
00273 mrb_top_self(mrb_state *mrb)
00274 {
00275   if (!mrb->top_self) {
00276     mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
00277     mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE());
00278     mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, MRB_ARGS_NONE());
00279   }
00280   return mrb_obj_value(mrb->top_self);
00281 }
00282 
00283 MRB_API void
00284 mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f)
00285 {
00286 #ifdef MRB_FIXED_STATE_ATEXIT_STACK
00287   if (mrb->atexit_stack_len + 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE) {
00288     mrb_raise(mrb, E_RUNTIME_ERROR, "exceeded fixed state atexit stack limit");
00289   }
00290 #else
00291   size_t stack_size;
00292 
00293   stack_size = sizeof(mrb_atexit_func) * (mrb->atexit_stack_len + 1);
00294   if (mrb->atexit_stack_len == 0) {
00295     mrb->atexit_stack = (mrb_atexit_func*)mrb_malloc(mrb, stack_size);
00296   } else {
00297     mrb->atexit_stack = (mrb_atexit_func*)mrb_realloc(mrb, mrb->atexit_stack, stack_size);
00298   }
00299 #endif
00300 
00301   mrb->atexit_stack[mrb->atexit_stack_len++] = f;
00302 }
00303