17 extern ULONG _emx_exception ( EXCEPTIONREPORTRECORD *,
18 EXCEPTIONREGISTRATIONRECORD *,
22 static RXSTRING * strs;
24 static SHVBLOCK * vars;
28 static RXSTRING rxcommand = { 9, "RXCOMMAND" };
29 static RXSTRING rxsubroutine = { 12, "RXSUBROUTINE" };
30 static RXSTRING rxfunction = { 11, "RXFUNCTION" };
32 static ULONG PERLCALL(PSZ name, ULONG argc, PRXSTRING argv, PSZ queue, PRXSTRING ret);
36 #define Fetch RXSHV_FETCH
37 #define Drop RXSHV_DROPV
39 #define Set RXSHV_SYSET
40 #define Fetch RXSHV_SYFET
41 #define Drop RXSHV_SYDRO
44 static long incompartment;
47 exec_in_REXX(pTHX_ char *cmd, char * handlerName, RexxFunctionHandler *handler)
50 HMODULE hRexx, hRexxAPI;
52 LONG APIENTRY (*pRexxStart) (LONG, PRXSTRING, PSZ, PRXSTRING,
53 PSZ, LONG, PRXSYSEXIT, PSHORT, PRXSTRING);
54 APIRET APIENTRY (*pRexxRegisterFunctionExe) (PSZ,
55 RexxFunctionHandler *);
56 APIRET APIENTRY (*pRexxDeregisterFunction) (PSZ);
65 Perl_die(aTHX_ "Attempt to reenter into REXX compartment");
68 if (DosLoadModule(buf, sizeof buf, "REXX", &hRexx)
69 || DosLoadModule(buf, sizeof buf, "REXXAPI", &hRexxAPI)
70 || DosQueryProcAddr(hRexx, 0, "RexxStart", (PFN *)&pRexxStart)
71 || DosQueryProcAddr(hRexxAPI, 0, "RexxRegisterFunctionExe",
72 (PFN *)&pRexxRegisterFunctionExe)
73 || DosQueryProcAddr(hRexxAPI, 0, "RexxDeregisterFunction",
74 (PFN *)&pRexxDeregisterFunction)) {
75 Perl_die(aTHX_ "REXX not available\n");
79 pRexxRegisterFunctionExe(handlerName, handler);
81 MAKERXSTRING(args[0], NULL, 0);
82 MAKERXSTRING(inst[0], cmd, strlen(cmd));
83 MAKERXSTRING(inst[1], NULL, 0);
84 MAKERXSTRING(result, NULL, 0);
85 rc = pRexxStart(0, args, "StartPerl", inst, "Perl", RXSUBROUTINE, NULL,
89 pRexxDeregisterFunction("StartPerl");
90 DosFreeModule(hRexxAPI);
92 if (!RXNULLSTRING(result)) {
93 res = newSVpv(RXSTRPTR(result), RXSTRLEN(result));
94 DosFreeMem(RXSTRPTR(result));
98 if (rc || SvTRUE(GvSV(PL_errgv))) {
99 if (SvTRUE(GvSV(PL_errgv))) {
101 Perl_die(aTHX_ "Error inside perl function called from REXX compartment.\n%s", SvPV(GvSV(PL_errgv), n_a)) ;
103 Perl_die(aTHX_ "REXX compartment returned non-zero status %li", rc);
112 PERLSTART(PSZ name, ULONG argc, PRXSTRING argv, PSZ queue, PRXSTRING ret)
114 return PERLCALL(NULL, argc, argv, queue, ret);
117 #define in_rexx_compartment() exec_in_REXX(aTHX_ "return StartPerl()\r\n", \
118 "StartPerl", PERLSTART)
119 #define REXX_call(cv) ( exec_cv = (cv), in_rexx_compartment())
120 #define REXX_eval_with(cmd,name,cv) ( exec_cv = (cv), \
121 exec_in_REXX(aTHX_ cmd,name,PERLSTART))
122 #define REXX_eval(cmd) REXX_eval_with(cmd,NULL,NULL)
125 PERLCALL(PSZ name, ULONG argc, PRXSTRING argv, PSZ queue, PRXSTRING ret)
128 EXCEPTIONREGISTRATIONRECORD xreg = { NULL, _emx_exception };
135 DosSetExceptionHandler(&xreg);
143 DosUnsetExceptionHandler(&xreg);
150 char **arr = alloca((argc + 1) * sizeof(char *));
152 for (i = 0; i < argc; ++i)
153 arr[ac++] = argv[i].strptr;
156 rc = perl_call_argv(name, G_SCALAR | G_EVAL, arr);
157 } else if (exec_cv) {
161 rc = perl_call_sv(cv, G_SCALAR | G_EVAL);
166 if (rc == 1 && SvOK(TOPs)) {
167 str = SvPVx(POPs, len);
169 if (DosAllocMem((PPVOID)&ret->strptr, len, PAG_READ|PAG_WRITE|PAG_COMMIT)) {
170 DosUnsetExceptionHandler(&xreg);
173 memcpy(ret->strptr, str, len);
174 ret->strlength = len;
182 DosUnsetExceptionHandler(&xreg);
187 DosUnsetExceptionHandler(&xreg);
198 strs = malloc(nstrs * sizeof(RXSTRING));
209 vars = malloc(nvars * sizeof(SHVBLOCK));
218 trace = getenv("PERL_REXX_DEBUG");
222 constant(char *name, int arg)
229 MODULE = OS2::REXX PACKAGE = OS2::REXX
240 _call(name, address, queue="SESSION", ...)
250 RexxFunctionHandler *fcn = address;
254 fprintf(stderr, "REXXCALL::_call name: '%s' args:", name);
255 for (i = 0; i < argc; ++i) {
257 char *ptr = SvPV(ST(3+i), len);
258 MAKERXSTRING(strs[i], ptr, len);
260 fprintf(stderr, " '%.*s'", len, ptr);
265 fprintf(stderr, "\n");
266 MAKERXSTRING(result, resbuf, sizeof resbuf);
267 rc = fcn(name, argc, strs, queue, &result);
269 fprintf(stderr, " rc=%X, result='%.*s'\n", rc,
270 result.strlength, result.strptr);
271 ST(0) = sv_newmortal();
274 sv_setpvn(ST(0), result.strptr, result.strlength);
276 sv_setpvn(ST(0), "", 0);
278 if (result.strptr && result.strptr != resbuf)
279 DosFreeMem(result.strptr);
289 int n = (items + 1) / 2;
293 fprintf(stderr, "REXXCALL::_set");
294 for (i = 0; i < n; ++i) {
295 SHVBLOCK * var = &vars[i];
298 name = SvPV(ST(2*i+0),namelen);
300 value = SvPV(ST(2*i+1),valuelen);
306 var->shvcode = RXSHV_SET;
307 var->shvnext = &vars[i+1];
308 var->shvnamelen = namelen;
309 var->shvvaluelen = valuelen;
310 MAKERXSTRING(var->shvname, name, namelen);
311 MAKERXSTRING(var->shvvalue, value, valuelen);
313 fprintf(stderr, " %.*s='%.*s'",
314 var->shvname.strlength, var->shvname.strptr,
315 var->shvvalue.strlength, var->shvvalue.strptr);
318 fprintf(stderr, "\n");
319 vars[n-1].shvnext = NULL;
320 rc = RexxVariablePool(vars);
322 fprintf(stderr, " rc=%X\n", rc);
323 RETVAL = (rc & ~RXSHV_NEWV) ? FALSE : TRUE;
338 fprintf(stderr, "REXXCALL::_fetch");
339 for (i = 0; i < items; ++i) {
340 SHVBLOCK * var = &vars[i];
342 name = SvPV(ST(i),namelen);
343 var->shvcode = RXSHV_FETCH;
344 var->shvnext = &vars[i+1];
345 var->shvnamelen = namelen;
346 var->shvvaluelen = 0;
347 MAKERXSTRING(var->shvname, name, namelen);
348 MAKERXSTRING(var->shvvalue, NULL, 0);
350 fprintf(stderr, " '%s'", name);
353 fprintf(stderr, "\n");
354 vars[items-1].shvnext = NULL;
355 rc = RexxVariablePool(vars);
356 if (!(rc & ~RXSHV_NEWV)) {
357 for (i = 0; i < items; ++i) {
359 SHVBLOCK * var = &vars[i];
360 /* returned lengths appear to be swapped */
361 /* but beware of "future bug fixes" */
362 namelen = var->shvvalue.strlength; /* should be */
363 if (var->shvvaluelen < var->shvvalue.strlength)
364 namelen = var->shvvaluelen; /* is */
366 fprintf(stderr, " %.*s='%.*s'\n",
367 var->shvname.strlength, var->shvname.strptr,
368 namelen, var->shvvalue.strptr);
369 if (var->shvret & RXSHV_NEWV || !var->shvvalue.strptr)
372 PUSHs(sv_2mortal(newSVpv(var->shvvalue.strptr,
377 fprintf(stderr, " rc=%X\n", rc);
389 int len = strlen(stem), namelen, valuelen;
391 fprintf(stderr, "REXXCALL::_next stem='%s'\n", stem);
392 sv.shvcode = RXSHV_NEXTV;
394 MAKERXSTRING(sv.shvvalue, NULL, 0);
396 sv.shvnamelen = sizeof name;
398 MAKERXSTRING(sv.shvname, name, sizeof name);
399 if (sv.shvvalue.strptr) {
400 DosFreeMem(sv.shvvalue.strptr);
401 MAKERXSTRING(sv.shvvalue, NULL, 0);
403 rc = RexxVariablePool(&sv);
404 } while (!rc && memcmp(stem, sv.shvname.strptr, len) != 0);
407 /* returned lengths appear to be swapped */
408 /* but beware of "future bug fixes" */
409 namelen = sv.shvname.strlength; /* should be */
410 if (sv.shvnamelen < sv.shvname.strlength)
411 namelen = sv.shvnamelen; /* is */
412 valuelen = sv.shvvalue.strlength; /* should be */
413 if (sv.shvvaluelen < sv.shvvalue.strlength)
414 valuelen = sv.shvvaluelen; /* is */
416 fprintf(stderr, " %.*s='%.*s'\n",
417 namelen, sv.shvname.strptr,
418 valuelen, sv.shvvalue.strptr);
419 PUSHs(sv_2mortal(newSVpv(sv.shvname.strptr+len, namelen-len)));
420 if (sv.shvvalue.strptr) {
421 PUSHs(sv_2mortal(newSVpv(sv.shvvalue.strptr, valuelen)));
422 DosFreeMem(sv.shvvalue.strptr);
425 } else if (rc != RXSHV_LVAR) {
426 die("Error %i when in _next", rc);
429 fprintf(stderr, " rc=%X\n", rc);
440 for (i = 0; i < items; ++i) {
441 SHVBLOCK * var = &vars[i];
443 name = SvPV(ST(i),namelen);
444 var->shvcode = RXSHV_DROPV;
445 var->shvnext = &vars[i+1];
446 var->shvnamelen = namelen;
447 var->shvvaluelen = 0;
448 MAKERXSTRING(var->shvname, name, var->shvnamelen);
449 MAKERXSTRING(var->shvvalue, NULL, 0);
451 vars[items-1].shvnext = NULL;
452 RETVAL = (RexxVariablePool(vars) & ~RXSHV_NEWV) ? FALSE : TRUE;
461 RETVAL = RexxRegisterFunctionExe(name, PERLCALL);
475 REXX_eval_with(cmd,name,cv)