diff --git a/src/modules/Perl/perlmod.c b/src/modules/Perl/perlmod.c index d437376b38b42022a1d84111cafced85e51ca1d9..f7d082d1d04058fc7c8b9f165404c1d7d2bc5608 100644 --- a/src/modules/Perl/perlmod.c +++ b/src/modules/Perl/perlmod.c @@ -1,4 +1,4 @@ -/* $Id: perlmod.c,v 1.15 2000/03/27 00:17:06 grubba Exp $ */ +/* $Id: perlmod.c,v 1.16 2000/05/16 12:38:54 leif Exp $ */ #include "builtin_functions.h" #include "global.h" @@ -11,19 +11,44 @@ #include "mapping.h" #include "perl_machine.h" - /* this is just for debugging */ -#define _sv_2mortal(x) (x) - #ifdef HAVE_PERL +/* #define PERL_560 1 */ + #include <EXTERN.h> #include <perl.h> +#ifdef USE_THREADS +/* #error Threaded Perl not supported. */ +#endif + +#define MY_XS 1 +#undef MY_XS + +/* #define PIKE_PERLDEBUG */ + +#ifdef MY_XS +EXTERN_C void boot_DynaLoader(); + +static void xs_init() +{ char *file = __FILE__; + dXSUB_SYS; +#ifdef PIKE_PERLDEBUG + fprintf(stderr, "[my xs_init]\n"); +#endif + newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); +} +#endif + + /* Do not redefine my malloc macro you stupid Perl! */ #include "dmalloc.h" + /* this is just for debugging */ +#define _sv_2mortal(x) (sv_2mortal(x)) + static int num_perl_interpreters=0; -DEFINE_MUTEX(perl_running); +DEFINE_MUTEX(perlrunning); #ifdef MULTIPLICITY #endif @@ -36,11 +61,14 @@ struct perlmod_storage struct array *argv_strings; int constructed, parsed; int array_size_limit; - PerlInterpreter *my_perl; + PerlInterpreter *perl; }; -#define THIS ((struct perlmod_storage *)(fp->current_storage)) -#define PERL THIS->my_perl +#define _THIS ((struct perlmod_storage *)(Pike_fp->current_storage)) + +#ifdef PERL_560 +#define my_perl PERL +#endif /* since both Perl and Pike likes to use "sp" as a stack pointer, * let's define some Pike macros as functions... @@ -50,15 +78,21 @@ static void _push_float(float f) { push_float(f);} static void _push_string(struct pike_string *s) { push_string(s);} static void _push_array(struct array *a) { push_array(a);} static void _pop_n_elems(int n) { pop_n_elems(n);} -static struct svalue *_pikesp() { return Pike_sp;} -static void _pike_pop() { --sp;} +static void _pike_pop() { --Pike_sp;} #undef sp +#define BLOCKING 1 + #ifndef BLOCKING #define MT_PERMIT THREADS_ALLOW(); mt_lock(&perl_running); #define MT_FORBID mt_unlock(&perl_running); THREADS_DISALLOW(); +#else + +#define MT_PERMIT ; +#define MT_FORBID ; + #endif /* utility function: push a zero_type zero */ @@ -116,86 +150,157 @@ static void _pikepush_sv(SV *sv) _push_int(0); } +static int _perl_parse(struct perlmod_storage *ps, + int argc, char *argv[], char *envp[]) +{ int result; +#ifndef MY_XS + extern void xs_init(void); +#endif +#ifdef PIKE_PERLDEBUG + fprintf(stderr, "[_perl_parse, argc=%d]\n", argc); +#endif + + if (!ps) + error("Internal error: no Perl storage allocated.\n"); + if (!ps->perl) + error("Internal error: no Perl interpreter allocated.\n"); + if (!ps->constructed) + error("Internal error: Perl interpreter not constructed.\n"); + if (!envp && !ps->env) + { /* Copy environment data, since Perl may wish to modify it. */ + + INT32 d; + int env_block_size=0; + char *env_blockp; + +#ifdef DECLARE_ENVIRON + extern char **environ; +#endif + + for(d=0;environ[d];d++) + env_block_size+=strlen(environ[d])+1; + + ps->env_block=xalloc(env_block_size); + ps->env=(char **)xalloc(sizeof(char *)*(d+1)); + + env_blockp = ps->env_block; + + for(d=0;environ[d];d++) + { + int l=strlen(environ[d]); + ps->env[d]=env_blockp; + MEMCPY(env_blockp,environ[d],l+1); + env_blockp+=l+1; + } + +#ifdef PIKE_DEBUG + if(env_blockp - ps->env_block > env_block_size) + fatal("Arglebargle glop-glyf.\n"); +#endif + + ps->env[d]=0; + } + MT_PERMIT; + result = perl_parse(ps->perl, xs_init, argc, argv, envp ? envp : ps->env); + MT_FORBID; + ps->parsed += 1; + return result; +} + +static char *dummyargv[] = { "perl", "-e", "1", 0 }; static void init_perl_glue(struct object *o) -{ PerlInterpreter *p; +{ struct perlmod_storage *ps = _THIS; #ifdef PIKE_PERLDEBUG fprintf(stderr, "[init_perl_glue]\n"); #endif - THIS->argv = 0; - THIS->env = 0; - THIS->env_block = 0; - THIS->argv_strings = 0; - THIS->constructed = 0; - THIS->parsed = 0; - THIS->array_size_limit = 500; + ps->argv = 0; + ps->env = 0; + ps->env_block = 0; + ps->argv_strings = 0; + ps->constructed = 0; + ps->parsed = 0; + ps->array_size_limit = 500; #ifndef MULTIPLICITY if(num_perl_interpreters>0) { - PERL=0; + ps->perl=0; +#ifdef PIKE_PERLDEBUG fprintf(stderr,"num_perl_interpreters=%d\n",num_perl_interpreters); +#endif /* error("Perl: There can be only one!\n"); */ return; } #endif MT_PERMIT; - p=perl_alloc(); + ps->perl = perl_alloc(); + PL_perl_destruct_level=2; MT_FORBID; - PERL=p; - if(p) num_perl_interpreters++; + if(ps->perl) num_perl_interpreters++; + +/* #define SPECIAL_PERL_DEBUG */ +#ifdef SPECIAL_PERL_DEBUG + if (!ps->constructed) + { fprintf(stderr, "[SpecialDebug: early perl_construct]\n"); + perl_construct(ps->perl); + ps->constructed = 1; + } + if (!ps->parsed) + { fprintf(stderr, "[SpecialDebug: early perl_parse]\n"); + perl_parse(ps->perl, xs_init, 3, dummyargv, NULL); + ps->parsed = 1; + } +#endif } static void _free_arg_and_env() -{ if(THIS->argv) - { - free((char *)THIS->argv); - THIS->argv=0; +{ struct perlmod_storage *ps = _THIS; + + if (ps->argv) + { free((char *)ps->argv); + ps->argv=0; } - if(THIS->argv_strings) - { - free_array(THIS->argv_strings); - THIS->argv_strings=0; + + if (ps->argv_strings) + { free_array(ps->argv_strings); + ps->argv_strings=0; } - if(THIS->env) - { - free((char *)THIS->env); - THIS->env=0; + + if (ps->env) + { free((char *)ps->env); + ps->env=0; } - if(THIS->env_block) - { - free((char *)THIS->env_block); - THIS->env_block=0; + + if (ps->env_block) + { free((char *)ps->env_block); + ps->env_block=0; } } static void exit_perl_glue(struct object *o) -{ +{ struct perlmod_storage *ps = _THIS; #ifdef PIKE_PERLDEBUG fprintf(stderr, "[exit_perl_glue]\n"); #endif - if(PERL) + if (ps->perl) { - struct perlmod_storage *storage=THIS; - - MT_PERMIT; - if(storage->constructed) + if (ps->constructed) { - if (!storage->parsed) - { static char *dummyargv[] = { "perl", "-e", "1", 0 }; - extern void xs_init(void); - /* this should be unnecessary, but for some reason, some + if (!ps->parsed) + { /* This should be unnecessary, but for some reason, some * perl5.004 installations dump core if we don't do this. */ - perl_parse(storage->my_perl, xs_init, 3, dummyargv, NULL); + _perl_parse(ps, 3, dummyargv, NULL); } - perl_destruct(storage->my_perl); - storage->constructed=0; + perl_destruct(ps->perl); + ps->constructed = 0; } - perl_free(storage->my_perl); + MT_PERMIT; + perl_free(ps->perl); MT_FORBID; num_perl_interpreters--; } @@ -203,20 +308,26 @@ static void exit_perl_glue(struct object *o) } static void perlmod_create(INT32 args) -{ PerlInterpreter *p=PERL; - struct perlmod_storage *storage=THIS; +{ struct perlmod_storage *ps = _THIS; #ifdef PIKE_PERLDEBUG fprintf(stderr, "[perlmod_create, %d args]\n", args); +#ifdef MY_XS + fprintf(stderr, "[has MY_XS]\n"); +#endif #endif if (args != 0) error("Perl->create takes no arguments."); - if(!p) error("No perl interpreter available.\n"); + if (!ps || !ps->perl) error("No perl interpreter available.\n"); MT_PERMIT; - if(!storage->constructed) - { perl_construct(p); - storage->constructed++; + if(!ps->constructed) + { perl_construct(ps->perl); + ps->constructed++; + } + if (!ps->parsed) + { + _perl_parse(ps, 3, dummyargv, NULL); } MT_FORBID; pop_n_elems(args); @@ -225,18 +336,19 @@ static void perlmod_create(INT32 args) static void perlmod_parse(INT32 args) { - extern void xs_init(void); int e; struct mapping *env_mapping=0; - PerlInterpreter *p=PERL; - struct perlmod_storage *storage=THIS; + struct perlmod_storage *ps = _THIS; +#ifndef MY_XS + extern void xs_init(void); +#endif #ifdef PIKE_PERLDEBUG fprintf(stderr, "[perlmod_parse, %d args]\n", args); #endif check_all_args("Perl->parse",args,BIT_ARRAY, BIT_MAPPING|BIT_VOID, 0); - if(!p) error("No perl interpreter available.\n"); + if(!ps->perl) error("No perl interpreter available.\n"); switch(args) { @@ -250,25 +362,25 @@ static void perlmod_parse(INT32 args) error("Bad argument 2 to Perl->create().\n"); case 1: - if (THIS->argv_strings || THIS->env_block) + if (_THIS->argv_strings || _THIS->env_block) { /* if we have already setup args/env, free the old values now */ _free_arg_and_env(); } - THIS->argv_strings = Pike_sp[-args].u.array; - add_ref(THIS->argv_strings); - array_fix_type_field(THIS->argv_strings); + ps->argv_strings = Pike_sp[-args].u.array; + add_ref(ps->argv_strings); + array_fix_type_field(ps->argv_strings); - if(THIS->argv_strings->size<2) + if(ps->argv_strings->size<2) error("Perl: Too few elements in argv array.\n"); - if(THIS->argv_strings->type_field & ~BIT_STRING) + if(ps->argv_strings->type_field & ~BIT_STRING) error("Bad argument 1 to Perl->parse().\n"); } - THIS->argv=(char **)xalloc(sizeof(char *)*THIS->argv_strings->size); - for(e=0;e<THIS->argv_strings->size;e++) - THIS->argv[e]=ITEM(THIS->argv_strings)[e].u.string->str; + ps->argv=(char **)xalloc(sizeof(char *)*ps->argv_strings->size); + for(e=0;e<ps->argv_strings->size;e++) + ps->argv[e]=ITEM(ps->argv_strings)[e].u.string->str; if(env_mapping) { @@ -279,14 +391,14 @@ static void perlmod_parse(INT32 args) MAPPING_LOOP(env_mapping) env_block_size+=k->ind.u.string->len+k->val.u.string->len+2; - THIS->env_block=xalloc(env_block_size); - THIS->env=(char **)xalloc(sizeof(char *)*(m_sizeof(env_mapping)+1)); + ps->env_block=xalloc(env_block_size); + ps->env=(char **)xalloc(sizeof(char *)*(m_sizeof(env_mapping)+1)); - env_blockp=THIS->env_block; + env_blockp = ps->env_block; d=0; MAPPING_LOOP(env_mapping) { - THIS->env[d++]=env_blockp; + ps->env[d++]=env_blockp; MEMCPY(env_blockp,k->ind.u.string->str,k->ind.u.string->len); env_blockp+=k->ind.u.string->len; @@ -297,55 +409,12 @@ static void perlmod_parse(INT32 args) *(env_blockp++)=0; } - THIS->env[d]=0; - } - else - { - /* Perl likes to be able to write in the environment block, - * give it it's own copy to protect ourselves.. /Hubbe - */ - INT32 d; - int env_block_size=0; - char *env_blockp; - -#ifdef DECLARE_ENVIRON - extern char **environ; -#endif - - for(d=0;environ[d];d++) - env_block_size+=strlen(environ[d])+1; - - THIS->env_block=xalloc(env_block_size); - THIS->env=(char **)xalloc(sizeof(char *)*(d+1)); - - env_blockp=THIS->env_block; - - for(d=0;environ[d];d++) - { - int l=strlen(environ[d]); - THIS->env[d]=env_blockp; - MEMCPY(env_blockp,environ[d],l+1); - env_blockp+=l+1; - } - -#ifdef PIKE_DEBUG - if(env_blockp - THIS->env_block > env_block_size) - fatal("Arglebargle glop-glyf.\n"); -#endif - - THIS->env[d]=0; + ps->env[d]=0; } - + else ps->env = 0; - THIS->parsed++; + e = _perl_parse(ps, ps->argv_strings->size, ps->argv, ps->env); - MT_PERMIT; - e=perl_parse(p, - xs_init, - storage->argv_strings->size, - storage->argv, - storage->env); - MT_FORBID; pop_n_elems(args); push_int(e); } @@ -353,62 +422,74 @@ static void perlmod_parse(INT32 args) static void perlmod_run(INT32 args) { INT32 i; - PerlInterpreter *p=PERL; - if(!p) error("No perl interpreter available.\n"); + struct perlmod_storage *ps = _THIS; + + if(!ps->perl) error("No perl interpreter available.\n"); pop_n_elems(args); - if(!THIS->constructed || !THIS->parsed) + if(!_THIS->constructed || !_THIS->parsed) error("No Perl program loaded (run() called before parse()).\n"); MT_PERMIT; - i=perl_run(p); + i=perl_run(ps->perl); MT_FORBID; push_int(i); } static void _perlmod_eval(INT32 args, int perlflags) -{ PerlInterpreter *p = PERL; - struct pike_string *arg1; - struct perlmod_storage *storage = THIS; +{ struct pike_string *firstarg; + struct perlmod_storage *ps = _THIS; int i, n; -#define sp _perlsp +// #define sp _perlsp dSP; - if (!p) error("Perl interpreter not available.\n"); + if (!ps->perl) error("Perl interpreter not available.\n"); check_all_args("Perl->eval", args, BIT_STRING, 0); - arg1 = _pikesp()[-args].u.string; + firstarg = Pike_sp[-args].u.string; ENTER; SAVETMPS; PUSHMARK(sp); PUTBACK; -#undef sp - MT_PERMIT; +// #undef sp - if (!storage->parsed) - { static char *dummyargv[] = { "perl", "-e", "1", 0 }; + if (!ps->parsed) + { +#if 0 + _perl_parse(ps, 3, dummyargv, NULL); +#else +#ifndef MY_XS extern void xs_init(void); - perl_parse(p, xs_init, 3, dummyargv, NULL); - storage->parsed++; +#endif + perl_parse(ps->perl, xs_init, 3, dummyargv, NULL); +#endif } - n = perl_eval_sv(newSVpv(arg1->str, arg1->len), perlflags | G_EVAL); + MT_PERMIT; + +/* perl5.6.0 testing: newSVpv((const char *) "ABC", 3); */ + + n = perl_eval_sv(newSVpv((firstarg->str), + (firstarg->len)), + perlflags | G_EVAL); MT_FORBID; _pop_n_elems(args); -#define sp _perlsp +// #define sp _perlsp SPAGAIN; - if (SvTRUE(GvSV(errgv))) + if (SvTRUE(GvSV(PL_errgv))) { char errtmp[256]; memset(errtmp, 0, sizeof(errtmp)); strcpy(errtmp, "Error from Perl: "); - strncpy(errtmp+strlen(errtmp), SvPV(GvSV(errgv), na), 254-strlen(errtmp)); + strncpy(errtmp+strlen(errtmp), + SvPV(GvSV(PL_errgv), PL_na), + 254-strlen(errtmp)); POPs; PUTBACK; FREETMPS; LEAVE; error(errtmp); @@ -427,7 +508,7 @@ static void _perlmod_eval(INT32 args, int perlflags) else _push_zerotype(); PUTBACK; FREETMPS; LEAVE; -#undef sp +// #undef sp } static void perlmod_eval(INT32 args) @@ -437,22 +518,22 @@ static void perlmod_eval_list(INT32 args) { _perlmod_eval(args, G_ARRAY); } static void _perlmod_call(INT32 args, int perlflags) -{ PerlInterpreter *p = PERL; +{ struct perlmod_storage *ps = _THIS; int i, n; char *pv; -#define sp _perlsp +// #define sp _perlsp dSP; #ifdef PIKE_PERLDEBUG fprintf(stderr, "[perlmod_call: args=%d]\n", args); #endif - if (!p) error("No perl interpreter available.\n"); + if (!ps->perl) error("No perl interpreter available.\n"); if (args < 1) error("Too few arguments.\n"); if (args > 201) error("Too many arguments.\n"); - if (_pikesp()[-args].type != T_STRING || - _pikesp()[-args].u.string->size_shift) + if (Pike_sp[-args].type != T_STRING || + Pike_sp[-args].u.string->size_shift) error("bad Perl function name (must be an 8-bit string)"); ENTER; @@ -460,7 +541,7 @@ static void _perlmod_call(INT32 args, int perlflags) PUSHMARK(sp); for(n = 1; n < args; ++n) - { struct svalue *s = &(_pikesp()[n-args]); + { struct svalue *s = &(Pike_sp[n-args]); char *msg; switch (s->type) { case T_INT: @@ -495,23 +576,25 @@ static void _perlmod_call(INT32 args, int perlflags) PUTBACK; pv = Pike_sp[-args].u.string->str; -#undef sp +// #undef sp MT_PERMIT; n = perl_call_pv(pv, perlflags); MT_FORBID; -#define sp _perlsp +// #define sp _perlsp _pop_n_elems(args); SPAGAIN; - if (SvTRUE(GvSV(errgv))) + if (SvTRUE(GvSV(PL_errgv))) { char errtmp[256]; memset(errtmp, 0, sizeof(errtmp)); strcpy(errtmp, "Error from Perl: "); - strncpy(errtmp+strlen(errtmp), SvPV(GvSV(errgv), na), 254-strlen(errtmp)); + strncpy(errtmp+strlen(errtmp), + SvPV(GvSV(PL_errgv), PL_na), + 254-strlen(errtmp)); POPs; PUTBACK; FREETMPS; LEAVE; error(errtmp); @@ -525,7 +608,7 @@ static void _perlmod_call(INT32 args, int perlflags) if (!(perlflags & G_ARRAY) && n > 1) while (n > 1) --n, POPs; - if (n > THIS->array_size_limit) + if (n > ps->array_size_limit) { PUTBACK; FREETMPS; LEAVE; error("Perl function returned too many values.\n"); } @@ -542,7 +625,7 @@ static void _perlmod_call(INT32 args, int perlflags) _push_zerotype(); PUTBACK; FREETMPS; LEAVE; -#undef sp +// #undef sp } static void perlmod_call_list(INT32 args) @@ -559,7 +642,7 @@ static void _perlmod_varop(INT32 args, int op, int type) wanted_args = type == 'S' ? 1 : 2; if (op == 'W') ++wanted_args; - if (!(PERL)) error("No Perl interpreter available.\n"); + if (!(_THIS->perl)) error("No Perl interpreter available.\n"); if (args != wanted_args) error("Wrong number of arguments.\n"); if (Pike_sp[-args].type != T_STRING || @@ -649,7 +732,7 @@ static void perlmod_get_whole_array(INT32 args) if (!av) error("Interal error: perl_get_av() returned NULL.\n"); n = av_len(av) + 1; - if (n > THIS->array_size_limit) + if (n > _THIS->array_size_limit) error("The array is larger than array_size_limit.\n"); arr = allocate_array(n); @@ -674,7 +757,7 @@ static void perlmod_get_hash_keys(INT32 args) /* count number of elements in hash */ for(n = 0, hv_iterinit(hv); (he = hv_iternext(hv)); ++n); - if (n > THIS->array_size_limit) + if (n > _THIS->array_size_limit) error("The array is larger than array_size_limit.\n"); arr = allocate_array(n); @@ -693,13 +776,13 @@ static void perlmod_array_size_limit(INT32 args) case 1: if (Pike_sp[-args].type != T_INT || Pike_sp[-args].u.integer < 1) error("Argument must be a integer in range 1 to 2147483647."); - THIS->array_size_limit = Pike_sp[-args].u.integer; + _THIS->array_size_limit = Pike_sp[-args].u.integer; break; default: error("Wrong number of arguments.\n"); } pop_n_elems(args); - _push_int(THIS->array_size_limit); + _push_int(_THIS->array_size_limit); } void pike_module_init(void) @@ -708,8 +791,6 @@ void pike_module_init(void) fprintf(stderr, "[perl: module init]\n"); #endif - perl_destruct_level=1; - start_new_program(); ADD_STORAGE(struct perlmod_storage); /* function(void:int) */ @@ -793,6 +874,11 @@ void pike_module_exit(void) } #else /* HAVE_PERL */ + +#ifdef ERROR_IF_NO_PERL +#error "No Perl!" +#endif + void pike_module_init(void) {} void pike_module_exit(void) {} #endif