Embedding CRuby interpreter without internal headers has been difficult
for few years because: * NODE is no longer accessible. * rb_iseq_eval_main crashes without preparing with rb_thread_t. * some existing APIs calls exit(3) without giving the opportunity to finalize or handle errors to the client. * No general-purpose function to compile a source to an iseq are published in the public headers. This commit solves the problems. * include/ruby/ruby.h: Grouped APIs for embedding CRuby interpreter. (ruby_setup, ruby_compile_main_from_file, ruby_compile_main_from_string, ruby_eval_main, ruby_set_script_name): new APIs to embed CRuby. (ruby_opaque_t) Opaque pointer to an internal data, to NODE or iseq in particular. * eval.c (ruby_setup): Similar to ruby_init but returns an error code instead of exit(3) on error. (ruby_eval_main): Similar to ruby_exec_node but returns the evaluation result. (ruby_eval_main_internal): renamed from ruby_exec_internal. * ruby.c (toplevel_context): new helper function. (PREPARE_EVAL_MAIN): moved. (process_options): refactored with new functions. (parse_and_compile_main) new helper funciton. (ruby_compile_main_from_file, ruby_compile_main_from_string) new API (ruby_set_script_name): new API. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36079 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f8601bd903
commit
8c9a453f2d
23
ChangeLog
23
ChangeLog
@ -1,3 +1,26 @@
|
||||
Thu Jun 14 10:44:41 2012 Yuki Yugui Sonoda <yugui@google.com>
|
||||
|
||||
* include/ruby/ruby.h: Grouped APIs for embedding CRuby interpreter.
|
||||
(ruby_setup, ruby_compile_main_from_file,
|
||||
ruby_compile_main_from_string, ruby_eval_main,
|
||||
ruby_set_script_name): new APIs to embed CRuby.
|
||||
(ruby_opaque_t) Opaque pointer to an internal data, to NODE or iseq
|
||||
in particular.
|
||||
|
||||
* eval.c (ruby_setup): Similar to ruby_init but returns an error code
|
||||
instead of exit(3) on error.
|
||||
(ruby_eval_main): Similar to ruby_exec_node but returns the
|
||||
evaluation result.
|
||||
(ruby_eval_main_internal): renamed from ruby_exec_internal.
|
||||
|
||||
* ruby.c (toplevel_context): new helper function.
|
||||
(PREPARE_EVAL_MAIN): moved.
|
||||
(process_options): refactored with new functions.
|
||||
(parse_and_compile_main) new helper funciton.
|
||||
(ruby_compile_main_from_file, ruby_compile_main_from_string) new API
|
||||
(ruby_set_script_name): new API.
|
||||
|
||||
|
||||
Thu Jun 14 10:39:48 2012 Yuki Yugui Sonoda <yugui@google.com>
|
||||
|
||||
* eval.c: Add doxygen comments.
|
||||
|
93
eval.c
93
eval.c
@ -31,16 +31,18 @@ VALUE rb_eSysStackError;
|
||||
#include "eval_error.c"
|
||||
#include "eval_jump.c"
|
||||
|
||||
/* initialize ruby */
|
||||
|
||||
void
|
||||
ruby_init(void)
|
||||
/* Initializes the Ruby VM and builtin libraries.
|
||||
* @retval 0 if succeeded.
|
||||
* @retval non-zero an error occured.
|
||||
*/
|
||||
int
|
||||
ruby_setup(void)
|
||||
{
|
||||
static int initialized = 0;
|
||||
int state;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
return 0;
|
||||
initialized = 1;
|
||||
|
||||
ruby_init_stack((void *)&state);
|
||||
@ -54,11 +56,22 @@ ruby_init(void)
|
||||
}
|
||||
POP_TAG();
|
||||
|
||||
if (!state) GET_VM()->running = 1;
|
||||
return state;
|
||||
}
|
||||
|
||||
/* Calls ruby_setup() and check error.
|
||||
*
|
||||
* Prints errors and calls exit(3) if an error occured.
|
||||
*/
|
||||
void
|
||||
ruby_init(void)
|
||||
{
|
||||
int state = ruby_setup();
|
||||
if (state) {
|
||||
error_print();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
GET_VM()->running = 1;
|
||||
}
|
||||
|
||||
/*! Processes command line arguments and compiles the Ruby source to execute.
|
||||
@ -71,7 +84,7 @@ ruby_init(void)
|
||||
* @return an opaque pointer to the compiled source or an internal special value.
|
||||
* @sa ruby_executable_node().
|
||||
*/
|
||||
void *
|
||||
ruby_opaque_t
|
||||
ruby_options(int argc, char **argv)
|
||||
{
|
||||
int state;
|
||||
@ -217,26 +230,6 @@ ruby_cleanup(volatile int ex)
|
||||
return ex;
|
||||
}
|
||||
|
||||
static int
|
||||
ruby_exec_internal(void *n)
|
||||
{
|
||||
volatile int state;
|
||||
VALUE iseq = (VALUE)n;
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
|
||||
if (!n) return 0;
|
||||
|
||||
PUSH_TAG();
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
SAVE_ROOT_JMPBUF(th, {
|
||||
th->base_block = 0;
|
||||
rb_iseq_eval_main(iseq);
|
||||
});
|
||||
}
|
||||
POP_TAG();
|
||||
return state;
|
||||
}
|
||||
|
||||
/*! Calls ruby_cleanup() and exits the process */
|
||||
void
|
||||
ruby_stop(int ex)
|
||||
@ -257,7 +250,7 @@ ruby_stop(int ex)
|
||||
* @retval 0 if the given value is such a special value.
|
||||
*/
|
||||
int
|
||||
ruby_executable_node(void *n, int *status)
|
||||
ruby_executable_node(ruby_opaque_t n, int *status)
|
||||
{
|
||||
VALUE v = (VALUE)n;
|
||||
int s;
|
||||
@ -273,12 +266,33 @@ ruby_executable_node(void *n, int *status)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
ruby_eval_main_internal(VALUE iseqval, VALUE* result)
|
||||
{
|
||||
volatile int state;
|
||||
volatile VALUE retval;
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
|
||||
if (!iseqval) return 0;
|
||||
|
||||
PUSH_TAG();
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
SAVE_ROOT_JMPBUF(th, {
|
||||
th->base_block = 0;
|
||||
retval = rb_iseq_eval_main(iseqval);
|
||||
});
|
||||
}
|
||||
POP_TAG();
|
||||
*result = state ? th->errinfo : retval;
|
||||
return state;
|
||||
}
|
||||
|
||||
/*! Runs the given compiled source and exits this process.
|
||||
* @retval 0 if successfully run thhe source
|
||||
* @retval non-zero if an error occurred.
|
||||
*/
|
||||
int
|
||||
ruby_run_node(void *n)
|
||||
ruby_run_node(ruby_opaque_t n)
|
||||
{
|
||||
int status;
|
||||
if (!ruby_executable_node(n, &status)) {
|
||||
@ -290,10 +304,27 @@ ruby_run_node(void *n)
|
||||
|
||||
/*! Runs the given compiled source */
|
||||
int
|
||||
ruby_exec_node(void *n)
|
||||
ruby_exec_node(ruby_opaque_t n)
|
||||
{
|
||||
VALUE dummy;
|
||||
ruby_init_stack((void *)&n);
|
||||
return ruby_exec_internal(n);
|
||||
return ruby_eval_main_internal((VALUE)n, &dummy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Evaluates the given iseq in the main (toplevel) context.
|
||||
*
|
||||
* @param iseqval a VALUE that wraps an iseq.
|
||||
* @param result Stores the evaluated value if succeeded,
|
||||
* or an exception if failed.
|
||||
* @retval 0 if succeeded
|
||||
* @retval non-zero if failed.
|
||||
*/
|
||||
int
|
||||
ruby_eval_main(ruby_opaque_t n, VALUE *result)
|
||||
{
|
||||
return !!ruby_eval_main_internal((VALUE)n, result);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -386,9 +386,6 @@ VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
|
||||
void rb_set_end_proc(void (*)(VALUE), VALUE);
|
||||
void rb_mark_end_proc(void);
|
||||
void rb_exec_end_proc(void);
|
||||
void ruby_finalize(void);
|
||||
NORETURN(void ruby_stop(int));
|
||||
int ruby_cleanup(volatile int);
|
||||
DEPRECATED(void rb_gc_mark_threads(void));
|
||||
void rb_thread_schedule(void);
|
||||
void rb_thread_wait_fd(int);
|
||||
@ -432,10 +429,7 @@ VALUE rb_file_directory_p(VALUE,VALUE);
|
||||
VALUE rb_str_encode_ospath(VALUE);
|
||||
int rb_is_absolute_path(const char *);
|
||||
/* gc.c */
|
||||
void ruby_set_stack_size(size_t);
|
||||
NORETURN(void rb_memerror(void));
|
||||
int ruby_stack_check(void);
|
||||
size_t ruby_stack_length(VALUE**);
|
||||
int rb_during_gc(void);
|
||||
void rb_gc_mark_locations(VALUE*, VALUE*);
|
||||
void rb_mark_tbl(struct st_table*);
|
||||
@ -451,7 +445,6 @@ void rb_gc_call_finalizer_at_exit(void);
|
||||
VALUE rb_gc_enable(void);
|
||||
VALUE rb_gc_disable(void);
|
||||
VALUE rb_gc_start(void);
|
||||
#define Init_stack(addr) ruby_init_stack(addr)
|
||||
void rb_gc_set_params(void);
|
||||
/* hash.c */
|
||||
void st_foreach_safe(struct st_table *, int (*)(ANYARGS), st_data_t);
|
||||
@ -662,12 +655,6 @@ int rb_reg_options(VALUE);
|
||||
RUBY_EXTERN VALUE rb_argv0;
|
||||
VALUE rb_get_argv(void);
|
||||
void *rb_load_file(const char*);
|
||||
void ruby_script(const char*);
|
||||
void ruby_prog_init(void);
|
||||
void ruby_set_argv(int, char**);
|
||||
void *ruby_process_options(int, char**);
|
||||
void ruby_init_loadpath(void);
|
||||
void ruby_incpush(const char*);
|
||||
/* signal.c */
|
||||
VALUE rb_f_kill(int, VALUE*);
|
||||
void rb_gc_mark_trap_list(void);
|
||||
@ -675,7 +662,6 @@ void rb_gc_mark_trap_list(void);
|
||||
#define posix_signal ruby_posix_signal
|
||||
RETSIGTYPE (*posix_signal(int, RETSIGTYPE (*)(int)))(int);
|
||||
#endif
|
||||
void ruby_sig_finalize(void);
|
||||
void rb_trap_exit(void);
|
||||
void rb_trap_exec(void);
|
||||
const char *ruby_signal_name(int);
|
||||
@ -929,9 +915,6 @@ VALUE rb_cv_get(VALUE, const char*);
|
||||
void rb_define_class_variable(VALUE, const char*, VALUE);
|
||||
VALUE rb_mod_class_variables(VALUE);
|
||||
VALUE rb_mod_remove_cvar(VALUE, VALUE);
|
||||
/* version.c */
|
||||
void ruby_show_version(void);
|
||||
void ruby_show_copyright(void);
|
||||
|
||||
ID rb_frame_callee(void);
|
||||
VALUE rb_str_succ(VALUE);
|
||||
|
@ -1229,21 +1229,6 @@ NORETURN(void rb_throw_obj(VALUE,VALUE));
|
||||
|
||||
VALUE rb_require(const char*);
|
||||
|
||||
#ifdef __ia64
|
||||
void ruby_init_stack(volatile VALUE*, void*);
|
||||
#define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp())
|
||||
#else
|
||||
void ruby_init_stack(volatile VALUE*);
|
||||
#endif
|
||||
#define RUBY_INIT_STACK \
|
||||
VALUE variable_in_this_stack_frame; \
|
||||
ruby_init_stack(&variable_in_this_stack_frame);
|
||||
void ruby_init(void);
|
||||
void *ruby_options(int, char**);
|
||||
int ruby_run_node(void *);
|
||||
int ruby_exec_node(void *);
|
||||
int ruby_executable_node(void *n, int *status);
|
||||
|
||||
RUBY_EXTERN VALUE rb_mKernel;
|
||||
RUBY_EXTERN VALUE rb_mComparable;
|
||||
RUBY_EXTERN VALUE rb_mEnumerable;
|
||||
@ -1400,14 +1385,6 @@ rb_special_const_p(VALUE obj)
|
||||
static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) || defined(__NeXT__)) && defined(__MACH__)
|
||||
#define RUBY_GLOBAL_SETUP /* use linker option to link startup code with ObjC support */
|
||||
#else
|
||||
#define RUBY_GLOBAL_SETUP
|
||||
#endif
|
||||
|
||||
void ruby_sysinit(int *, char ***);
|
||||
|
||||
#define RUBY_VM 1 /* YARV */
|
||||
#define HAVE_NATIVETHREAD
|
||||
int ruby_native_thread_p(void);
|
||||
@ -1495,6 +1472,89 @@ int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
|
||||
#include "ruby/subst.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup embed CRuby Embedding APIs
|
||||
* CRuby interpreter APIs. These are APIs to embed MRI interpreter into your
|
||||
* program.
|
||||
* These functions are not a part of Ruby extention library API.
|
||||
* Extension libraries of Ruby should not depend on these functions.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! Opaque pointer to an inner data structure.
|
||||
*
|
||||
* You do not have to know what the actual data type this pointer points.
|
||||
* It often changes for internal improvements.
|
||||
*/
|
||||
typedef void *ruby_opaque_t;
|
||||
|
||||
/*! @deprecated You no longer need to use this macro. */
|
||||
#if (defined(__APPLE__) || defined(__NeXT__)) && defined(__MACH__)
|
||||
#define RUBY_GLOBAL_SETUP /* use linker option to link startup code with ObjC support */
|
||||
#else
|
||||
#define RUBY_GLOBAL_SETUP
|
||||
#endif
|
||||
|
||||
/** @defgroup ruby1 ruby(1) implementation
|
||||
* A part of the implementation of ruby(1) command.
|
||||
* Other programs that embed Ruby interpreter do not always need to use these
|
||||
* functions.
|
||||
* @{
|
||||
*/
|
||||
|
||||
void ruby_sysinit(int *argc, char ***argv);
|
||||
void ruby_init(void);
|
||||
ruby_opaque_t ruby_options(int argc, char** argv);
|
||||
int ruby_executable_node(ruby_opaque_t n, int *status);
|
||||
int ruby_run_node(ruby_opaque_t n);
|
||||
|
||||
/* version.c */
|
||||
void ruby_show_version(void);
|
||||
void ruby_show_copyright(void);
|
||||
|
||||
|
||||
/*! A convenience macro to call ruby_init_stack(). Must be placed just after
|
||||
* variable declarations */
|
||||
#define RUBY_INIT_STACK \
|
||||
VALUE variable_in_this_stack_frame; \
|
||||
ruby_init_stack(&variable_in_this_stack_frame);
|
||||
/*! @} */
|
||||
|
||||
#ifdef __ia64
|
||||
void ruby_init_stack(volatile VALUE*, void*);
|
||||
#define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp())
|
||||
#else
|
||||
void ruby_init_stack(volatile VALUE*);
|
||||
#endif
|
||||
#define Init_stack(addr) ruby_init_stack(addr)
|
||||
|
||||
int ruby_setup(void);
|
||||
int ruby_cleanup(volatile int);
|
||||
|
||||
void ruby_finalize(void);
|
||||
NORETURN(void ruby_stop(int));
|
||||
|
||||
void ruby_set_stack_size(size_t);
|
||||
int ruby_stack_check(void);
|
||||
size_t ruby_stack_length(VALUE**);
|
||||
|
||||
ruby_opaque_t ruby_compile_main_from_file(VALUE fname, const char* path, VALUE* error);
|
||||
ruby_opaque_t ruby_compile_main_from_string(VALUE fname, VALUE string, VALUE* error);
|
||||
int ruby_exec_node(ruby_opaque_t n);
|
||||
int ruby_eval_main(ruby_opaque_t n, VALUE *result);
|
||||
|
||||
void ruby_script(const char* name);
|
||||
void ruby_set_script_name(VALUE name);
|
||||
|
||||
void ruby_prog_init(void);
|
||||
void ruby_set_argv(int, char**);
|
||||
void *ruby_process_options(int, char**);
|
||||
void ruby_init_loadpath(void);
|
||||
void ruby_incpush(const char*);
|
||||
void ruby_sig_finalize(void);
|
||||
|
||||
/*! @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#if 0
|
||||
{ /* satisfy cc-mode */
|
||||
|
164
ruby.c
164
ruby.c
@ -496,6 +496,26 @@ require_libraries(VALUE *req_list)
|
||||
th->base_block = prev_base_block;
|
||||
}
|
||||
|
||||
static rb_env_t*
|
||||
toplevel_context(void)
|
||||
{
|
||||
rb_env_t *env;
|
||||
VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
|
||||
rb_binding_t *bind;
|
||||
|
||||
GetBindingPtr(toplevel_binding, bind);
|
||||
GetEnvPtr(bind->env, env);
|
||||
return env;
|
||||
}
|
||||
|
||||
#define PREPARE_PARSE_MAIN(th, env, expr) do { \
|
||||
(th)->parse_in_eval--; \
|
||||
(th)->base_block = &(env)->block; \
|
||||
expr; \
|
||||
(th)->parse_in_eval++; \
|
||||
(th)->base_block = 0; \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
process_sflag(int *sflag)
|
||||
{
|
||||
@ -1365,22 +1385,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
|
||||
ruby_set_argv(argc, argv);
|
||||
process_sflag(&opt->sflag);
|
||||
|
||||
{
|
||||
/* set eval context */
|
||||
VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
|
||||
rb_binding_t *bind;
|
||||
|
||||
GetBindingPtr(toplevel_binding, bind);
|
||||
GetEnvPtr(bind->env, env);
|
||||
}
|
||||
|
||||
#define PREPARE_PARSE_MAIN(expr) do { \
|
||||
th->parse_in_eval--; \
|
||||
th->base_block = &env->block; \
|
||||
expr; \
|
||||
th->parse_in_eval++; \
|
||||
th->base_block = 0; \
|
||||
} while (0)
|
||||
env = toplevel_context();
|
||||
|
||||
if (opt->e_script) {
|
||||
VALUE progname = rb_progname;
|
||||
@ -1392,11 +1397,11 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
|
||||
eenc = lenc;
|
||||
}
|
||||
rb_enc_associate(opt->e_script, eenc);
|
||||
rb_vm_set_progname(rb_progname = opt->script_name);
|
||||
ruby_set_script_name(opt->script_name);
|
||||
require_libraries(&opt->req_list);
|
||||
rb_vm_set_progname(rb_progname = progname);
|
||||
ruby_set_script_name(progname);
|
||||
|
||||
PREPARE_PARSE_MAIN({
|
||||
PREPARE_PARSE_MAIN(th, env, {
|
||||
tree = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
|
||||
});
|
||||
}
|
||||
@ -1405,12 +1410,11 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
|
||||
forbid_setid("program input from stdin");
|
||||
}
|
||||
|
||||
PREPARE_PARSE_MAIN({
|
||||
PREPARE_PARSE_MAIN(th, env, {
|
||||
tree = load_file(parser, opt->script_name, 1, opt);
|
||||
});
|
||||
}
|
||||
rb_progname = opt->script_name;
|
||||
rb_vm_set_progname(rb_progname);
|
||||
ruby_set_script_name(opt->script_name);
|
||||
if (opt->dump & DUMP_BIT(yydebug)) return Qtrue;
|
||||
|
||||
if (opt->ext.enc.index >= 0) {
|
||||
@ -1446,12 +1450,12 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
|
||||
}
|
||||
|
||||
if (opt->do_print) {
|
||||
PREPARE_PARSE_MAIN({
|
||||
PREPARE_PARSE_MAIN(th, env, {
|
||||
tree = rb_parser_append_print(parser, tree);
|
||||
});
|
||||
}
|
||||
if (opt->do_loop) {
|
||||
PREPARE_PARSE_MAIN({
|
||||
PREPARE_PARSE_MAIN(th, env, {
|
||||
tree = rb_parser_while_loop(parser, tree, opt->do_line, opt->do_split);
|
||||
});
|
||||
rb_define_global_function("sub", rb_f_sub, -1);
|
||||
@ -1466,7 +1470,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
PREPARE_PARSE_MAIN({
|
||||
PREPARE_PARSE_MAIN(th, env, {
|
||||
VALUE path = Qnil;
|
||||
if (!opt->e_script && strcmp(opt->script, "-"))
|
||||
path = rb_realpath_internal(Qnil, opt->script_name, 1);
|
||||
@ -1622,7 +1626,7 @@ load_file_internal(VALUE arg)
|
||||
if (f != rb_stdin) rb_io_close(f);
|
||||
f = Qnil;
|
||||
}
|
||||
rb_vm_set_progname(rb_progname = opt->script_name);
|
||||
ruby_set_script_name(opt->script_name);
|
||||
require_libraries(&opt->req_list); /* Why here? unnatural */
|
||||
}
|
||||
if (opt->src.enc.index >= 0) {
|
||||
@ -1689,6 +1693,103 @@ rb_load_file(const char *fname)
|
||||
return load_file(rb_parser_new(), fname_v, 0, cmdline_options_init(&opt));
|
||||
}
|
||||
|
||||
struct ruby_compile_main_arg {
|
||||
int is_string;
|
||||
union {
|
||||
VALUE path;
|
||||
VALUE string;
|
||||
} source;
|
||||
};
|
||||
|
||||
static ruby_opaque_t
|
||||
parse_and_compile_main(VALUE fname, const struct ruby_compile_main_arg* arg, VALUE* error)
|
||||
{
|
||||
rb_env_t *const env = toplevel_context();
|
||||
rb_thread_t *const th = GET_THREAD();
|
||||
NODE* tree;
|
||||
VALUE iseq;
|
||||
VALUE path;
|
||||
int state;
|
||||
|
||||
PUSH_TAG();
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
PREPARE_PARSE_MAIN(th, env, {
|
||||
VALUE parser = rb_parser_new();
|
||||
th->mild_compile_error++;
|
||||
if (arg->is_string) {
|
||||
FilePathValue(fname);
|
||||
path = fname;
|
||||
tree = rb_parser_compile_string(parser, RSTRING_PTR(fname), arg->source.string, 1);
|
||||
}
|
||||
else {
|
||||
struct cmdline_options opt;
|
||||
path = arg->source.path;
|
||||
tree = load_file(parser, path, 0, cmdline_options_init(&opt));
|
||||
}
|
||||
th->mild_compile_error--;
|
||||
});
|
||||
if (!tree) rb_exc_raise(th->errinfo);
|
||||
|
||||
ruby_set_script_name(fname);
|
||||
|
||||
PREPARE_PARSE_MAIN(th, env, {
|
||||
iseq = rb_iseq_new_main(tree, fname, path);
|
||||
});
|
||||
}
|
||||
POP_TAG();
|
||||
if (state) {
|
||||
*error = th->errinfo;
|
||||
return NULL;
|
||||
} else {
|
||||
*error = Qnil;
|
||||
return iseq;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a main Ruby script file into the internal a data structure.
|
||||
*
|
||||
* This function:
|
||||
* @li loads the file specified by path.
|
||||
* @li parses the source and compiles it
|
||||
*
|
||||
* @param fname <code>$0</code> is set to this value.
|
||||
* If nil,
|
||||
* uses the given path instead.
|
||||
* @param path path to the source
|
||||
* @param error where to store the exception if an error occured.
|
||||
* @return The compiled source code. Or NULL if an error occured.
|
||||
*/
|
||||
ruby_opaque_t
|
||||
ruby_compile_main_from_file(VALUE fname, const char* path, VALUE* error)
|
||||
{
|
||||
struct ruby_compile_main_arg arg;
|
||||
arg.is_string = FALSE;
|
||||
arg.source.path = rb_str_new_cstr(path);
|
||||
|
||||
if (NIL_P(fname)) fname = arg.source.path;
|
||||
return parse_and_compile_main(fname, &arg, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a main Ruby script in a string into the internal a data structure.
|
||||
*
|
||||
* This function parses the given source and compiles it
|
||||
*
|
||||
* @param fname <code>$0</code> is set to this value.
|
||||
* @param source Ruby source string
|
||||
* @param error where to store the exception if an error occured.
|
||||
* @return The compiled source code. Or NULL if an error occured.
|
||||
*/
|
||||
ruby_opaque_t
|
||||
ruby_compile_main_from_string(VALUE fname, VALUE source, VALUE* error)
|
||||
{
|
||||
struct ruby_compile_main_arg arg;
|
||||
arg.is_string = TRUE;
|
||||
arg.source.string = source;
|
||||
return parse_and_compile_main(fname, &arg, error);
|
||||
}
|
||||
|
||||
static void
|
||||
set_arg0(VALUE val, ID id)
|
||||
{
|
||||
@ -1720,6 +1821,17 @@ ruby_script(const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
/*! Sets the current script name to this value.
|
||||
*
|
||||
* Same as ruby_script() but accepts a VALUE.
|
||||
*/
|
||||
void
|
||||
ruby_set_script_name(VALUE name)
|
||||
{
|
||||
rb_progname = rb_str_dup(name);
|
||||
rb_vm_set_progname(rb_progname);
|
||||
}
|
||||
|
||||
static void
|
||||
init_ids(struct cmdline_options *opt)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user