|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817 |
- /* xen support procedures */
-
- #include "mus-config.h"
- #include <ctype.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <math.h>
- #include <time.h>
-
- #ifdef _MSC_VER
- #include <io.h>
- #include <process.h>
- #pragma warning(disable: 4244)
- #endif
-
- #include "xen.h"
-
- #define S_gc_off "gc-off"
- #define S_gc_on "gc-on"
-
-
- char *xen_strdup(const char *str)
- {
- char *newstr = NULL;
- if ((!str) || (!(*str))) return(NULL);
- newstr = (char *)malloc(strlen(str) + 1);
- if (newstr) strcpy(newstr, str);
- return(newstr);
- }
-
-
-
- /* ------------------------------ RUBY ------------------------------ */
-
- #if HAVE_RUBY
-
- #define HAVE_RB_PROC_NEW 1
- /* As the README says, only versions of ruby 1.8 or later will work */
-
- #if USE_SND
- void snd_rb_raise(Xen type, Xen info); /* XEN_ERROR */
- #endif
-
- #define S_add_help "add_help"
- #define S_get_help "get_help"
-
- Xen rb_documentation(Xen name)
- {
- Xen_check_type((Xen_is_string(name) || Xen_is_symbol(name)), name, 1, S_get_help, "a char* or symbol");
- if (Xen_is_symbol(name))
- return(rb_property(XEN_SYMBOL_TO_STRING(name), Xen_documentation_symbol));
- else
- return(rb_property(name, Xen_documentation_symbol));
- }
-
-
- Xen rb_set_documentation(Xen name, Xen help)
- {
- Xen_check_type((Xen_is_string(name) || Xen_is_symbol(name)), name, 1, S_add_help, "a char* or symbol");
- Xen_check_type(Xen_is_string(help), help, 2, S_add_help, "a char*");
- if (Xen_is_symbol(name))
- rb_set_property(XEN_SYMBOL_TO_STRING(name), Xen_documentation_symbol, help);
- else
- rb_set_property(name, Xen_documentation_symbol, help);
- return(name);
- }
-
-
- static Xen g_add_help(Xen name, Xen help)
- {
- #define H_add_help S_add_help "(name, help) add help to topic or function name (String or Symbol)"
- return(rb_set_documentation(name, help));
- }
-
-
- static Xen g_get_help(Xen name)
- {
- #define H_get_help S_get_help "([name=:" S_get_help "]) \
- return help associated with name (String or Symbol) or false"
- if (!Xen_is_bound(name))
- return(C_string_to_Xen_string(H_get_help));
- else
- return(rb_documentation(name));
- }
-
-
- void xen_initialize(void)
- {
- #ifdef RUBY_INIT_STACK
- RUBY_INIT_STACK;
- #endif
-
- ruby_init();
- ruby_init_loadpath();
- ruby_script("xen"); /* necessary in ruby 1.9 (else segfault in rb_raise -- is this the rb GC bug (see snd-xen.c)?) */
-
- Init_Hook();
- }
-
-
- void xen_gc_mark(Xen val)
- {
- rb_gc_mark(val);
- }
-
-
- Xen xen_rb_cdr(Xen val)
- {
- if (Xen_is_cons(val))
- {
- Xen new_list;
- new_list = Xen_copy_arg(val);
- rb_ary_delete_at(new_list, 0);
- return(new_list);
- }
- return(val);
- }
-
-
- Xen xen_rb_cons(Xen arg1, Xen arg2)
- {
- if (Xen_is_null(arg2))
- return(rb_ary_new3(1, arg1));
- if (!(Xen_is_cons(arg2)))
- return(rb_ary_new3(2, arg1, arg2));
- return(rb_ary_unshift(arg2, arg1)); /* arg2 assumed to be array here in Ruby */
- }
-
-
- Xen xen_rb_cons2(Xen arg1, Xen arg2, Xen arg3)
- {
- return(rb_ary_unshift(xen_rb_cons(arg2, arg3), arg1));
- }
-
-
- Xen xen_rb_ary_new_with_initial_element(long num, Xen element)
- {
- Xen arr;
- int i;
- arr = rb_ary_new2(num);
- for (i = 0; i < num; i++)
- rb_ary_store(arr, i, element);
- return(arr);
- }
-
-
- Xen xen_set_assoc(Xen key, Xen val, Xen alist)
- {
- /* assoc key val in alist so later rb_ary_assoc will find val given key in alist */
- /*
- if array?(alist)
- if array?(item = alist.assoc(key))
- item[1] = val
- else
- alist.push([key, val])
- end
- else
- [[key, val]]
- end
- */
- if (Xen_is_cons(alist))
- {
- Xen pair;
- pair = rb_ary_assoc(alist, key);
- if (Xen_is_cons(pair))
- rb_ary_store(pair, 1, val);
- else rb_ary_push(alist, rb_assoc_new(key, val));
- return(alist);
- }
- return(rb_ary_new3(1, rb_assoc_new(key, val)));
- }
-
-
- Xen xen_assoc(Xen key, Xen alist)
- {
- if (Xen_is_cons(alist))
- {
- Xen val;
- val = rb_ary_assoc(alist, key);
- if (val != Qnil)
- return(rb_ary_entry(val, 1));
- }
- return(Qfalse);
- }
-
-
- static char *scheme_to_ruby(const char *name)
- {
- /* replace any non-alphanumeric except "?" with "_". "?" -> "_p". '->" -> "2" drop "!" */
- char *new_name = NULL;
- int len;
- len = strlen(name);
- if (len > 0)
- {
- int i, j;
- new_name = (char *)calloc(len + 3, sizeof(char)); /* +1 for possible _p, +1 for possible $ */
- for (i = 0, j = 0; i < len; i++)
- {
- if (isalnum(name[i]))
- new_name[j++] = name[i];
- else
- {
- if (name[i] != '!')
- {
- if ((name[i] == '-') &&
- (name[i + 1] == '>'))
- {
- new_name[j++] = '2';
- i++;
- }
- else
- {
- new_name[j++] = '_';
- if (name[i] == '?')
- new_name[j++] = 'p';
- }
- }
- }
- }
- }
- return(new_name);
- }
-
-
- char *xen_scheme_constant_to_ruby(const char *name)
- {
- /* upcase first char */
- char *new_name;
- new_name = scheme_to_ruby(name);
- new_name[0] = toupper(new_name[0]);
- return(new_name);
- }
-
-
- char *xen_scheme_procedure_to_ruby(const char *name)
- {
- char *new_name = NULL;
- int len;
- len = name ? strlen(name) : 0;
- if (len > 0)
- {
- int i, j;
- new_name = (char *)calloc(len + 1, sizeof(char));
- for (i = 0, j = 0; i < len; i++)
- {
- if ((isalnum(name[i])) || (name[i] == '!') || (name[i] == '?'))
- new_name[j++] = name[i];
- else
- {
- if ((name[i] == '-') &&
- (name[i + 1] == '>'))
- {
- new_name[j++] = '2';
- i++;
- }
- else new_name[j++] = '_';
- }
- }
- }
- return(new_name);
- }
-
-
- char *xen_scheme_global_variable_to_ruby(const char *name)
- {
- /* prepend $ */
- char *new_name;
- new_name = scheme_to_ruby(name);
- if (new_name[0] == '_')
- new_name[0] = '$';
- else
- {
- int i, len;
- len = strlen(new_name);
- for (i = len; i > 0; i--)
- new_name[i] = new_name[i - 1];
- new_name[0] = '$';
- }
- return(new_name);
- }
-
-
- /* looks for global variables and constants (functions too?) */
-
- bool xen_rb_defined_p(const char *name)
- {
- char *var_name = scheme_to_ruby(name);
- char buf[128];
-
- if (var_name[0] == '$')
- sprintf(buf, "defined? %s", var_name);
- else sprintf(buf, "defined? $%s", var_name);
-
- if (Xen_eval_C_string(buf) != Qnil)
- {
- free(var_name);
- return(true);
- }
- else
- {
- bool val;
- var_name[0] = toupper(var_name[0]);
- val = rb_const_defined(rb_cObject, rb_intern(var_name));
- free(var_name);
- return(val);
- }
- }
-
-
- Xen xen_rb_gv_get(const char *name)
- {
- char *temp;
- Xen val;
- temp = xen_scheme_global_variable_to_ruby(name);
- val = rb_gv_get(temp);
- if (temp) free(temp);
- return(val);
- }
-
-
- Xen xen_rb_gv_set(const char *name, Xen new_val)
- {
- char *temp;
- Xen val;
- temp = xen_scheme_global_variable_to_ruby(name);
- val = rb_gv_set(temp, new_val);
- if (temp) free(temp);
- return(val);
- }
-
-
- Xen xen_rb_intern(const char *name)
- {
- char *temp;
- Xen val;
- temp = xen_scheme_constant_to_ruby(name);
- val = rb_intern(temp);
- if (temp) free(temp);
- return(val);
- }
-
-
- Xen xen_rb_make_keyword(const char *name)
- {
- char *temp;
- Xen val;
- temp = xen_scheme_procedure_to_ruby(name);
- val = C_string_to_Xen_symbol(temp);
- if (temp) free(temp);
- return(val);
- }
-
-
- void xen_rb_define(const char *name, Xen value)
- {
- char *temp;
- temp = xen_scheme_constant_to_ruby(name);
- rb_define_global_const(temp, value);
- if (temp) free(temp);
- }
-
-
- Xen xen_rb_define_class(const char *name)
- {
- char *temp;
- Xen val;
- temp = xen_scheme_constant_to_ruby(name);
- val = rb_define_class(temp, rb_cObject);
- if (temp) free(temp);
- return(val);
- }
-
-
-
-
- #ifndef RARRAY_PTR
- #define RB_ARRAY_PTR(Ary) RARRAY(Ary)->ptr
- #define RB_ARRAY_LEN(Ary) RARRAY(Ary)->len
- #else
- #define RB_ARRAY_PTR(Ary) RARRAY_PTR(Ary)
- #define RB_ARRAY_LEN(Ary) RARRAY_LEN(Ary)
- #endif
-
-
- int xen_rb_list_length(Xen obj)
- {
- if (Xen_is_vector(obj))
- return((int)RB_ARRAY_LEN(obj));
- if (obj == Xen_empty_list)
- return(0);
- return(-1);
- }
-
-
- Xen xen_rb_list_ref(Xen obj, int index)
- {
- if (Xen_is_vector(obj))
- return(rb_ary_entry(obj, (long)index));
- return(Xen_empty_list);
- }
-
-
- Xen xen_rb_list_set(Xen obj, int index, Xen value)
- {
- if (Xen_is_vector(obj))
- rb_ary_store(obj, (long)index, value);
- return(value);
- }
-
-
- char *xen_version(void)
- {
- /* there is no macro we can depend on for the version number (its name changes unpredictably),
- * and ruby/version.h tries to be funny about how unreliable their semi-functional access is.
- * Maybe use <ruby/version.h> and ruby_version here (a const char*).
- * No, even that doesn't work because there's no way to tell whether version.h exists.
- * Humph!
- */
- char *buf;
- buf = (char *)calloc(128, sizeof(char));
- snprintf(buf, 128, "%s", "Ruby");
- return(buf);
- }
-
-
- static Xen xen_rb_report_error(Xen nada, Xen err_info)
- {
- /* backtrace info: */
- /* return rb_funcall(err_info, rb_intern("backtrace"), 0); */
- /* which can be an array of strings */
-
- fprintf(stderr,"error: %s\n", Xen_object_to_C_string(err_info));
- return(Xen_false);
- }
-
-
- static char *rb_prompt = NULL;
-
- static Xen xen_rb_rep(Xen ig)
- {
- Xen val;
- char *str;
- size_t size = 512;
- char **buffer = NULL;
- buffer = (char **)calloc(1, sizeof(char *));
- buffer[0] = (char *)calloc(size, sizeof(char));
- fprintf(stdout, "%s", rb_prompt);
- fgets(buffer[0], size, stdin);
- val = xen_rb_eval_string_with_error(buffer[0]);
- str = Xen_object_to_C_string(val);
- fprintf(stdout, "%s\n", (str) ? str : "nil");
- free(buffer[0]);
- free(buffer);
- return(ig);
- }
-
-
- void xen_rb_repl_set_prompt(const char *prompt)
- {
- if (rb_prompt) free(rb_prompt);
- rb_prompt = xen_strdup(prompt);
- }
-
-
- static Xen xen_rb_rescue(Xen val)
- {
- if (!rb_prompt) rb_prompt = xen_strdup(">");
- return(rb_rescue(Xen_procedure_cast xen_rb_rep,
- Xen_false,
- Xen_procedure_cast xen_rb_report_error,
- Xen_false));
- }
-
-
- void xen_repl(int argc, char **argv)
- {
- while (true)
- {
- int status = 0;
- rb_protect(XEN_VALUE_ARG_PROCEDURE_CAST xen_rb_rescue,
- Xen_false,
- &status);
- if (status != 0)
- {
- fprintf(stderr, "%s\n", Xen_object_to_C_string(rb_gv_get("$!")));
- status = 0;
- }
- }
- }
-
-
- Xen xen_rb_eval_string_with_error(const char *str)
- {
- int status = 0;
- Xen res;
- res = rb_eval_string_protect(str, &status);
- if (status != 0)
- return(xen_rb_obj_as_string(rb_gv_get("$!")));
- return(res);
- }
-
-
- Xen xen_rb_load_file_with_error(Xen file)
- {
- int status = 0;
- rb_load_protect(file, 0, &status);
- if (status != 0)
- return(xen_rb_obj_as_string(rb_gv_get("$!")));
- return(Xen_true);
- }
-
-
- 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_is_false(rb_ary_includes(load_path, rpath)))
- rb_ary_unshift(load_path, rpath);
- return(Xen_false);
- }
-
-
- static char *lstbuf = NULL;
-
- static char *xen_rb_list_to_s(Xen lst)
- {
- int i, len;
- if (lstbuf == NULL)
- lstbuf = (char *)calloc(512, sizeof(char));
- else lstbuf[0] = '\0';
- len = Xen_list_length(lst);
- for (i = 0; i < len; i++)
- {
- strcat(lstbuf, Xen_object_to_C_string(Xen_list_ref(lst, i)));
- strcat(lstbuf, " ");
- }
- return(lstbuf);
- }
-
-
- void xen_rb_raise(Xen type, Xen info)
- {
- rb_raise(rb_eStandardError, "%s: %s\n",
- rb_id2name(type),
- xen_rb_list_to_s(info));
- }
-
-
- int xen_rb_required_args(Xen val)
- {
- int args;
- args = Xen_integer_to_C_int(val);
- if (args == -1) return(1);
- if (args < 0) return(abs(args + 1));
- return(args);
- }
-
-
- Xen xen_rb_obj_as_string(Xen obj)
- {
- int status = 0;
- Xen result;
- result = rb_protect(XEN_VALUE_ARG_PROCEDURE_CAST rb_obj_as_string,
- obj,
- &status);
- if (status != 0)
- return(C_string_to_Xen_string("<invalid object>"));
- return(result);
- }
-
-
- #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)
- {
- if (Xen_is_procedure(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)
- {
- Xen val;
- int status = 0;
- val = rb_protect(XEN_VALUE_ARG_PROCEDURE_CAST xen_rb_apply_1,
- Xen_list_2(func, args),
- &status);
- if (status != 0)
- return(xen_rb_obj_as_string(rb_gv_get("$!")));
- return(val);
- }
-
-
- static Xen xen_rb_funcall_0_inner(Xen args)
- {
- return(rb_funcall(args, rb_intern("call"), 0));
- }
-
-
- Xen xen_rb_funcall_0(Xen func)
- {
- Xen val;
- int status = 0;
- val = rb_protect(XEN_VALUE_ARG_PROCEDURE_CAST xen_rb_funcall_0_inner,
- func,
- &status);
- if (status != 0)
- return(xen_rb_obj_as_string(rb_gv_get("$!")));
- return(val);
- }
-
-
- Xen xen_rb_copy_list(Xen val)
- {
- if ((val == Xen_empty_list) || (!Xen_is_cons(val)))
- return Xen_empty_list;
- return rb_ary_dup(val);
- }
-
-
- Xen xen_rb_str_new2(char *arg)
- {
- return(rb_str_new2((arg) ? arg : ""));
- }
-
-
- /* class Hook */
-
- static Xen xen_rb_cHook;
-
- static Xen hook_alloc(Xen klass)
- {
- return(Data_Wrap_Struct(klass, 0, 0, 0));
- }
-
-
- #define Xen_is_class_hook(Arg) rb_obj_is_kind_of(Arg, xen_rb_cHook)
-
- bool xen_rb_hook_p(Xen obj)
- {
- return(Xen_is_class_hook(obj));
- }
-
-
- bool xen_rb_hook_empty_p(Xen obj)
- {
- if (Xen_is_class_hook(obj))
- return(RB_ARRAY_LEN(rb_iv_get(obj, "@procs")) == 0);
- return(true);
- }
-
-
- /*
- * @name = "$name_of_hook"
- * @arity = arity of procedure(s), default 0
- * @procs = [["named proc1", proc1], ...]
- */
-
- static Xen xen_rb_hook_initialize(int argc, Xen *argv, Xen hook)
- {
- Xen name, arity, help;
- rb_scan_args(argc, argv, "12", &name, &arity, &help);
- Xen_check_type(Xen_is_string(name) || Xen_is_symbol(name), name, 1, __func__, "a char* or symbol");
- if (Xen_is_symbol(name))
- name = XEN_SYMBOL_TO_STRING(name);
- if (arity != Qnil)
- {
- Xen_check_type(Xen_is_integer(arity), arity, 2, __func__, "an integer");
- }
- else arity = INT2NUM(0);
- if (help != Qnil)
- {
- Xen_check_type(Xen_is_string(help), help, 3, __func__, "a char*");
- XEN_SET_OBJECT_HELP(name, help);
- }
- rb_iv_set(hook, "@name", name);
- rb_iv_set(hook, "@arity", arity);
- rb_iv_set(hook, "@procs", rb_ary_new());
- return(hook);
- }
-
-
- /*
- * To create a simple hook in C, see xen.h, XEN_DEFINE_SIMPLE_HOOK.
- * To create a global hook variables, see xen_rb_create_hook() below.
- */
-
- Xen xen_rb_hook_c_new(char *name, int arity, char *help)
- {
- Xen args[3];
- args[0] = C_string_to_Xen_string(name);
- args[1] = C_int_to_Xen_integer(arity);
- args[2] = C_string_to_Xen_string(help);
- return(xen_rb_hook_initialize(3, args, hook_alloc(xen_rb_cHook)));
- }
-
-
- /*
- RUBY_RELEASE_DATE < "2004-03-18" ? old : new
-
- lambda do end.arity -1 0 !!!
- lambda do || end.arity 0 0
- lambda do |a| end.arity -1 1 !!!
- lambda do |*a| end.arity -1 -1
- lambda do |a, b| end.arity 2 2
- lambda do |a, *b| end.arity -2 -2
- etc.
- */
-
- #ifdef RUBY_VERSION
- #define XEN_RUBY_RELEASE_DATE RUBY_RELEASE_DATE
- #else
- #define XEN_RUBY_RELEASE_DATE Xen_string_to_C_string(Xen_eval_C_string("RUBY_RELEASE_DATE"))
- #endif
-
- #define RUBY_NEW_ARITY_DATE "2004-03-18"
- #define OLD_RUBY_ARITY() (strcmp(XEN_RUBY_RELEASE_DATE, RUBY_NEW_ARITY_DATE) < 0)
- /* #define NEW_RUBY_ARITY() (strcmp(XEN_RUBY_RELEASE_DATE, RUBY_NEW_ARITY_DATE) >= 0) */
-
- bool xen_rb_arity_ok(int rargs, int args)
- {
- if (OLD_RUBY_ARITY())
- {
- if ((rargs >= 2) || (rargs == 0))
- return(rargs == args);
- else if (rargs <= -2)
- return(abs(rargs) <= args);
- else /* rargs -1 remains (no 1 exists) */
- return((args == 1) || (args == 0) || (args == -1));
- }
- else /* NEW_RUBY_ARITY */
- return((rargs >= 0) ? (rargs == args) : (abs(rargs) <= args));
- }
-
-
- static Xen xen_rb_hook_add_hook(int argc, Xen *argv, Xen hook)
- {
- Xen name, func;
- int args;
- args = Xen_integer_to_C_int(rb_iv_get(hook, "@arity"));
- rb_scan_args(argc, argv, "1&", &name, &func);
- Xen_check_type(Xen_is_string(name), name, 1, __func__, "a char*");
- Xen_check_type(Xen_is_procedure(func) && xen_rb_arity_ok(Xen_integer_to_C_int(Xen_arity(func)), args),
- func, 2, __func__, "a procedure");
- rb_ary_push(rb_iv_get(hook, "@procs"), rb_ary_new3(2, name, func));
- return(hook);
- }
-
-
- #if HAVE_RB_PROC_NEW
-
- static Xen xen_proc_call(Xen args, Xen id)
- {
- return(rb_apply(rb_mKernel, (ID)id, Xen_is_cons(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_string_to_Xen_string(temp), xen_rb_proc_new(temp, func, Xen_integer_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, avar;
- char *temp;
- temp = xen_scheme_procedure_to_ruby(name);
- avar = rb_iv_get(hook, "@arity");
- rb_define_module_function(rb_mKernel, temp, Xen_procedure_cast func, (Xen_is_integer(avar)) ? Xen_integer_to_C_int(avar) : 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_string_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;
- ary = rb_iv_get(hook, "@procs");
- return(rb_ary_delete(ary, rb_ary_assoc(ary, name)));
- }
-
-
- Xen xen_rb_hook_reset_hook(Xen hook)
- {
- if (Xen_is_class_hook(hook))
- rb_ary_clear(rb_iv_get(hook, "@procs"));
- return(hook);
- }
-
-
- static Xen xen_rb_hook_names(Xen hook)
- {
- Xen ary, ret = Qnil;
- long len;
- ary = rb_iv_get(hook, "@procs");
- len = RB_ARRAY_LEN(ary);
- if (len > 0)
- {
- long i;
- ret = rb_ary_new2(len);
- for (i = 0; i < len; i++)
- rb_ary_store(ret, i, Xen_vector_ref(Xen_vector_ref(ary, i), 0));
- }
- return(ret);
- }
-
-
- Xen xen_rb_hook_to_a(Xen hook)
- {
- Xen ret = Qnil;
- if (Xen_is_class_hook(hook))
- {
- Xen ary;
- long len;
- ary = rb_iv_get(hook, "@procs");
- len = Xen_list_length(ary);
- if (len > 0)
- {
- long i;
- ret = rb_ary_new2(len);
- for (i = 0; i < len; i++)
- rb_ary_store(ret, i, Xen_vector_ref(Xen_vector_ref(ary, i), 1));
- }
- }
- return(ret);
- }
-
-
- static Xen xen_rb_hook_run_hook(Xen hook)
- {
- if (RB_ARRAY_LEN(rb_iv_get(hook, "@procs")))
- rb_ary_each(xen_rb_hook_to_a(hook));
- return(hook);
- }
-
-
- /*
- * Calls all hook-procedures but returns only the last result; use
- * $var_hook.run_hook { |prc| ret << prc.call(*args) } for collecting
- * results.
- */
-
- static Xen xen_rb_hook_call(int argc, Xen *argv, Xen hook)
- {
- Xen result = Qnil, rest, procs;
- rb_scan_args(argc, argv, "*", &rest);
- procs = xen_rb_hook_to_a(hook);
- if (procs != Qnil)
- {
- long i;
- for (i = 0; i < RB_ARRAY_LEN(procs); i++)
- result = xen_rb_apply(rb_ary_entry(procs, i), rest);
- }
- return(result);
- }
-
-
- static Xen xen_rb_hook_is_empty_p(Xen hook)
- {
- return(C_bool_to_Xen_boolean(RB_ARRAY_LEN(rb_iv_get(hook, "@procs")) == 0));
- }
-
-
- static Xen xen_rb_hook_length(Xen hook)
- {
- return(C_int_to_Xen_integer(RB_ARRAY_LEN(rb_iv_get(hook, "@procs"))));
- }
-
-
- static Xen xen_rb_hook_name(Xen hook)
- {
- return(rb_iv_get(hook, "@name"));
- }
-
-
- static Xen xen_rb_hook_describe(Xen hook)
- {
- return(Xen_documentation(xen_rb_hook_name(hook)));
- }
-
-
- static Xen xen_rb_hook_arity(Xen hook)
- {
- return(rb_iv_get(hook, "@arity"));
- }
-
-
- static Xen xen_rb_hook_inspect(Xen hook)
- {
- Xen str = rb_str_new2("#<Hook name: ");
- rb_str_append(str, rb_inspect(rb_iv_get(hook, "@name")));
- rb_str_cat2(str, ", arity: ");
- rb_str_append(str, rb_inspect(rb_iv_get(hook, "@arity")));
- rb_str_cat2(str, ", procs[");
- rb_str_append(str, rb_inspect(xen_rb_hook_length(hook)));
- rb_str_cat2(str, "]: ");
- rb_str_append(str, rb_inspect(xen_rb_hook_names(hook)));
- rb_str_cat2(str, ">");
- return(str);
- }
-
-
- /* bil -- added xen_rb_create_hook for Xen_define_hook in xen.h, 13-Jun-05 --
- * seems to work, but I'm guessing, especially the rb_gv_set line.
- * I can't use rb_define_variable here, as in the old version, because it takes a pointer
- * to the new variable, which in this case is a local variable => segfault.
- */
-
- Xen xen_rb_create_hook(char *name, int arity, char *help)
- {
- Xen var, hook_name;
- char *temp;
- var = xen_rb_hook_c_new(temp = xen_scheme_global_variable_to_ruby(name), arity, help);
- hook_name = xen_rb_hook_name(var);
- rb_gv_set(Xen_string_to_C_string(hook_name), var);
- if (temp) free(temp);
- 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)
- *
- * make_hook("var_hook")
- * == $var_hook = Hook.new("var_hook")
- * make_hook("var_hook", 1)
- * == $var_hook = Hook.new("var_hook", 1)
- * make_hook("var_hook", 1, "help $var_hook")
- * == $var_hook = Hook.new("var_hook", 1, "help $var_hook")
- *
- * make_hook("var_hook", 1, "help $var_hook", "1st proc") do |a| ... end
- * == $var_hook = Hook.new("var_hook", 1, "help $var_hook")
- * $var_hook.add_hook!("1st proc") do |a| ... end
- */
-
- #ifndef RSTRING_LEN
- #define RB_STR_LEN(str) RSTRING(str)->len
- #else
- #define RB_STR_LEN(str) RSTRING_LEN(str)
- #endif
-
- static Xen xen_rb_make_hook(int argc, Xen *argv, Xen klass)
- {
- Xen hook = Xen_false, name;
- if (argc > 0 && argc < 4)
- {
- hook = xen_rb_hook_initialize(argc, argv, hook_alloc(xen_rb_cHook));
- if (rb_block_given_p())
- {
- argv[0] = rb_str_new2("");
- xen_rb_hook_add_hook(1, argv, hook);
- }
- }
- else if (argc == 4 && rb_block_given_p())
- {
- hook = xen_rb_hook_initialize(3, argv, hook_alloc(xen_rb_cHook));
- argv[0] = argv[3];
- xen_rb_hook_add_hook(1, argv, hook);
- }
- else Xen_error(Xen_make_error_type("wrong-number-of-args"),
- Xen_list_1(C_string_to_Xen_string("make_hook(name, arity=0, help=\"\", hook_name=\"\", &func)")));
- name = xen_rb_hook_name(hook);
- if (Xen_char_to_C_char(name) != '$')
- {
- char *temp;
- temp = xen_scheme_global_variable_to_ruby(Xen_string_to_C_string(name));
- name = C_string_to_Xen_string(temp);
- if (temp) free(temp);
- }
- Xen_check_type(RB_STR_LEN(name) >= 2, name, 1, __func__, "a char*, len >= 2");
- return(rb_gv_set(Xen_string_to_C_string(name), hook));
- }
-
-
- static Xen xen_rb_is_hook_p(Xen klass, Xen obj)
- {
- return(C_bool_to_Xen_boolean(Xen_is_class_hook(obj)));
- }
-
-
- /*
- * Hook.new(name, arity = 0, help = "")
- *
- * $my_hook = Hook.new("my_hook", 2, "info of my_hook")
- * $my_hook.add_hook!("1st proc") do |a, b| ... end
- * or make_hook("my_hook", 2, "info of my_hook", "1st proc") do |a, b| ... end
- *
- * $my_hook.add_hook!("2nd proc") do |a, b| ... end
- * $my_hook.inspect --> #<Hook name: "$my_hook", arity: 2, procs[2]: ["1st proc", "2nd proc"]>
- *
- * ret = 0
- * $my_hook.run_hook do |prc| ret = prc.call(ret, 2) end
- *
- * $my_hook.help --> info of my_hook
- * $my_hook.remove_hook!("1st proc")
- * $my_hook.inspect --> #<Hook name: "$my_hook", arity: 2, procs[1]: ["2nd proc"]>
- *
- * $my_hook.remove_hook!("2nd proc")
- * $my_hook.inspect --> #<Hook name: "$my_hook", arity: 2, procs[0]: nil>
- */
-
- #if (!HAVE_RB_DEFINE_ALLOC_FUNC)
- static Xen xen_rb_new(int argc, Xen *argv, Xen klass)
- {
- Xen hook = hook_alloc(klass);
- rb_obj_call_init(hook, argc, argv);
- return(hook);
- }
- #endif
-
-
- static Xen rb_object_properties = Xen_false;
-
- #define S_property "property"
- #define S_set_property "set_property"
- #define S_properties "properties"
-
-
- Xen rb_property(Xen obj, Xen key)
- {
- #define H_property S_property "(obj, key) \
- if key exists, return obj's value (maybe nil) associated with key otherwise false"
- Xen props = Xen_false;
-
- if (Xen_is_false(rb_object_properties))
- return(Xen_false);
-
- props = rb_hash_aref(rb_object_properties, obj);
-
- if (Xen_is_false(props) || props == Qnil)
- return(Xen_false);
- else
- return(rb_hash_aref(props, key));
- }
-
-
- Xen rb_set_property(Xen obj, Xen key, Xen value)
- {
- #define H_set_property S_set_property "(obj, key, value) \
- set key-value pair for obj and return value"
- Xen props = Xen_false;
-
- if (Xen_is_false(rb_object_properties))
- {
- rb_object_properties = rb_hash_new();
- Xen_GC_protect(rb_object_properties);
- }
- else
- props = rb_hash_aref(rb_object_properties, obj);
-
- if (Xen_is_false(props) || props == Qnil)
- props = rb_hash_new();
-
- rb_hash_aset(props, key, value);
- rb_hash_aset(rb_object_properties, obj, props);
- return(value);
- }
-
-
- Xen rb_properties(void)
- {
- #define H_properties S_properties "() return all properties of rb_object_properties (a hash)"
- return(rb_object_properties);
- }
-
-
- static Xen g_gc_off(void)
- {
- #define H_gc_off "(" S_gc_off ") turns off garbage collection"
- rb_gc_disable();
- return(Xen_false);
- }
-
-
- static Xen g_gc_on(void)
- {
- #define H_gc_on "(" S_gc_on ") turns on garbage collection"
- rb_gc_enable();
- return(Xen_false);
- }
-
-
- Xen_wrap_1_optional_arg(g_get_help_w, g_get_help);
- Xen_wrap_2_args(g_add_help_w, g_add_help);
- Xen_wrap_3_args(g_set_property_w, rb_set_property);
- Xen_wrap_2_args(g_property_w, rb_property);
- Xen_wrap_no_args(g_properties_w, rb_properties);
-
- Xen_wrap_no_args(g_gc_off_w, g_gc_off)
- Xen_wrap_no_args(g_gc_on_w, g_gc_on)
-
-
- static bool hook_inited = false;
-
- void Init_Hook(void)
- {
- if (hook_inited) return;
- hook_inited = true;
-
- xen_rb_cHook = rb_define_class("Hook", rb_cObject);
- rb_include_module(xen_rb_cHook, rb_mEnumerable);
- #if HAVE_RB_DEFINE_ALLOC_FUNC
- rb_define_alloc_func(xen_rb_cHook, hook_alloc);
- #else
- rb_define_singleton_method(xen_rb_cHook, "new", Xen_procedure_cast xen_rb_new, -1);
- #endif
-
- rb_define_method(xen_rb_cHook, "initialize", Xen_procedure_cast xen_rb_hook_initialize, -1);
- rb_define_method(xen_rb_cHook, "add_hook!", Xen_procedure_cast xen_rb_hook_add_hook, -1);
- rb_define_method(xen_rb_cHook, "remove_hook!", Xen_procedure_cast xen_rb_hook_remove_hook, 1);
- rb_define_method(xen_rb_cHook, "reset_hook!", Xen_procedure_cast xen_rb_hook_reset_hook, 0);
- rb_define_alias(xen_rb_cHook, "clear", "reset_hook!");
- rb_define_method(xen_rb_cHook, "to_a", Xen_procedure_cast xen_rb_hook_to_a, 0);
- rb_define_method(xen_rb_cHook, "run_hook", Xen_procedure_cast xen_rb_hook_run_hook, 0);
- rb_define_alias(xen_rb_cHook, "each", "run_hook");
- rb_define_method(xen_rb_cHook, "call", Xen_procedure_cast xen_rb_hook_call, -1);
- rb_define_method(xen_rb_cHook, "length", Xen_procedure_cast xen_rb_hook_length, 0);
- rb_define_alias(xen_rb_cHook, "size", "length");
- rb_define_method(xen_rb_cHook, "empty?", Xen_procedure_cast xen_rb_hook_is_empty_p, 0);
- rb_define_method(xen_rb_cHook, "name", Xen_procedure_cast xen_rb_hook_name, 0);
- rb_define_method(xen_rb_cHook, "arity", Xen_procedure_cast xen_rb_hook_arity, 0);
- rb_define_method(xen_rb_cHook, "describe", Xen_procedure_cast xen_rb_hook_describe, 0);
- rb_define_alias(xen_rb_cHook, "help", "describe");
- rb_define_alias(xen_rb_cHook, "documentation", "describe");
- rb_define_method(xen_rb_cHook, "inspect", Xen_procedure_cast xen_rb_hook_inspect, 0);
-
- rb_define_global_function("make_hook", Xen_procedure_cast xen_rb_make_hook, -1);
- rb_define_global_function("hook?", Xen_procedure_cast xen_rb_is_hook_p, 1);
-
- Xen_define_procedure(S_get_help, g_get_help_w, 0, 1, 0, H_get_help);
- Xen_define_procedure(S_add_help, g_add_help_w, 2, 0, 0, H_add_help);
-
- Xen_define_procedure(S_set_property, g_set_property_w, 3, 0, 0, H_set_property);
- Xen_define_procedure(S_property, g_property_w, 2, 0, 0, H_property);
- Xen_define_procedure(S_properties, g_properties_w, 0, 0, 0, H_properties);
-
- 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);
- }
-
- /* end of class Hook */
-
- #endif
-
-
-
- /* ------------------------------ FORTH ------------------------------ */
-
- #if HAVE_FORTH
-
- char *xen_version(void)
- {
- return(fth_format("Fth: %s, Xen: " XEN_VERSION, FTH_VERSION));
- }
-
-
- void xen_gc_mark(Xen val)
- {
- fth_gc_mark(val);
- }
-
-
- /*
- * A simple interpreter:
- *
- * #include <xen.h>
- *
- * int main(int argc, char **argv)
- * {
- * xen_repl(argc, argv);
- * return(0);
- * }
- *
- * linking requires xen.o and -lfth -lm
- */
-
- void xen_repl(int argc, char **argv)
- {
- fth_repl(argc, argv);
- }
-
-
- static ficlWord *snd_exit_xt;
-
- static void fth_snd_exit(int n)
- {
- if (!snd_exit_xt)
- snd_exit_xt = ficlSystemLookup(FTH_FICL_SYSTEM(), (char *)"snd-exit");
- ficlStackPushInteger(FTH_FICL_STACK(), n);
- ficlVmExecuteXT(FTH_FICL_VM(), snd_exit_xt);
- ficlStackDrop(FTH_FICL_STACK(), 1);
- }
-
-
- static Xen g_gc_off(void)
- {
- #define H_gc_off "(" S_gc_off ") turns off garbage collection"
- fth_gc_on();
- return(Xen_false);
- }
-
-
- static Xen g_gc_on(void)
- {
- #define H_gc_on "(" S_gc_on ") turns on garbage collection"
- fth_gc_on();
- return(Xen_false);
- }
-
-
- void xen_initialize(void)
- {
- fth_init();
- fth_exit_hook = fth_snd_exit;
-
- Xen_define_procedure(S_gc_off, g_gc_off, 0, 0, 0, H_gc_off);
- Xen_define_procedure(S_gc_on, g_gc_on, 0, 0, 0, H_gc_on);
- }
-
- #endif /* HAVE_FORTH */
-
-
-
- /* ------------------------------ S7 ------------------------------ */
-
- #if HAVE_SCHEME
- #include "s7.h"
-
- #if ENABLE_WEBSERVER
- #include "s7webserver/s7webserver.h"
- #endif
-
- s7_scheme *s7;
- Xen xen_false, xen_true, xen_nil, xen_undefined, xen_zero;
-
- char *xen_version(void)
- {
- char *buf;
- buf = (char *)calloc(64, sizeof(char));
- #if HAVE_SNPRINTF
- snprintf(buf, 64, "s7: %s (%s), Xen: %s", S7_VERSION, S7_DATE, XEN_VERSION);
- #else
- sprintf(buf, "s7: %s (%s), Xen: %s", S7_VERSION, S7_DATE, XEN_VERSION);
- #endif
- return(buf);
- }
-
-
- static char *xen_s7_repl_prompt = NULL;
-
- void xen_s7_set_repl_prompt(const char *new_prompt)
- {
- if (xen_s7_repl_prompt) free(xen_s7_repl_prompt);
- xen_s7_repl_prompt = xen_strdup(new_prompt);
- }
-
-
- #if USE_SND
- char *stdin_check_for_full_expression(const char *newstr);
- void stdin_free_str(void);
- #endif
-
- void xen_repl(int argc, char **argv)
- {
- int size = 512;
- bool expr_ok = true;
- char *buffer = NULL;
- buffer = (char *)calloc(size, sizeof(char));
-
- while (true)
- {
- if (expr_ok)
- {
- fprintf(stdout, "\n%s", xen_s7_repl_prompt);
- expr_ok = false; /* don't get into an infinite loop if running in the background! */
- }
- if (fgets(buffer, size, stdin) != NULL)
- {
- /* also, it's possible to get a string of spaces or nulls (? -- not sure what is coming in) if stdin is /dev/null */
- /* then if (as in condor) stdout is being saved in a file, we get in an infinite loop storing "snd>" until the disk fills up */
- int i, len;
-
- expr_ok = false;
- len = strlen(buffer);
- for (i = 0; i < len; i++)
- {
- if (buffer[i] == 0)
- break;
- if (!isspace((int)buffer[i]))
- {
- expr_ok = true;
- break;
- }
- }
- if (expr_ok)
- {
- char *str, *temp;
- #if USE_SND
- str = stdin_check_for_full_expression(buffer); /* "str" here is actually stdin_str, so we need to clear it explicitly */
- if (!str) {expr_ok = false; continue;}
- len = strlen(str) + 16;
- temp = (char *)malloc(len * sizeof(char));
- snprintf(temp, len, "(write %s)", str);
- Xen_eval_C_string(temp);
- free(temp);
- stdin_free_str();
- #else
- temp = (char *)malloc(len + 16);
- snprintf(temp, len + 16, "(write %s)", buffer); /* use write, not display so that strings are in double quotes */
- Xen_eval_C_string(temp);
- free(temp);
- #endif
- }
- }
- }
- free(buffer);
- }
-
-
- void xen_gc_mark(Xen val)
- {
- s7_mark_object(val);
- }
-
-
- Xen xen_set_assoc(s7_scheme *sc, s7_pointer key, s7_pointer val, s7_pointer alist)
- {
- /* fixup alist, return it (caller has to make sure it is reflected in its object) */
- /*
- (let ((old-val (assoc key alist)))
- (if old-val
- (progn
- (set-cdr! old-val new-val)
- alist)
- (cons (cons key new-val) alist)))
- */
- Xen old_val;
- old_val = s7_assoc(sc, key, alist); /* returns #f if nothing found */
- if (old_val == s7_f(sc))
- return(s7_cons(sc, s7_cons(sc, key, val), alist));
- s7_set_cdr(old_val, val);
- return(alist);
- }
-
-
- Xen xen_assoc(s7_scheme *sc, Xen key, Xen alist)
- {
- Xen val;
- val = s7_assoc(sc, key, alist);
- if (val != s7_f(sc))
- return(s7_cdr(val));
- return(s7_f(sc));
- }
-
-
- /* add various file functions that everyone else implements */
-
- #ifndef _MSC_VER
- #include <unistd.h>
- #include <sys/time.h>
- #endif
-
- #include <sys/stat.h>
- #include <fcntl.h>
-
-
- static Xen g_getpid(void)
- {
- #define H_getpid "(getpid) returns the current job's process id"
- return(C_int_to_Xen_integer((int)getpid()));
- }
-
-
- #if (!WITH_SYSTEM_EXTRAS)
- static bool file_probe(const char *arg)
- {
- #ifndef _MSC_VER
- return(access(arg, F_OK) == 0);
- #else
- int fd;
- #ifdef O_NONBLOCK
- fd = open(arg, O_RDONLY, O_NONBLOCK);
- #else
- fd = open(arg, O_RDONLY, 0);
- #endif
- if (fd == -1) return(false);
- close(fd);
- return(true);
- #endif
- }
-
-
- static Xen g_file_exists_p(Xen name)
- {
- #define H_file_exists_p "(file-exists? filename): #t if the file exists"
- Xen_check_type(Xen_is_string(name), name, 1, "file-exists?", "a string");
- return(C_bool_to_Xen_boolean(file_probe(Xen_string_to_C_string(name))));
- }
-
-
- static bool is_directory(const char *filename)
- {
- #if (defined(_MSC_VER) || __CYGWIN__)
- return(false);
- #else
- #ifdef S_ISDIR
- struct stat statbuf;
- return((stat(filename, &statbuf) >= 0) &&
- (S_ISDIR(statbuf.st_mode)));
- return(false);
- #endif
- #endif
- }
-
- static Xen g_is_directory(Xen name)
- {
- #define H_is_directory "(directory? filename): #t if filename names a directory"
- Xen_check_type(Xen_is_string(name), name, 1, "directory?", "a string");
- return(C_bool_to_Xen_boolean(is_directory(Xen_string_to_C_string(name)))); /* snd-file.c l 84 */
- }
-
- static Xen g_delete_file(Xen name)
- {
- #define H_delete_file "(delete-file filename): deletes the file"
- Xen_check_type(Xen_is_string(name), name, 1, "delete-file", "a string");
- return(C_bool_to_Xen_boolean(unlink(Xen_string_to_C_string(name))));
- }
-
-
- static Xen g_system(Xen command)
- {
- #define H_system "(system command): execute command"
- Xen_check_type(Xen_is_string(command), command, 1, "system", "a string");
- return(C_int_to_Xen_integer(system(Xen_string_to_C_string(command))));
- }
-
-
- static Xen g_s7_getenv(Xen var) /* "g_getenv" is in use in glib! */
- {
- #define H_getenv "(getenv var): return value of environment variable var"
- Xen_check_type(Xen_is_string(var), var, 1, "getenv", "a string");
- return(C_string_to_Xen_string(getenv(Xen_string_to_C_string(var))));
- }
- #endif
-
-
-
- #ifdef _MSC_VER
- #include <direct.h>
- #endif
-
- static Xen g_getcwd(void)
- {
- #define H_getcwd "(getcwd) returns the name of the current working directory"
- char *buf;
- Xen result = Xen_false;
- buf = (char *)calloc(1024, sizeof(char));
- #ifdef _MSC_VER
- if (_getcwd(buf, 1024) != NULL)
- #else
- if (getcwd(buf, 1024) != NULL)
- #endif
- result = C_string_to_Xen_string(buf);
- free(buf);
- return(result);
- }
-
-
- static Xen g_strftime(Xen format, Xen tm)
- {
- #define H_strftime "(strftime format time) returns a string describing the time: (strftime \"%d-%b %H:%M %Z\" (localtime (current-time)))"
- char *buf;
- Xen result;
- const struct tm *p;
-
- Xen_check_type(Xen_is_string(format), format, 1, "strftime", "a string");
- Xen_check_type(Xen_is_wrapped_c_pointer(tm), tm, 2, "strftime", "a localtime struct");
-
- p = (const struct tm *)Xen_unwrap_C_pointer(tm);
- Xen_check_type(p != NULL, tm, 2, "strftime", "a localtime struct");
-
- buf = (char *)calloc(1024, sizeof(char));
- strftime(buf, 1024, Xen_string_to_C_string(format), p);
- result = C_string_to_Xen_string(buf);
- free(buf);
-
- return(result);
- }
-
-
- /* (format #f ";~A~%" (strftime "%d-%b %H:%M %Z" (localtime (current-time)))) */
- /* these two need to be compatible with g_file_write_date in snd-file.c */
-
- static Xen g_localtime(Xen tm)
- {
- #define H_localtime "(localtime tm) breaks up tm into something suitable for strftime"
- time_t rtime;
- rtime = (time_t)Xen_ulong_to_C_ulong(tm);
- return(Xen_wrap_C_pointer(localtime((time_t *)(&rtime))));
- }
-
-
- static Xen g_current_time(void)
- {
- time_t curtime;
- #define H_current_time "(current-time) returns the current time (for localtime and strftime)"
- curtime = time(NULL);
- return(C_ulong_to_Xen_ulong(curtime));
- }
-
-
- static Xen g_tmpnam(void)
- {
- #define H_tmpnam "(tmpnam) returns a new (hopefully unused) temporary file name"
- #define BUFFER_SIZE 512
- static int file_ctr = 0;
- char *str, *tmpdir = NULL;
- Xen result;
-
- str = (char *)calloc(BUFFER_SIZE, sizeof(char));
- tmpdir = xen_strdup(getenv("TMPDIR"));
-
- #ifdef P_tmpdir
- if (tmpdir == NULL)
- tmpdir = xen_strdup(P_tmpdir); /* /usr/include/stdio.h */
- if (tmpdir)
- {
- int len;
- len = strlen(tmpdir);
- if (len > 0)
- {
- if (tmpdir[len - 1] == '/')
- tmpdir[len - 1] = 0;
- }
- else
- {
- free(tmpdir);
- tmpdir = xen_strdup(".");
- }
- }
- #else
- if (tmpdir == NULL) tmpdir = xen_strdup("/tmp");
- #endif
-
- snprintf(str, BUFFER_SIZE, "%s/xen_%d_%d", tmpdir, (int)getpid(), file_ctr++);
- if (tmpdir) free(tmpdir);
- result = C_string_to_Xen_string(str);
- free(str);
- return(result);
- }
-
-
- static Xen g_ftell(Xen fd)
- {
- return(C_int_to_Xen_integer(lseek(Xen_integer_to_C_int(fd), 0, SEEK_CUR)));
- }
-
-
- static Xen g_gc_off(void)
- {
- #define H_gc_off "(" S_gc_off ") turns off garbage collection"
- s7_gc_on(s7, false);
- return(Xen_false);
- }
-
-
- static Xen g_gc_on(void)
- {
- #define H_gc_on "(" S_gc_on ") turns on garbage collection"
- s7_gc_on(s7, true);
- return(Xen_false);
- }
-
-
-
- Xen_wrap_no_args(g_getpid_w, g_getpid)
- #if (!WITH_SYSTEM_EXTRAS)
- Xen_wrap_1_arg(g_file_exists_p_w, g_file_exists_p)
- Xen_wrap_1_arg(g_is_directory_w, g_is_directory)
- Xen_wrap_1_arg(g_delete_file_w, g_delete_file)
- Xen_wrap_1_arg(g_s7_getenv_w, g_s7_getenv)
- Xen_wrap_1_arg(g_system_w, g_system)
- #endif
- Xen_wrap_no_args(g_getcwd_w, g_getcwd)
- Xen_wrap_2_args(g_strftime_w, g_strftime)
- Xen_wrap_1_arg(g_localtime_w, g_localtime)
- Xen_wrap_no_args(g_current_time_w, g_current_time)
- Xen_wrap_no_args(g_tmpnam_w, g_tmpnam)
- Xen_wrap_1_arg(g_ftell_w, g_ftell)
-
- Xen_wrap_no_args(g_gc_off_w, g_gc_off)
- Xen_wrap_no_args(g_gc_on_w, g_gc_on)
-
- #if ENABLE_WEBSERVER
- #if USE_MOTIF
- #include "snd.h"
- static idle_func_t called_periodically(any_pointer_t pet)
- {
- s7webserver_call_very_often();
- return(BACKGROUND_CONTINUE);
- }
- #endif
- #endif
-
-
- s7_scheme *s7_xen_initialize(s7_scheme *sc)
- {
- s7_pointer i, b, p, s;
-
- xen_s7_repl_prompt = xen_strdup("> ");
- if (!sc)
- {
- s7 = s7_init();
- if (!s7)
- {
- fprintf(stderr, "Can't initialize s7!\n");
- return(NULL);
- }
- #if ENABLE_WEBSERVER
- {
- s7webserver_t *s7webserver;
- s7webserver = s7webserver_create(s7, 6080, true);
- if (!s7webserver)
- fprintf(stderr, "Unable to start web server. Port 6080 may be in use\n");
- else fprintf(stdout, "Started s7 webserver at port %d\n", s7webserver_get_portnumber(s7webserver));
- #if USE_MOTIF
- BACKGROUND_ADD(called_periodically, NULL);
- #endif
- }
- #endif
- }
- else s7 = sc;
-
- i = s7_make_symbol(s7, "integer?");
- b = s7_make_symbol(s7, "boolean?");
- p = s7_make_symbol(s7, "pair?");
- s = s7_make_symbol(s7, "string?");
-
- xen_false = s7_f(s7);
- xen_true = s7_t(s7);
- xen_nil = s7_nil(s7);
- xen_undefined = s7_undefined(s7);
- xen_zero = s7_make_integer(s7, 0);
- s7_gc_protect(s7, xen_zero);
-
- Xen_define_typed_procedure("getpid", g_getpid_w, 0, 0, 0, H_getpid, s7_make_signature(s7, 1, i));
- #if (!WITH_SYSTEM_EXTRAS)
- Xen_define_typed_procedure("file-exists?", g_file_exists_p_w, 1, 0, 0, H_file_exists_p, s7_make_signature(s7, 2, b, s));
- Xen_define_typed_procedure("directory?", g_is_directory_w, 1, 0, 0, H_is_directory, s7_make_signature(s7, 2, b, s));
- Xen_define_typed_procedure("delete-file", g_delete_file_w, 1, 0, 0, H_delete_file, s7_make_signature(s7, 2, b, s));
- Xen_define_typed_procedure("getenv", g_s7_getenv_w, 1, 0, 0, H_getenv, s7_make_signature(s7, 2, s, s));
- Xen_define_typed_procedure("system", g_system_w, 1, 0, 0, H_system, s7_make_signature(s7, 2, i, s));
- #endif
- Xen_define_typed_procedure("getcwd", g_getcwd_w, 0, 0, 0, H_getcwd, s7_make_signature(s7, 1, s));
- Xen_define_typed_procedure("strftime", g_strftime_w, 2, 0, 0, H_strftime, s7_make_signature(s7, 3, s, s, p));
- Xen_define_typed_procedure("tmpnam", g_tmpnam_w, 0, 0, 0, H_tmpnam, s7_make_signature(s7, 1, s));
- Xen_define_typed_procedure("localtime", g_localtime_w, 1, 0, 0, H_localtime, s7_make_signature(s7, 2, p, i));
- Xen_define_typed_procedure("current-time", g_current_time_w, 0, 0, 0, H_current_time, s7_make_signature(s7, 1, i));
- Xen_define_typed_procedure("ftell", g_ftell_w, 1, 0, 0, "(ftell fd): lseek", s7_make_signature(s7, 2, i, i));
- Xen_define_typed_procedure(S_gc_off, g_gc_off_w, 0, 0, 0, H_gc_off, s7_make_signature(s7, 1, b));
- Xen_define_typed_procedure(S_gc_on, g_gc_on_w, 0, 0, 0, H_gc_on, s7_make_signature(s7, 1, b));
-
- Xen_eval_C_string("(define (hook-push hook func) \n\
- \"(hook-push hook func) adds func to hook's function list\" \n\
- (if (not (member func (hook-functions hook) eq?)) (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-clear hook) (set! (hook-functions hook) ()))");
- Xen_eval_C_string("(define (hook-remove 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)))))))");
-
- #if (!DISABLE_DEPRECATED)
- 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))");
- #endif
- Xen_eval_C_string("(define-macro (while whether . body) `(do () ((not ,whether)) ,@body))");
- Xen_eval_C_string("(define (identity x) \"return arg\" x)");
-
- return(s7);
- }
-
-
- void xen_initialize(void)
- {
- s7_xen_initialize(NULL);
- }
- #endif
-
-
-
-
- /* ------------------------------ NONE OF THE ABOVE ------------------------------ */
-
- #if (!HAVE_EXTENSION_LANGUAGE)
-
- char *xen_version(void)
- {
- char *buf;
- buf = (char *)calloc(64, sizeof(char));
- #if HAVE_SNPRINTF
- snprintf(buf, 64, "no extension language");
- #else
- sprintf(buf, "no extension language");
- #endif
- return(buf);
- }
-
-
- void xen_repl(int argc, char **argv)
- {
- }
-
-
- void xen_initialize(void)
- {
- }
-
-
- void xen_gc_mark(Xen val)
- {
- }
-
-
- void xen_no_ext_lang_check_args(const char *name, int args, int req_args, int opt_args, int rst_args)
- {
- if (args > 0) /* nargify -- all are required */
- {
- if (req_args != args)
- fprintf(stderr, "%s: %d required args, but req: %d (opt: %d, rst: %d)\n", name, args, req_args, opt_args, rst_args);
- if (opt_args != 0)
- fprintf(stderr, "%s: all args required, but opt: %d (rst: %d)\n", name, opt_args, rst_args);
- if (rst_args != 0)
- fprintf(stderr, "%s: all args required, but rst: %d\n", name, rst_args);
- }
- else
- {
- if (args != -100) /* vargify -- any ok */
- {
- args = -args;
- if (rst_args == 0)
- {
- if (req_args + opt_args != args)
- fprintf(stderr, "%s: total args: %d, but req: %d and opt: %d\n", name, args, req_args, opt_args);
- }
- else
- {
- if (req_args + opt_args > args)
- fprintf(stderr, "%s: has :rest, but req: %d and opt: %d , whereas total: %d\n", name, req_args, opt_args, args);
- }
- }
- }
- }
-
- #endif
|