When using an ISPF table for input, the table library must be available via ISPTLIB. The library containing the table to be used has to be either part of the original ISPTLIB allocation or LIBDEF'd into a preferential position. If LIBDEF'd, the LIBDEF can reference either a DATASET or a LIBRARY. If a LIBRARY, the library itself must have been previously ALLOCATEd under a unique DDname. This latter method is fraught with hazard and I do not recommend it. I recommend instead using the DATASET route as being much less likely to give you an ulcer:
"LIBDEF ISPTLIB DATASET ID("isptlib") STACK" --- use the dataset --- "LIBDEF ISPTLIB"
Once the dataset is in place, you must open it with TBOPEN... unless it's already open... unless it's not even present. Well, heck, how do we know that? TBSTATS:
"LIBDEF ISPTLIB DATASET ID("isptlib") STACK" "TBSTATS" $tn$ "STATUS1(s1) STATUS2(s2)" if s1 > 1 then do say "Table" $tn$ "not available." zerrsm = "Table" $tn$ "not available." zerrlm = "Table" $tn$ "not found in the ISPTLIB library chain" sw.0error_found = "1" end; else, if s2 = 1 then do /* table is not open */ "TBOPEN " $tn$ openmode.NOUPDT if rc > 4 then do sw.0error_found = 1 zerrsm = "Table did not OPEN" zerrlm = "Table" $tn$ "cannot be opened due to prior", "enqueues." "SETMSG MSG(ISRZ002)" end end else "TBTOP" $tn$ "LIBDEF ISPTLIB"
STATUS1 generally addresses the data-content of the library. STATUS2 references the OPEN-state of the named table, in this case, variable "$tn$". A value of "1" in STATUS1 indicates that the named table exists in ISPTLIB. A value greater than one signals trouble: the table you've named isn't where it can be opened. This certainly constitutes 'an error'.
A value of "1" in STATUS2 signals that the named table is not presently open or otherwise in use. If this is not the case (the table is already open - STATUS2 returned a value greater than "1") there is no need to re-open the table. ISPF will ignore such a request. With the table presently in a not-open state, a TBOPEN can be issued for the table. The example here shows that the mode of opening is determined by the current setting of variable "NOUPDT" (set in REXXSKEL's TOOLKIT_INIT section). The table will be opened for WRITE if NOUPDT is off, and NOWRITE if it is on.
A table which is already open need only be TBTOPped to make it ready for our use.
As soon as the table is determined to be open, the LIBDEF for the ISPTLIB is no longer needed — a full copy of the table now exists within the user's region. It's good practice to immediately drop the LIBDEF the instant it has served its purpose.
That's it. That's all there is to opening an ISPF table. From here on in until the table is TBCLOSEd or TBENDed, the complete contents are available for your use. Unfortunately, that makes them unavailable for anyone else's use if the table was opened WRITE, so be a good user: get in, get done, get out.
If you as the programmer discover that some of your users are hogging the table, you may have to take drastic action to prevent that. 'Drastic action' may include TBCLOSEing the table after every update, TBENDing it after every inquiry, and consequently repeatedly TBOPENing it for each new cycle. In between, you will have to maintain a record of what the original looked like when it was first fetched so that you'll know whether it was changed in the meantime. Lots of CPU cycles wasted because of undisciplined users. You may even wind up rewriting the app to eliminate ISPF... but you will have had the experience of prototyping it (easily) in ISPF and will get the benefits Dr. Brooks promised when he said:
When planning a program, plan to do it twice. You're going to do it twice; you might as well plan for it.