| 1 | #define INCL_DOSPROCESS
|
|---|
| 2 | #define INCL_DOSSEMAPHORES
|
|---|
| 3 | #define INCL_DOSMODULEMGR
|
|---|
| 4 | #define INCL_DOSMISC
|
|---|
| 5 | #define INCL_DOSEXCEPTIONS
|
|---|
| 6 | #define INCL_DOSERRORS
|
|---|
| 7 | #define INCL_REXXSAA
|
|---|
| 8 | #include <os2.h>
|
|---|
| 9 |
|
|---|
| 10 | /*
|
|---|
| 11 | * "The Road goes ever on and on, down from the door where it began."
|
|---|
| 12 | */
|
|---|
| 13 |
|
|---|
| 14 | #ifdef OEMVS
|
|---|
| 15 | #ifdef MYMALLOC
|
|---|
| 16 | /* sbrk is limited to first heap segement so make it big */
|
|---|
| 17 | #pragma runopts(HEAP(8M,500K,ANYWHERE,KEEP,8K,4K) STACK(,,ANY,) ALL31(ON))
|
|---|
| 18 | #else
|
|---|
| 19 | #pragma runopts(HEAP(2M,500K,ANYWHERE,KEEP,8K,4K) STACK(,,ANY,) ALL31(ON))
|
|---|
| 20 | #endif
|
|---|
| 21 | #endif
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 | #include "EXTERN.h"
|
|---|
| 25 | #include "perl.h"
|
|---|
| 26 |
|
|---|
| 27 | static void xs_init (pTHX);
|
|---|
| 28 | static PerlInterpreter *my_perl;
|
|---|
| 29 |
|
|---|
| 30 | ULONG PERLEXPORTALL(PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr);
|
|---|
| 31 | ULONG PERLDROPALL(PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr);
|
|---|
| 32 | ULONG PERLDROPALLEXIT(PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr);
|
|---|
| 33 |
|
|---|
| 34 | #if defined (__MINT__) || defined (atarist)
|
|---|
| 35 | /* The Atari operating system doesn't have a dynamic stack. The
|
|---|
| 36 | stack size is determined from this value. */
|
|---|
| 37 | long _stksize = 64 * 1024;
|
|---|
| 38 | #endif
|
|---|
| 39 |
|
|---|
| 40 | /* Register any extra external extensions */
|
|---|
| 41 |
|
|---|
| 42 | /* Do not delete this line--writemain depends on it */
|
|---|
| 43 | EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
|
|---|
| 44 |
|
|---|
| 45 | static void
|
|---|
| 46 | xs_init(pTHX)
|
|---|
| 47 | {
|
|---|
| 48 | char *file = __FILE__;
|
|---|
| 49 | dXSUB_SYS;
|
|---|
| 50 | newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
|
|---|
| 51 | }
|
|---|
| 52 |
|
|---|
| 53 | int perlos2_is_inited;
|
|---|
| 54 |
|
|---|
| 55 | static void
|
|---|
| 56 | init_perlos2(void)
|
|---|
| 57 | {
|
|---|
| 58 | /* static char *env[1] = {NULL}; */
|
|---|
| 59 |
|
|---|
| 60 | Perl_OS2_init3(0, 0, 0);
|
|---|
| 61 | }
|
|---|
| 62 |
|
|---|
| 63 | static int
|
|---|
| 64 | init_perl(int doparse)
|
|---|
| 65 | {
|
|---|
| 66 | int exitstatus;
|
|---|
| 67 | char *argv[3] = {"perl_in_REXX", "-e", ""};
|
|---|
| 68 |
|
|---|
| 69 | if (!perlos2_is_inited) {
|
|---|
| 70 | perlos2_is_inited = 1;
|
|---|
| 71 | init_perlos2();
|
|---|
| 72 | }
|
|---|
| 73 | if (my_perl)
|
|---|
| 74 | return 1;
|
|---|
| 75 | if (!PL_do_undump) {
|
|---|
| 76 | my_perl = perl_alloc();
|
|---|
| 77 | if (!my_perl)
|
|---|
| 78 | return 0;
|
|---|
| 79 | perl_construct(my_perl);
|
|---|
| 80 | PL_perl_destruct_level = 1;
|
|---|
| 81 | }
|
|---|
| 82 | if (!doparse)
|
|---|
| 83 | return 1;
|
|---|
| 84 | exitstatus = perl_parse(my_perl, xs_init, 3, argv, (char **)NULL);
|
|---|
| 85 | return !exitstatus;
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 | static char last_error[4096];
|
|---|
| 89 |
|
|---|
| 90 | static int
|
|---|
| 91 | seterr(char *format, ...)
|
|---|
| 92 | {
|
|---|
| 93 | va_list va;
|
|---|
| 94 | char *s = last_error;
|
|---|
| 95 |
|
|---|
| 96 | va_start(va, format);
|
|---|
| 97 | if (s[0]) {
|
|---|
| 98 | s += strlen(s);
|
|---|
| 99 | if (s[-1] != '\n') {
|
|---|
| 100 | snprintf(s, sizeof(last_error) - (s - last_error), "\n");
|
|---|
| 101 | s += strlen(s);
|
|---|
| 102 | }
|
|---|
| 103 | }
|
|---|
| 104 | vsnprintf(s, sizeof(last_error) - (s - last_error), format, va);
|
|---|
| 105 | return 1;
|
|---|
| 106 | }
|
|---|
| 107 |
|
|---|
| 108 | /* The REXX-callable entrypoints ... */
|
|---|
| 109 |
|
|---|
| 110 | ULONG PERL (PCSZ name, LONG rargc, const RXSTRING *rargv,
|
|---|
| 111 | PCSZ queuename, PRXSTRING retstr)
|
|---|
| 112 | {
|
|---|
| 113 | int exitstatus;
|
|---|
| 114 | char buf[256];
|
|---|
| 115 | char *argv[3] = {"perl_from_REXX", "-e", buf};
|
|---|
| 116 | ULONG ret;
|
|---|
| 117 |
|
|---|
| 118 | if (rargc != 1)
|
|---|
| 119 | return seterr("one argument expected, got %ld", rargc);
|
|---|
| 120 | if (rargv[0].strlength >= sizeof(buf))
|
|---|
| 121 | return seterr("length of the argument %ld exceeds the maximum %ld",
|
|---|
| 122 | rargv[0].strlength, (long)sizeof(buf) - 1);
|
|---|
| 123 |
|
|---|
| 124 | if (!init_perl(0))
|
|---|
| 125 | return 1;
|
|---|
| 126 |
|
|---|
| 127 | memcpy(buf, rargv[0].strptr, rargv[0].strlength);
|
|---|
| 128 | buf[rargv[0].strlength] = 0;
|
|---|
| 129 |
|
|---|
| 130 | exitstatus = perl_parse(my_perl, xs_init, 3, argv, (char **)NULL);
|
|---|
| 131 | if (!exitstatus) {
|
|---|
| 132 | exitstatus = perl_run(my_perl);
|
|---|
| 133 | }
|
|---|
| 134 |
|
|---|
| 135 | perl_destruct(my_perl);
|
|---|
| 136 | perl_free(my_perl);
|
|---|
| 137 | my_perl = 0;
|
|---|
| 138 |
|
|---|
| 139 | if (exitstatus)
|
|---|
| 140 | ret = 1;
|
|---|
| 141 | else {
|
|---|
| 142 | ret = 0;
|
|---|
| 143 | sprintf(retstr->strptr, "%s", "ok");
|
|---|
| 144 | retstr->strlength = strlen (retstr->strptr);
|
|---|
| 145 | }
|
|---|
| 146 | PERL_SYS_TERM1(0);
|
|---|
| 147 | return ret;
|
|---|
| 148 | }
|
|---|
| 149 |
|
|---|
| 150 | ULONG PERLEXIT (PCSZ name, LONG rargc, const RXSTRING *rargv,
|
|---|
| 151 | PCSZ queuename, PRXSTRING retstr)
|
|---|
| 152 | {
|
|---|
| 153 | if (rargc != 0)
|
|---|
| 154 | return seterr("no arguments expected, got %ld", rargc);
|
|---|
| 155 | PERL_SYS_TERM1(0);
|
|---|
| 156 | return 0;
|
|---|
| 157 | }
|
|---|
| 158 |
|
|---|
| 159 | ULONG PERLTERM (PCSZ name, LONG rargc, const RXSTRING *rargv,
|
|---|
| 160 | PCSZ queuename, PRXSTRING retstr)
|
|---|
| 161 | {
|
|---|
| 162 | if (rargc != 0)
|
|---|
| 163 | return seterr("no arguments expected, got %ld", rargc);
|
|---|
| 164 | if (!my_perl)
|
|---|
| 165 | return seterr("no perl interpreter present");
|
|---|
| 166 | perl_destruct(my_perl);
|
|---|
| 167 | perl_free(my_perl);
|
|---|
| 168 | my_perl = 0;
|
|---|
| 169 |
|
|---|
| 170 | sprintf(retstr->strptr, "%s", "ok");
|
|---|
| 171 | retstr->strlength = strlen (retstr->strptr);
|
|---|
| 172 | return 0;
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 |
|
|---|
| 176 | ULONG PERLINIT (PCSZ name, LONG rargc, const RXSTRING *rargv,
|
|---|
| 177 | PCSZ queuename, PRXSTRING retstr)
|
|---|
| 178 | {
|
|---|
| 179 | if (rargc != 0)
|
|---|
| 180 | return seterr("no argument expected, got %ld", rargc);
|
|---|
| 181 | if (!init_perl(1))
|
|---|
| 182 | return 1;
|
|---|
| 183 |
|
|---|
| 184 | sprintf(retstr->strptr, "%s", "ok");
|
|---|
| 185 | retstr->strlength = strlen (retstr->strptr);
|
|---|
| 186 | return 0;
|
|---|
| 187 | }
|
|---|
| 188 |
|
|---|
| 189 | ULONG
|
|---|
| 190 | PERLLASTERROR (PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr)
|
|---|
| 191 | {
|
|---|
| 192 | int len = strlen(last_error);
|
|---|
| 193 |
|
|---|
| 194 | if (len <= 256 /* Default buffer is 256-char long */
|
|---|
| 195 | || !DosAllocMem((PPVOID)&retstr->strptr, len,
|
|---|
| 196 | PAG_READ|PAG_WRITE|PAG_COMMIT)) {
|
|---|
| 197 | memcpy(retstr->strptr, last_error, len);
|
|---|
| 198 | retstr->strlength = len;
|
|---|
| 199 | } else {
|
|---|
| 200 | strcpy(retstr->strptr, "[Not enough memory to copy the errortext]");
|
|---|
| 201 | retstr->strlength = strlen(retstr->strptr);
|
|---|
| 202 | }
|
|---|
| 203 | return 0;
|
|---|
| 204 | }
|
|---|
| 205 |
|
|---|
| 206 | ULONG
|
|---|
| 207 | PERLEVAL (PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr)
|
|---|
| 208 | {
|
|---|
| 209 | SV *res, *in;
|
|---|
| 210 | STRLEN len, n_a;
|
|---|
| 211 | char *str;
|
|---|
| 212 |
|
|---|
| 213 | last_error[0] = 0;
|
|---|
| 214 | if (rargc != 1)
|
|---|
| 215 | return seterr("one argument expected, got %ld", rargc);
|
|---|
| 216 |
|
|---|
| 217 | if (!init_perl(1))
|
|---|
| 218 | return seterr("error initializing perl");
|
|---|
| 219 |
|
|---|
| 220 | {
|
|---|
| 221 | dSP;
|
|---|
| 222 | int ret;
|
|---|
| 223 |
|
|---|
| 224 | ENTER;
|
|---|
| 225 | SAVETMPS;
|
|---|
| 226 |
|
|---|
| 227 | PUSHMARK(SP);
|
|---|
| 228 | in = sv_2mortal(newSVpvn(rargv[0].strptr, rargv[0].strlength));
|
|---|
| 229 | eval_sv(in, G_SCALAR);
|
|---|
| 230 | SPAGAIN;
|
|---|
| 231 | res = POPs;
|
|---|
| 232 | PUTBACK;
|
|---|
| 233 |
|
|---|
| 234 | ret = 0;
|
|---|
| 235 | if (SvTRUE(ERRSV))
|
|---|
| 236 | ret = seterr(SvPV(ERRSV, n_a));
|
|---|
| 237 | if (!SvOK(res))
|
|---|
| 238 | ret = seterr("undefined value returned by Perl-in-REXX");
|
|---|
| 239 | str = SvPV(res, len);
|
|---|
| 240 | if (len <= 256 /* Default buffer is 256-char long */
|
|---|
| 241 | || !DosAllocMem((PPVOID)&retstr->strptr, len,
|
|---|
| 242 | PAG_READ|PAG_WRITE|PAG_COMMIT)) {
|
|---|
| 243 | memcpy(retstr->strptr, str, len);
|
|---|
| 244 | retstr->strlength = len;
|
|---|
| 245 | } else
|
|---|
| 246 | ret = seterr("Not enough memory for the return string of Perl-in-REXX");
|
|---|
| 247 |
|
|---|
| 248 | FREETMPS;
|
|---|
| 249 | LEAVE;
|
|---|
| 250 |
|
|---|
| 251 | return ret;
|
|---|
| 252 | }
|
|---|
| 253 | }
|
|---|
| 254 |
|
|---|
| 255 | ULONG
|
|---|
| 256 | PERLEVALSUBCOMMAND(
|
|---|
| 257 | const RXSTRING *command, /* command to issue */
|
|---|
| 258 | PUSHORT flags, /* error/failure flags */
|
|---|
| 259 | PRXSTRING retstr ) /* return code */
|
|---|
| 260 | {
|
|---|
| 261 | ULONG rc = PERLEVAL(NULL, 1, command, NULL, retstr);
|
|---|
| 262 |
|
|---|
| 263 | if (rc)
|
|---|
| 264 | *flags = RXSUBCOM_ERROR; /* raise error condition */
|
|---|
| 265 |
|
|---|
| 266 | return 0; /* finished */
|
|---|
| 267 | }
|
|---|
| 268 |
|
|---|
| 269 | #define ArrLength(a) (sizeof(a)/sizeof(*(a)))
|
|---|
| 270 |
|
|---|
| 271 | static const struct {
|
|---|
| 272 | char *name;
|
|---|
| 273 | RexxFunctionHandler *f;
|
|---|
| 274 | } funcs[] = {
|
|---|
| 275 | {"PERL", (RexxFunctionHandler *)&PERL},
|
|---|
| 276 | {"PERLTERM", (RexxFunctionHandler *)&PERLTERM},
|
|---|
| 277 | {"PERLINIT", (RexxFunctionHandler *)&PERLINIT},
|
|---|
| 278 | {"PERLEXIT", (RexxFunctionHandler *)&PERLEXIT},
|
|---|
| 279 | {"PERLEVAL", (RexxFunctionHandler *)&PERLEVAL},
|
|---|
| 280 | {"PERLLASTERROR", (RexxFunctionHandler *)&PERLLASTERROR},
|
|---|
| 281 | {"PERLDROPALL", (RexxFunctionHandler *)&PERLDROPALL},
|
|---|
| 282 | {"PERLDROPALLEXIT", (RexxFunctionHandler *)&PERLDROPALLEXIT},
|
|---|
| 283 | /* Should be the last entry */
|
|---|
| 284 | {"PERLEXPORTALL", (RexxFunctionHandler *)&PERLEXPORTALL}
|
|---|
| 285 | };
|
|---|
| 286 |
|
|---|
| 287 | ULONG
|
|---|
| 288 | PERLEXPORTALL(PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr)
|
|---|
| 289 | {
|
|---|
| 290 | int i = -1;
|
|---|
| 291 |
|
|---|
| 292 | while (++i < ArrLength(funcs) - 1)
|
|---|
| 293 | RexxRegisterFunctionExe(funcs[i].name, funcs[i].f);
|
|---|
| 294 | RexxRegisterSubcomExe("EVALPERL", (PFN)&PERLEVALSUBCOMMAND, NULL);
|
|---|
| 295 | retstr->strlength = 0;
|
|---|
| 296 | return 0;
|
|---|
| 297 | }
|
|---|
| 298 |
|
|---|
| 299 | ULONG
|
|---|
| 300 | PERLDROPALL(PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr)
|
|---|
| 301 | {
|
|---|
| 302 | int i = -1;
|
|---|
| 303 |
|
|---|
| 304 | while (++i < ArrLength(funcs))
|
|---|
| 305 | RexxDeregisterFunction(funcs[i].name);
|
|---|
| 306 | RexxDeregisterSubcom("EVALPERL", NULL /* Not a DLL version */);
|
|---|
| 307 | retstr->strlength = 0;
|
|---|
| 308 | return 0;
|
|---|
| 309 | }
|
|---|
| 310 |
|
|---|
| 311 | ULONG
|
|---|
| 312 | PERLDROPALLEXIT(PCSZ name, LONG rargc, const RXSTRING *rargv, PCSZ queuename, PRXSTRING retstr)
|
|---|
| 313 | {
|
|---|
| 314 | int i = -1;
|
|---|
| 315 |
|
|---|
| 316 | while (++i < ArrLength(funcs))
|
|---|
| 317 | RexxDeregisterFunction(funcs[i].name);
|
|---|
| 318 | RexxDeregisterSubcom("EVALPERL", NULL /* Not a DLL version */);
|
|---|
| 319 | PERL_SYS_TERM1(0);
|
|---|
| 320 | retstr->strlength = 0;
|
|---|
| 321 | return 0;
|
|---|
| 322 | }
|
|---|