diff options
author | Alessio Treglia <alessio@debian.org> | 2011-03-24 09:13:51 +0100 |
---|---|---|
committer | Alessio Treglia <alessio@debian.org> | 2011-03-24 09:13:51 +0100 |
commit | e5328e59987b90c4e98959510b810510e384650d (patch) | |
tree | 0f140b79d942c4654701d8fb4cfe2f1dd904f9f0 /xen.c | |
parent | 36cf8384e5699cda3f1ca607753fe4d4a8515b01 (diff) |
Imported Upstream version 12.0
Diffstat (limited to 'xen.c')
-rw-r--r-- | xen.c | 447 |
1 files changed, 135 insertions, 312 deletions
@@ -162,9 +162,7 @@ int xen_to_c_int_or_else(XEN obj, int fallback) void xen_gc_mark(XEN val) { -#if HAVE_REASONABLE_RB_GC_MARK rb_gc_mark(val); -#endif } @@ -567,14 +565,6 @@ static XEN xen_rb_rescue(XEN val) } -#if (!HAVE_RB_ERRINFO) -XEN rb_errinfo(void) -{ - return ruby_errinfo; -} -#endif - - void xen_repl(int argc, char **argv) { while (true) @@ -585,7 +575,7 @@ void xen_repl(int argc, char **argv) &status); if (status != 0) { - fprintf(stderr, "%s\n", XEN_AS_STRING(rb_errinfo())); + fprintf(stderr, "%s\n", XEN_AS_STRING(rb_gv_get("$!"))); status = 0; } } @@ -598,7 +588,7 @@ XEN xen_rb_eval_string_with_error(const char *str) XEN res; res = rb_eval_string_protect(str, &status); if (status != 0) - return(XEN_TO_STRING(rb_errinfo())); + return(XEN_TO_STRING(rb_gv_get("$!"))); return(res); } @@ -608,27 +598,20 @@ XEN xen_rb_load_file_with_error(XEN file) int status = 0; rb_load_protect(file, 0, &status); if (status != 0) - return(XEN_TO_STRING(rb_errinfo())); + return(XEN_TO_STRING(rb_gv_get("$!"))); return(XEN_TRUE); } -XEN xen_rb_add_to_load_path(char *path) -{ -#if (!HAVE_RB_GET_LOAD_PATH) - extern VALUE rb_load_path; - XEN rpath; - rpath = rb_str_new2(path); - if (XEN_FALSE_P(rb_ary_includes(rb_load_path, rpath))) - rb_ary_unshift(rb_load_path, rpath); -#else - XEN rpath; - rpath = rb_str_new2(path); - if (XEN_FALSE_P(rb_ary_includes(rb_get_load_path(), rpath))) - rb_ary_unshift(rb_get_load_path(), rpath); -#endif - return(XEN_FALSE); -} +XEN xen_rb_add_to_load_path(char *path) +{ + XEN rpath, load_path; + rpath = rb_str_new2(path); + load_path = rb_gv_get("$:"); + if (XEN_FALSE_P(rb_ary_includes(load_path, rpath))) + rb_ary_unshift(load_path, rpath); + return(XEN_FALSE); +} static char *lstbuf = NULL; @@ -680,11 +663,24 @@ XEN xen_rb_obj_as_string(XEN obj) } +#if HAVE_RB_PROC_NEW + +static XEN xen_rb_apply_1(XEN args) +{ + return(rb_apply(XEN_CAR(args), rb_intern("call"), XEN_CADR(args))); +} + +#else + static XEN xen_rb_apply_1(XEN args) { - return(rb_apply(XEN_CAR(args), rb_intern("call"), XEN_CADR(args))); + if (XEN_PROCEDURE_P(XEN_CAR(args))) + return(rb_apply(XEN_CAR(args), rb_intern("call"), XEN_CADR(args))); + return(rb_apply(rb_mKernel, XEN_CAR(args), XEN_CADR(args))); } +#endif + XEN xen_rb_apply(XEN func, XEN args) { @@ -694,7 +690,7 @@ XEN xen_rb_apply(XEN func, XEN args) XEN_LIST_2(func, args), &status); if (status != 0) - return(XEN_TO_STRING(rb_errinfo())); + return(XEN_TO_STRING(rb_gv_get("$!"))); return(val); } @@ -713,7 +709,7 @@ XEN xen_rb_funcall_0(XEN func) func, &status); if (status != 0) - return(XEN_TO_STRING(rb_errinfo())); + return(XEN_TO_STRING(rb_gv_get("$!"))); return(val); } @@ -722,22 +718,7 @@ XEN xen_rb_copy_list(XEN val) { if ((val == XEN_EMPTY_LIST) || (!XEN_CONS_P(val))) return XEN_EMPTY_LIST; - -#if (!HAVE_RB_ARY_DUP) - { - /* if this is considered bad form, we could fall back on flatten (rb_ary_dup?) */ - long len, i; - VALUE collect; - len = RB_ARRAY_LEN(val); - collect = rb_ary_new2(len); - for (i = 0; i < len; i++) - RB_ARRAY_PTR(collect)[i] = RB_ARRAY_PTR(val)[i]; - RB_ARRAY_LEN(collect) = len; - return(collect); - } -#else return rb_ary_dup(val); -#endif } @@ -885,6 +866,59 @@ static XEN xen_rb_hook_add_hook(int argc, XEN *argv, XEN hook) } +#if HAVE_RB_PROC_NEW + +static XEN xen_proc_call(XEN args, XEN id) +{ + return(rb_apply(rb_mKernel, (ID)id, XEN_CONS_P(args) ? args : XEN_LIST_1(args))); +} + +#if 0 + VALUE rb_proc_new((VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE)); +#endif + +static XEN xen_rb_proc_new(const char *name, XEN (*func)(), int arity, const char* doc) +{ + rb_define_module_function(rb_mKernel, name, XEN_PROCEDURE_CAST func, arity); + if (doc) C_SET_OBJECT_HELP(name, doc); + return(rb_proc_new(XEN_PROCEDURE_CAST xen_proc_call, rb_intern(name))); +} + + +static XEN xen_rb_hook_arity(XEN hook); + +XEN xen_rb_add_hook(XEN hook, VALUE (*func)(), const char *name, const char* doc) +{ + /* called from C, not Ruby, to add a function to a Ruby-side hook */ + char *temp; + temp = xen_scheme_procedure_to_ruby(name); + rb_ary_push(rb_iv_get(hook, "@procs"), rb_ary_new3(2, C_TO_XEN_STRING(temp), xen_rb_proc_new(temp, func, XEN_TO_C_INT(xen_rb_hook_arity(hook)), doc))); + if (temp) free(temp); + return(hook); +} + +#else + +XEN xen_rb_add_hook(XEN hook, VALUE (*func)(), const char *name, const char* doc) +{ + /* called from C, not Ruby, to add a function to a Ruby-side hook + * this doesn't work in g++ because it thinks the funcs are invalid: + * "error: invalid conversion from 'VALUE (*)(VALUE, VALUE)' to 'VALUE (*)(...)'" (snd-file.c etc) + */ + XEN var; + char *temp; + temp = xen_scheme_procedure_to_ruby(name); + rb_define_module_function(rb_mKernel, temp, XEN_PROCEDURE_CAST func, XEN_TO_C_INT_OR_ELSE(rb_iv_get(hook, "@arity"), 0)); + if (doc) C_SET_OBJECT_HELP(temp, doc); + var = rb_intern(temp); + rb_ary_push(rb_iv_get(hook, "@procs"), rb_ary_new3(2, C_TO_XEN_STRING(temp), var)); + if (temp) free(temp); + return(hook); +} + +#endif + + static XEN xen_rb_hook_remove_hook(XEN hook, XEN name) { XEN ary; @@ -1030,6 +1064,20 @@ XEN xen_rb_create_hook(char *name, int arity, char *help) return(var); } +static int simple_hook_number = 0; + + +XEN xen_rb_create_simple_hook(int arity) +{ + char *name; + XEN hook; + name = (char *)calloc(20, sizeof(char)); + snprintf(name, 20, "simple_%02d_hook", simple_hook_number++); + hook = xen_rb_create_hook(name, arity, NULL); + free(name); + return(hook); +} + /* * make_hook(name, arity = 0, help = "", hook_name = nil, &func) @@ -1179,24 +1227,16 @@ XEN rb_properties(void) static XEN g_gc_off(void) { -#if HAVE_RB_GC_DISABLE #define H_gc_off "(" S_gc_off ") turns off garbage collection" rb_gc_disable(); -#else - #define H_gc_off "(" S_gc_off ") is a no-op" -#endif return(XEN_FALSE); } static XEN g_gc_on(void) { -#if HAVE_RB_GC_DISABLE #define H_gc_on "(" S_gc_on ") turns on garbage collection" rb_gc_enable(); -#else - #define H_gc_on "(" S_gc_on ") is a no-op" -#endif return(XEN_FALSE); } @@ -1498,11 +1538,20 @@ void xen_s7_ignore(s7_function func) /* squelch compiler warnings */ XEN xen_define_variable(const char *name, XEN value) { XEN_DEFINE(name, value); - s7_gc_protect(s7, value); + /* s7_gc_protect(s7, value); */ + /* XEN_DEFINE places value in the global env, so it is already gc protected */ return(C_STRING_TO_XEN_SYMBOL(name)); } +XEN xen_s7_define_hook(const char *name, XEN value) +{ + s7_define_constant(s7, name, value); + /* s7_gc_protect(s7, value); -- see above */ + return(value); +} + + void xen_gc_mark(XEN val) { s7_mark_object(val); @@ -1595,241 +1644,6 @@ XEN xen_assoc(s7_scheme *sc, XEN key, XEN alist) } -/* hooks */ - -typedef struct { - int arity; - XEN functions; - const char *documentation; -} ghook; - -static XEN_OBJECT_TYPE ghook_tag; - -#define XEN_TO_GHOOK(Obj) (ghook *)XEN_OBJECT_REF(Obj) - -static int ghook_arity(ghook *hook) {return(hook->arity);} - -static XEN ghook_functions(ghook *hook) {return(hook->functions);} - -static void reset_ghook(ghook *hook) {hook->functions = XEN_EMPTY_LIST;} - - -static ghook *make_ghook(int arity) -{ - ghook *hook; - hook = (ghook *)calloc(1, sizeof(ghook)); - hook->arity = arity; - hook->functions = XEN_EMPTY_LIST; - hook->documentation = NULL; - return(hook); -} - - -static void free_ghook(ghook *hook) -{ - if (hook) - { - hook->functions = XEN_FALSE; - free(hook); - } -} - - -static char *hook_to_string(ghook *hook) -{ - if (hook) - { - int len; - char *functions = NULL, *str; - functions = XEN_AS_STRING(hook->functions); - len = 64 + strlen(functions); - str = (char *)calloc(len, sizeof(char)); - snprintf(str, len, "<hook arity: %d, hooks: %s>", hook->arity, functions); - if (functions) free(functions); - return(str); - } - return(NULL); -} - - -static void add_ghook(ghook *hook, XEN function, bool at_end) -{ - if (at_end) - hook->functions = XEN_APPEND(hook->functions, XEN_LIST_1(function)); - else hook->functions = XEN_CONS(function, hook->functions); -} - - -bool xen_hook_p(XEN obj) -{ - return(XEN_OBJECT_TYPE_P(obj, ghook_tag)); -} - - -static XEN g_hook_p(XEN val) -{ - return(C_TO_XEN_BOOLEAN(xen_hook_p(val))); -} - - -static XEN g_hook_empty_p(XEN hook) -{ - XEN_ASSERT_TYPE(xen_hook_p(hook), hook, XEN_ONLY_ARG, "hook-empty?", "a hook"); - return(C_TO_XEN_BOOLEAN(XEN_NULL_P(ghook_functions(XEN_TO_GHOOK(hook))))); -} - - -bool xen_hook_empty_p(XEN hook) -{ - return(XEN_NULL_P(ghook_functions(XEN_TO_GHOOK(hook)))); -} - - -XEN xen_hook_to_list(XEN hook) -{ - XEN_ASSERT_TYPE(xen_hook_p(hook), hook, XEN_ONLY_ARG, "hook->list", "a hook"); - return(ghook_functions(XEN_TO_GHOOK(hook))); -} - - -const char *xen_s7_hook_documentation(XEN hook) -{ - ghook *obj; - obj = XEN_TO_GHOOK(hook); - return(obj->documentation); -} - - -static XEN g_make_hook(XEN arity, XEN help) -{ - ghook *hook; - XEN_ASSERT_TYPE(XEN_INTEGER_P(arity), arity, XEN_ARG_1, "make-hook", "an integer"); - XEN_ASSERT_TYPE(XEN_STRING_P(help) || XEN_NOT_BOUND_P(help), help, XEN_ARG_2, "make-hook", "a string if bound"); - hook = make_ghook(XEN_TO_C_INT(arity)); - if (XEN_STRING_P(help)) hook->documentation = xen_strdup(XEN_TO_C_STRING(help)); - XEN_MAKE_AND_RETURN_OBJECT(ghook_tag, hook, 0, 0); -} - - -static XEN g_add_hook(XEN hook, XEN function, XEN position) -{ - ghook *obj; - XEN arity; - bool at_end = false, arity_ok; - int gc_loc; - - obj = XEN_TO_GHOOK(hook); - XEN_ASSERT_TYPE(xen_hook_p(hook), hook, XEN_ARG_1, "add-hook!", "a hook"); - XEN_ASSERT_TYPE(XEN_PROCEDURE_P(function), function, XEN_ARG_2, "add-hook!", "a function"); - XEN_ASSERT_TYPE(XEN_BOOLEAN_IF_BOUND_P(position), position, XEN_ARG_3, "add-hook!", "boolean"); - - arity = XEN_ARITY(function); - gc_loc = s7_gc_protect(s7, arity); - arity_ok = ((XEN_TO_C_INT(XEN_CAR(arity)) == ghook_arity(obj)) || - (XEN_TO_C_INT(XEN_CAR(arity)) + XEN_TO_C_INT(XEN_CADR(arity)) >= ghook_arity(obj)) || - (XEN_TRUE_P(XEN_CADDR(arity)))); - s7_gc_unprotect_at(s7, gc_loc); - XEN_ASSERT_TYPE(arity_ok, function, XEN_ARG_2, "add-hook!", "a function whose arity matches the hook's"); - - if (XEN_BOOLEAN_P(position)) at_end = XEN_TO_C_BOOLEAN(position); - add_ghook(obj, function, at_end); - return(hook); -} - - -XEN xen_s7_reset_hook(XEN hook) -{ - XEN_ASSERT_TYPE(xen_hook_p(hook), hook, XEN_ONLY_ARG, "reset-hook!", "a hook"); - reset_ghook(XEN_TO_GHOOK(hook)); - return(hook); -} - - -static XEN g_run_hook(XEN all_args) -{ - XEN hook, args; - ghook *obj; - int arglen; - XEN functions, val = XEN_FALSE; - - hook = XEN_CAR(all_args); - XEN_ASSERT_TYPE(xen_hook_p(hook), hook, XEN_ARG_1, "run-hook", "a hook"); - - obj = XEN_TO_GHOOK(hook); - args = XEN_CDR(all_args); - arglen = XEN_LIST_LENGTH(args); - - if (ghook_arity(obj) != arglen) - XEN_ERROR(XEN_ERROR_TYPE("wrong-number-of-args"), - XEN_LIST_5(C_TO_XEN_STRING("run hook (~A) got ~A args, but wants ~A (args: ~A)"), - hook, - C_TO_XEN_INT(arglen), - C_TO_XEN_INT(ghook_arity(obj)), - args)); - - - functions = ghook_functions(obj); - while (XEN_NOT_NULL_P(functions)) - { - val = XEN_APPLY(XEN_CAR(functions), args, "run-hook"); - functions = XEN_CDR(functions); - } - - return(val); -} - - -static XEN g_remove_hook(XEN hook, XEN function) -{ - ghook *obj; - XEN_ASSERT_TYPE(xen_hook_p(hook), hook, XEN_ARG_1, "remove-hook!", "a hook"); - obj = XEN_TO_GHOOK(hook); - XEN_ASSERT_TYPE(XEN_PROCEDURE_P(function), function, XEN_ARG_2, "remove-hook!", "a function"); - obj->functions = s7_remv(s7, obj->functions, function); - return(hook); -} - - -XEN xen_s7_define_hook(const char *name, int arity, const char *help) -{ - XEN hook; - ghook *obj; - hook = g_make_hook(C_TO_XEN_INT(arity), XEN_UNDEFINED); - obj = XEN_TO_GHOOK(hook); - obj->documentation = help; - if (name) - { - XEN_DEFINE(name, hook); - } - s7_gc_protect(s7, hook); - return(hook); -} - - -static bool equalp_hook(void *uv1, void *uv2) -{ - return(uv1 == uv2); -} - - -static void mark_hook(void *v) -{ - s7_mark_object(((ghook *)v)->functions); -} - - -static void free_hook(void *v) -{ - free_ghook((ghook *)v); -} - - -static char *print_hook(s7_scheme *sc, void *v) -{ - return(hook_to_string((ghook *)v)); -} - - /* add various file functions that everyone else implements */ #if (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))) @@ -2058,15 +1872,6 @@ static XEN g_gc_on(void) -XEN_NARGIFY_1(g_hook_p_w, g_hook_p); -XEN_NARGIFY_1(g_hook_empty_p_w, g_hook_empty_p) -XEN_NARGIFY_2(g_remove_hook_w, g_remove_hook) -XEN_NARGIFY_1(g_hook_to_list_w, xen_hook_to_list) -XEN_VARGIFY(g_run_hook_w, g_run_hook) -XEN_NARGIFY_1(g_reset_hook_w, xen_s7_reset_hook) -XEN_ARGIFY_2(g_make_hook_w, g_make_hook) -XEN_ARGIFY_3(g_add_hook_w, g_add_hook) - XEN_NARGIFY_0(g_getpid_w, g_getpid) XEN_NARGIFY_1(g_file_exists_p_w, g_file_exists_p) XEN_NARGIFY_1(g_file_is_directory_w, g_file_is_directory) @@ -2104,20 +1909,10 @@ s7_scheme *s7_xen_initialize(s7_scheme *sc) xen_undefined = s7_undefined(s7); xen_zero = s7_make_integer(s7, 0); - ghook_tag = XEN_MAKE_OBJECT_TYPE("<hook>", print_hook, free_hook, equalp_hook, mark_hook, NULL, NULL, NULL, NULL, NULL); - - XEN_DEFINE_PROCEDURE("hook?", g_hook_p_w, 1, 0, 0, "(hook? obj) -> #t if obj is a hook"); - XEN_DEFINE_PROCEDURE("hook-empty?", g_hook_empty_p_w, 1, 0, 0, "(hook-empty? hook) -> #t if obj is an empty hook"); - XEN_DEFINE_PROCEDURE("remove-hook!", g_remove_hook_w, 2, 0, 0, "(remove-hook! hook func) removes func from hook obj"); - XEN_DEFINE_PROCEDURE("reset-hook!", g_reset_hook_w, 1, 0, 0, "(reset-hook! hook) removes all funcs from hook obj"); - XEN_DEFINE_PROCEDURE("hook->list", g_hook_to_list_w, 1, 0, 0, "(hook->list hook) -> list of functions on hook obj"); - XEN_DEFINE_PROCEDURE("run-hook", g_run_hook_w, 0, 0, 1, "(run-hook hook . args) applies each hook function to args"); - XEN_DEFINE_PROCEDURE("make-hook", g_make_hook_w, 1, 1, 0, "(make-hook arity :optional help) makes a new hook object"); - XEN_DEFINE_PROCEDURE("add-hook!", g_add_hook_w, 2, 1, 0, "(add-hook! hook func :optional append) adds func to the hooks function list"); - XEN_DEFINE_PROCEDURE("getpid", g_getpid_w, 0, 0, 0, H_getpid); XEN_DEFINE_PROCEDURE("file-exists?", g_file_exists_p_w, 1, 0, 0, H_file_exists_p); - XEN_DEFINE_PROCEDURE("file-is-directory?", g_file_is_directory_w, 1, 0, 0, H_file_is_directory); /* "directory?" would be a better name, but we follow Guile */ + XEN_DEFINE_PROCEDURE("directory?", g_file_is_directory_w, 1, 0, 0, H_file_is_directory); + XEN_EVAL_C_STRING("(define file-is-directory? directory?)"); /* backwards compatibility: */ XEN_DEFINE_PROCEDURE("system", g_system_w, 1, 0, 0, H_system); XEN_DEFINE_PROCEDURE("getenv", g_s7_getenv_w, 1, 0, 0, H_getenv); XEN_DEFINE_PROCEDURE("delete-file", g_delete_file_w, 1, 0, 0, H_delete_file); @@ -2130,6 +1925,34 @@ s7_scheme *s7_xen_initialize(s7_scheme *sc) XEN_DEFINE_PROCEDURE(S_gc_off, g_gc_off_w, 0, 0, 0, H_gc_off); XEN_DEFINE_PROCEDURE(S_gc_on, g_gc_on_w, 0, 0, 0, H_gc_on); + /* backwards compatibility (guile hook functions) */ + XEN_EVAL_C_STRING("(define (hook-empty? hook) (null? (hook-functions hook)))"); + XEN_EVAL_C_STRING("(define (reset-hook! hook) (set! (hook-functions hook) '()))"); + XEN_EVAL_C_STRING("(define (run-hook . args) (hook-apply (car args) (cdr args)))"); + XEN_EVAL_C_STRING("(define hook->list hook-functions)"); + XEN_EVAL_C_STRING("(define* (add-hook! hook func (at-end #f)) \n\ + (set! (hook-functions hook) \n\ + (if (not at-end) \n\ + (cons func (hook-functions hook)) \n\ + (append (hook-functions hook) (list func)))))"); + XEN_EVAL_C_STRING("(define (remove-hook! hook func) \n\ + (set! (hook-functions hook)\n\ + (let loop ((l (hook-functions hook))\n\ + (result '()))\n\ + (cond ((null? l) (reverse! result))\n\ + ((eq? func (car l)) (loop (cdr l) result))\n\ + (else (loop (cdr l) (cons (car l) result)))))))"); + + /* these three to replace add-hook! and remove-hook! */ + XEN_EVAL_C_STRING("(define (hook-push hook func) \n\ + \"(hook-push hook func) adds func to hook's function list\" \n\ + (set! (hook-functions hook) (cons func (hook-functions hook))))"); + XEN_EVAL_C_STRING("(define (hook-append hook func) \n\ + \"(hook-append hook func) adds func to the end of hook's function list\" \n\ + (set! (hook-functions hook) (append (hook-functions hook) (list func))))"); + XEN_EVAL_C_STRING("(define hook-remove remove-hook!)"); + + XEN_EVAL_C_STRING("(define load-from-path load)"); XEN_EVAL_C_STRING("(define (1+ x) \"add 1 to arg\" (+ x 1))"); XEN_EVAL_C_STRING("(define (1- x) \"subtract 1 from arg\" (- x 1))"); |