source: EcnlProtoTool/trunk/mrbgems/mruby-require/src/require.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 4.9 KB
Line 
1#if !(defined(_WIN32) || defined(_WIN64))
2#include <err.h>
3#endif
4#include <fcntl.h>
5#include <setjmp.h>
6#include <unistd.h>
7
8#include "mruby.h"
9#include "mruby/compile.h"
10#include "mruby/dump.h"
11#include "mruby/string.h"
12#include "mruby/proc.h"
13
14#include "opcode.h"
15#include "error.h"
16
17#include <stdlib.h>
18#include <sys/stat.h>
19
20#define E_LOAD_ERROR (mrb_class_get(mrb, "LoadError"))
21
22#if MRUBY_RELEASE_NO < 10000
23mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c);
24#define mrb_yield_with_class mrb_yield_internal
25#endif
26
27#if defined(_WIN32) || defined(_WIN64)
28 #include <windows.h>
29 int mkstemp(char *template)
30 {
31 DWORD pathSize;
32 char pathBuffer[1000];
33 char tempFilename[MAX_PATH];
34 UINT uniqueNum;
35 pathSize = GetTempPath(1000, pathBuffer);
36 if (pathSize < 1000) { pathBuffer[pathSize] = 0; }
37 else { pathBuffer[0] = 0; }
38 uniqueNum = GetTempFileName(pathBuffer, template, 0, tempFilename);
39 if (uniqueNum == 0) return -1;
40 strncpy(template, tempFilename, MAX_PATH);
41 return open(tempFilename, _O_RDWR|_O_BINARY);
42 }
43#endif
44
45static void
46replace_stop_with_return(mrb_state *mrb, mrb_irep *irep)
47{
48 if (irep->iseq[irep->ilen - 1] == MKOP_A(OP_STOP, 0)) {
49 irep->iseq = mrb_realloc(mrb, irep->iseq, (irep->ilen + 1) * sizeof(mrb_code));
50 irep->iseq[irep->ilen - 1] = MKOP_A(OP_LOADNIL, 0);
51 irep->iseq[irep->ilen] = MKOP_AB(OP_RETURN, 0, OP_R_NORMAL);
52 irep->ilen++;
53 }
54}
55
56static int
57compile_rb2mrb(mrb_state *mrb0, const char *code, int code_len, const char *path, FILE* tmpfp)
58{
59 mrb_state *mrb = mrb_open();
60 mrb_value result;
61 mrbc_context *c;
62 int ret = -1;
63 int debuginfo = 1;
64 mrb_irep *irep;
65
66 c = mrbc_context_new(mrb);
67 c->no_exec = 1;
68 if (path != NULL) {
69 mrbc_filename(mrb, c, path);
70 }
71
72 result = mrb_load_nstring_cxt(mrb, code, code_len, c);
73 if (mrb_undef_p(result)) {
74 mrbc_context_free(mrb, c);
75 mrb_close(mrb);
76 return MRB_DUMP_GENERAL_FAILURE;
77 }
78
79 irep = mrb_proc_ptr(result)->body.irep;
80 ret = mrb_dump_irep_binary(mrb, irep, debuginfo, tmpfp);
81
82 mrbc_context_free(mrb, c);
83 mrb_close(mrb);
84
85 return ret;
86}
87
88static void
89eval_load_irep(mrb_state *mrb, mrb_irep *irep)
90{
91 int ai;
92 struct RProc *proc;
93
94 replace_stop_with_return(mrb, irep);
95 proc = mrb_proc_new(mrb, irep);
96 proc->target_class = mrb->object_class;
97
98 ai = mrb_gc_arena_save(mrb);
99 mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class);
100 mrb_gc_arena_restore(mrb, ai);
101}
102
103static mrb_value
104mrb_require_load_rb_str(mrb_state *mrb, mrb_value self)
105{
106 char *path_ptr = NULL;
107#if defined(_WIN32) || defined(_WIN64)
108 char tmpname[MAX_PATH] = "tmp.XXXXXXXX";
109#else
110 char tmpname[] = "tmp.XXXXXXXX";
111#endif
112 mode_t mask;
113 FILE *tmpfp = NULL;
114 int fd = -1, ret;
115 mrb_irep *irep;
116 mrb_value code, path = mrb_nil_value();
117
118 mrb_get_args(mrb, "S|S", &code, &path);
119 if (!mrb_string_p(path)) {
120 path = mrb_str_new_cstr(mrb, "-");
121 }
122 path_ptr = mrb_str_to_cstr(mrb, path);
123
124 mask = umask(077);
125 fd = mkstemp(tmpname);
126 if (fd == -1) {
127 mrb_sys_fail(mrb, "can't create mkstemp() at mrb_require_load_rb_str");
128 }
129 umask(mask);
130
131 tmpfp = fdopen(fd, "r+");
132 if (tmpfp == NULL) {
133 close(fd);
134 mrb_sys_fail(mrb, "can't open temporay file at mrb_require_load_rb_str");
135 }
136
137 ret = compile_rb2mrb(mrb, RSTRING_PTR(code), RSTRING_LEN(code), path_ptr, tmpfp);
138 if (ret != MRB_DUMP_OK) {
139 fclose(tmpfp);
140 remove(tmpname);
141 mrb_raisef(mrb, E_LOAD_ERROR, "can't load file -- %S", path);
142 return mrb_nil_value();
143 }
144
145 rewind(tmpfp);
146 irep = mrb_read_irep_file(mrb, tmpfp);
147 fclose(tmpfp);
148 remove(tmpname);
149
150 if (irep) {
151 eval_load_irep(mrb, irep);
152 } else if (mrb->exc) {
153 // fail to load
154 longjmp(*(jmp_buf*)mrb->jmp, 1);
155 } else {
156 mrb_raisef(mrb, E_LOAD_ERROR, "can't load file -- %S", path);
157 return mrb_nil_value();
158 }
159
160 return mrb_true_value();
161}
162
163static mrb_value
164mrb_require_load_mrb_file(mrb_state *mrb, mrb_value self)
165{
166 char *path_ptr = NULL;
167 FILE *fp = NULL;
168 mrb_irep *irep;
169 mrb_value path;
170
171 mrb_get_args(mrb, "S", &path);
172 path_ptr = mrb_str_to_cstr(mrb, path);
173
174 fp = fopen(path_ptr, "rb");
175 if (fp == NULL) {
176 mrb_raisef(mrb, E_LOAD_ERROR, "can't open file -- %S", path);
177 }
178
179 irep = mrb_read_irep_file(mrb, fp);
180 fclose(fp);
181
182 if (irep) {
183 eval_load_irep(mrb, irep);
184 } else if (mrb->exc) {
185 // fail to load
186 longjmp(*(jmp_buf*)mrb->jmp, 1);
187 } else {
188 mrb_raisef(mrb, E_LOAD_ERROR, "can't load file -- %S", path);
189 return mrb_nil_value();
190 }
191
192 return mrb_true_value();
193}
194
195void
196mrb_mruby_require_gem_init(mrb_state *mrb)
197{
198 struct RClass *krn;
199 krn = mrb->kernel_module;
200
201 mrb_define_method(mrb, krn, "_load_rb_str", mrb_require_load_rb_str, MRB_ARGS_ANY());
202 mrb_define_method(mrb, krn, "_load_mrb_file", mrb_require_load_mrb_file, MRB_ARGS_REQ(1));
203}
204
205void
206mrb_mruby_require_gem_final(mrb_state *mrb)
207{
208}
Note: See TracBrowser for help on using the repository browser.