On 25/10/2017 2:51 AM, Tony Harminc wrote:
What's the obstacle (not to popularity, but to TSO toleration)?

One can certainly write a Rexx interpreter (or compiler, for that matter),
and run it under TSO and/or ISPF; in that sense it*tolerates*  those
environments. But for reasons known only to IBM, the interfaces needed to
implement*integration*  with the TSO/E and ISPF environments are
undocumented. It used to be possible to write one's own Terminal Monitor
Program (TMP), and there was even a book describing how to do so. With
TSO/E that book was dropped, and while one can guess at much of what needs
to be done, there are OCO control blocks and interfaces that inhibit
implementing interfaces like Address TSO and Address ISPF.

Of course the same thing inhibits implementing Lua or Python or <your
favourite interpreted language> in the TSO/E environment as much as it does
competitive Rexxs.

TSO is easy to integrate using IKJEFTSR in C Lua modules.

-- REXX --
call outtrap 'o.'
"LISTALC"
do i = 1 to o.0 say o.i end

-- Lua --
local o = tso.exec("LISTALC")
for line in o do print(line) end

ISPF is difficult. That's where the real integration with REXX works nicely, the binding between REXX variables and the ISPF function variable pool. And you're right, there's no published API to do something similar. A service that could return a list similar to option 7.3 would make this easy. But even then it's not ideal in languages with lexical scoping to "pollute" the environment with global variables.  For Lua I decided to map ISPF variables to tables using the VDEFINE service. The variables are cleaned up with VDELETE when the garbage collector destroys the table or explicitly with a release() function.

local row = ispf.bind {
  { "name", "char", 20 },
  { "age", "int" },
  { "addr", "char", 60 },
}

ispexec("TBCREATE TAB NAMES(NAME,AGE,ADDR) NOWRITE REPLACE")
row.name = "Sherlock"
row.age = 64
row.addr = "221b Baker Street"
ispexec("TBADD TAB")

Of course, this looks like a step down. It's more code and strings are fixed length. But the real benefit over REXX comes with modules. I find with REXX it's impossible to apply the DRY principle.

-- REXX --

"LMINIT DATAID(ID) DATASET(DSNAME) ENQ(SHR)"
"LMOPEN DATAID(&ID) OPTION(INPUT)"
member = ''
do forever
  "LMMLIST DATAID(&ID) OPTION(LIST) MEMBER(MEMBER)"
  if rc > 0 then leave
  say member
end
"LMCLOSE DATAID(&ID)"
"LMFREE  DATAID(&ID)"

-- Lua --

local ISPF = require("ISPF")
ISPF.MemberList(dsname, "SHR"):foreach(function (member) print(member.name) end)

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN

Reply via email to