What about function packages? -- Shmuel (Seymour J.) Metz http://mason.gmu.edu/~smetz3 עַם יִשְׂרָאֵל חַי נֵ֣צַח יִשְׂרָאֵ֔ל לֹ֥א יְשַׁקֵּ֖ר
________________________________________ From: IBM Mainframe Discussion List <[email protected]> on behalf of Rony G. Flatscher <[email protected]> Sent: Tuesday, July 2, 2024 6:34 AM To: [email protected] Subject: Rexx command handlers implemented in Java and in ooRexx (Re: Rexx is quite cool, flexible, powerful, feature-rich, thank you! (Re: z/OS 3.1 Enhancements & Support News On 01.07.2024 20:45, Phil Smith III wrote: > Paul Gilmartin wrote: >> Lack of closure: I don't believe a function package, much less a >> command environment can be coded in REXX. those must be coded in >> another language, therefore less portable. > Well, that's a good point. OORexx makes that somewhat better, but not like > P/P. But I could imagine writing an interface to enable this. The tricky part > with Classic Rexx would be variable passing, but Pipes demonstrates that it's > quite doable. I think it'd be easier with OORexx, no? You can implement Rexx command handlers for ooRexx e.g. in C, C++, Java and ... ooRexx. The Java bindings for ooRexx has a sample demonstrating how to do that in ooRexx only, see "samples\Java\handlers\commandHandlers\30_java_starter850\rexxonly". This is what index.html in that directory says about this sample: RunRexxProgram.rex An ooRexx program that configures another Rexx interpreter to use its two command handlers named |ONE| and |DEUX| for the Rexx program it runs. The companion Rexx program sending commands to the command handlers is: testPreconfiguredCommandHandlers.rex. The two preconfigured command handlers understand the following commands: * HELLO * INFO * PING To run enter the following command on the command line: rexx RunRexxProgram testPreconfiguredCommandHandlers.rex In case anyone is curious how such an ooRexx implemented command handler looks like that also takes advantage of ooRexx features like creating multiple Rexx interpreter instances that can be differently configured and define two different command handlers (that for demonstration purposes do the same but can be addressed independently of each other and in parallel) in ooRexx: parse arg rexxProgram if rexxProgram="" then do say "You must supply the name of a Rexx program to run." exit -1 end mgr = .bsf~new("org.apache.bsf.BSFManager") re = mgr~loadScriptingEngine("rexx") rexxconf = re~getRexxConfiguration say "default rexxconf="pp(rexxconf~toString) rhOne = .OneCommandHandler~new jhOne = BsfCreateRexxProxy(rhOne, , "org.rexxla.bsf.engines.rexx.AbstractDirectCommandHandler") rexxconf~addCommandHandler("ONE", jhOne) rhDeux = .DeuxCommandHandler~new jhDeux = BsfCreateRexxProxy(rhDeux, , "org.rexxla.bsf.engines.rexx.AbstractRedirectingCommandHandler") rexxconf~addCommandHandler("DEUX", jhDeux) rexxconf~setInitialAddressEnvironment("ONE"); say say "after configuration:" say "edited rexxconf="pp(rexxconf~toString) say "now running the Rexx program you supplied in file """rexxProgram""":" -- Rexx code to run rexxCode= "call """rexxProgram""" ;" - "::requires BSF.CLS ;" -- get ooRexx support (camouflage Java as ooRexx) say "rexxCode="pp(rexxCode) signal on syntax -- invoke the interpreter and call the Rexx program in the supplied file name re~apply(rexxProgram, 0, 0, rexxCode, .nil, .nil) mgr~terminate -- make sure that the Rexx interpreter instance gets terminated! exit syntax: co=condition('o') say ppJavaExceptionChain(co,.true) say "---" raise propagate ::requires BSF.CLS -- get ooRexx support (camouflage Java as ooRexx) ::class OneCommandHandler ::method handleCommand use arg slot, address, command, slotDir say "[OneCommandHandler] address="pp(address) "command="pp(command) parse upper var command cmd . -- carrying out received commands, return values set the RC variable in Rexx select case cmd when "HELLO" then return "Hello, ooRexx! This is your Rexx (!) OneCommandHandler greeting you!" when "INFO" then return slotDir~javaObject~toString(slot,address) when "PING" then return "Pong!" otherwise -- unknown command received create a failure jarr = bsf.createJavaArrayOf("java.lang.String", "Unknown command" pp(command) ) slotDir~javaObject~raiseCondition(slot, "Failure", command, jarr, "-1") return .nil end ::class DeuxCommandHandler ::method handleCommand use arg slot, address, command, slotDir say "[DeuxCommandHandler] address="pp(address) "command="pp(command) parse upper var command cmd . -- carrying out received commands, return values set the RC variable in Rexx select case cmd when "HELLO" then return "Hello, ooRexx! This is your Rexx (!) DeuxCommandHandler greeting you!" when "INFO" then return slotDir~javaObject~toString(slot,address) when "PING" then return "Pong!" otherwise -- unknown command received create a failure jarr = bsf.createJavaArrayOf("java.lang.String", "Unknown command" pp(command) ) slotDir~javaObject~raiseCondition(slot, "Failure", command, jarr, "-1") return .nil end And here the Java version (cf. "samples\Java\handlers\commandHandlers\30_java_starter850") of the same Rexx command handlers: import org.apache.bsf.BSFManager; import org.rexxla.bsf.engines.rexx.*; public class RunRexxProgram { public static void main (String args[]) { if (args.length==0) { System.err.println("You must supply the name of a Rexx program to run."); System.exit(-1); } try { BSFManager mgr= new BSFManager(); RexxEngine re = (RexxEngine) mgr.loadScriptingEngine("rexx"); RexxConfiguration rexxconf=re.getRexxConfiguration(); System.err.println("default rexxconf=["+rexxconf+"]\n"); rexxconf.addCommandHandler("ONE" , new OneCommandHandler()); rexxconf.addCommandHandler("DEUX" , new DeuxCommandHandler()); rexxconf.setInitialAddressEnvironment("ONE"); System.err.println("\nafter configuration:"); System.err.println("edited rexxconf=["+rexxconf+"]\n"); System.err.println("now running the Rexx program you supplied in file \""+args[0]+"\":"); // Rexx code to run String rexxCode= "call \""+args[0]+"\" ;" + "::requires BSF.CLS ;" ; // get ooRexx support (camouflage Java as ooRexx) // invoke the interpreter and call the Rexx program in the supplied file name re.apply (args[0], 0, 0, rexxCode, null, null); mgr.terminate(); // make sure that the Rexx interpreter instance gets terminated! } catch (Throwable t) { t.printStackTrace(); System.err.println("\n"+t); } System.exit(0); // exit Java } public static class OneCommandHandler implements RexxCommandHandler { public Object handleCommand(Object slot, String address, String command) { System.err.println("[OneCommandHandler] address=["+address+"] "+"command=["+command+"]"); // split at (and consume) whitespace String [] arrCommand = command.split("\\p{javaWhitespace}+"); String cmd = ""; if (arrCommand.length>0) { cmd=arrCommand[0].toUpperCase(); // get command, uppercase it } // excercise the default methods from RexxRedirectingCommandHandler or RexxHandler switch (cmd) { case "HELLO": // return values set the RC variable in Rexx return "Hello, ooRexx! This is your Java OneCommandHandler greeting you!"; case "INFO": // return information about this handler return toString(slot,address); case "PING": // return values set the RC variable in Rexx return "Pong!"; default: // unknown command received create a failure String [] strAdditional = new String[]{ "Unknown command ["+command+"]" }; // RC: raiseCondition(slot, "Failure", command, strAdditional, "-1"); return null; // uses fourth argument of raiseCondition as RC } } } public static class DeuxCommandHandler implements RexxRedirectingCommandHandler { public Object handleCommand(Object slot, String address, String command) { System.err.println("[DeuxCommandHandler] address=["+address+"] "+"command=["+command+"]"); // split at (and consume) whitespace String [] arrCommand = command.split("\\p{javaWhitespace}+"); String cmd = ""; if (arrCommand.length>0) { cmd=arrCommand[0].toUpperCase(); // get command, uppercase it } // excercise the default methods from RexxRedirectingCommandHandler or RexxHandler switch (cmd) { case "HELLO": // return values set the RC variable in Rexx return "Hello, ooRexx! This is your Java DeuxCommandHandler greeting you!"; case "INFO": // return information about this handler return toString(slot,address); case "PING": // return values set the RC variable in Rexx return "Pong!"; default: // unknown command received create a failure String [] strAdditional = new String[]{ "Unknown command ["+command+"]" }; // RC: raiseCondition(slot, "Failure", command, strAdditional, "-1"); return null; // uses fourth argument of raiseCondition as RC } } } } --- BTW, the ooRexx Java bindings comes with a full implementation of a Rexx command handler implemented in Java making all of Java2D available as Rexx commands. To see a simple example and the graphic it creates with Rexx commands see <https://wi.wu.ac.at/rgf/rexx/misc/jdor_doc.tmp/jdor_doc.html>. Anyone here can probably understand without any further information what happens there. One of my business administration students is currently creating an ooRexx package for business graphics that exploits this Java2D Rexx command handler for a Bachelor thesis. It is just unbelievable how fast he came up with a proof of concept with nice looking bar, line and pie charts, within a week, believe it or not! The productivity of Rexx, ooRexx and Rexx command handlers allow for, is just stunning. ... cut ... ---rony ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to [email protected] with the message: INFO IBM-MAIN ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to [email protected] with the message: INFO IBM-MAIN
