This REXX tool allows users to view datasets without leaving their current edit session by placing the cursor on a valid dataset name (DSN) or DDNAME. It checks the syntax of the DSN, handles symbolic variable substitution, and concatenation. If the edit fails, it will automatically switch to browse mode. It can also stack multiple edit sessions.
This REXX tool allows users to view datasets without leaving their current edit session by placing the cursor on a valid dataset name (DSN) or DDNAME. It checks the syntax of the DSN, handles symbolic variable substitution, and concatenation. If the edit fails, it will automatically switch to browse mode. It can also stack multiple edit sessions.
This REXX tool allows users to view datasets without leaving their current edit session by placing the cursor on a valid dataset name (DSN) or DDNAME. It checks the syntax of the DSN, handles symbolic variable substitution, and concatenation. If the edit fails, it will automatically switch to browse mode. It can also stack multiple edit sessions.
/* ** PURPOSE: Provide cursor sensitive DSN and DDNAME recognitions allowing users to VIEWDSN into another data set without leaving their current edit session. ** USAGE: Place cursor under any valid DSN or DDNAME character and start VIEWDSN from the command line or a predfined PFKey. PFKey use is recommended to minimize cursor repositioning. If the cursor is left on the command line, the first data line displayed will be searched for a valid DSN. ** FEATURES: - DSN syntax checking with SYSDSN. ** ** - Symbolic variable substitution. ** ** - Concatenation recognition with member search option. ** ** - Automatic switch to browse mode if edit fails. ** ** - Allows edit sessions to be stacked. ** ** - Allows modular addition of new functions. */ SETUP: /* - Set error and message controls ** ** - Establish edit macro environment ** ** - Set mode */ "ISPEXEC CONTROL ERRORS RETURN" x = Msg("OFF") "ISREDIT MACRO (FUNC)" If Translate(Substr(func,1,1)) = "E" Then func = "EDIT" Else func = "BROWSE" CHECK_CURSOR_DATA: /* - Find and save current cursor location ** ** - Reposition cursor to data field if necessary ** ** - Set data length and a list of valid DSN characters ** ** - Determine if cursor is on valid DSN character ** ** - Check if DSN or DDNAME and call appropriate routine */ "ISREDIT (LIN,COL) = CURSOR" olin = lin ; ocol = col If col = 0 Then Do "ISREDIT FIND '.' .ZCSR .ZCSR" If rc = 4 Then "ISREDIT CURSOR = .ZCSR 1" "ISREDIT (LIN,COL) = CURSOR" End "ISREDIT (DATA) = LINE .ZCSR" data = Translate(data) len = Length(data) val = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#$0123456789.{()-+&/" If Verify(Substr(data,col,1),val,"N") \= 0 Then Do Say "INVALID CURSOR LOCATION" Signal QUIT End mem = "" Call DDNAME /*If Substr(data,1,2) = "//" & col < Pos(" DD ",data) Then Call DDNAME Else Call DSNAME */ PROCESS_STACK: /* - Pull DSNs from stack in FIFO order ** ** - Check for symbolics and take appropriate action ** ** - Perform first level check using SYSDSN ** ** - Protect current stack from recursive edits ** ** - Check SYSDSN msg and decide whether to proceed */ Do Queued() Pull dsn If Pos("&",dsn) \= 0 & Pos("&&",dsn) = 0 Then Call SYMBOLIC If mem \= "" then dsn = dsn || "(" || mem || ")" msg = SYSDSN("'"dsn"'") "NEWSTACK" If (msg = "INVALID DATASET NAME, '"dsn"'" & mem = "") |, (msg = "MEMBER NOT FOUND" & mem = "") |, (msg = "OK") Then Interpret "Call" func Else Say msg "-" dsn "DELSTACK" End QUIT: /* - Reset excluded lines ** ** - Return cursor to original location ** ** - Exit from VIEWDSN */ "ISREDIT RESET" "ISREDIT CURSOR = "olin ocol Exit DDNAME: /* - This routine is designed for JCL DDNAME processing ** ** - Set current DDNAME ** ** - Determine total number of lines ** ** - Get new line of data if needed and parse it ** ** - Find all occurrences of DSN= and DSNAME= in current DDNAME, reposition cursor to first DSN position, and call DSNAME (do not prcess JCL comment statements) ** ** - If concatenation detected (more than one DSN queued) ask user if member search is desired ** ** - Return to original caller */ ddn = Substr(data,3,Pos(" ",data) - 3) "ISREDIT (LAST) = LINENUM .ZLAST" Do n = 1 to (last - lin + 1) by 1 If n \= 1 Then "ISREDIT (DATA) = LINE" lin + n - 1 Parse Var data v1 3 v2 v3 v4 v5 If v1 = "//" Then Select When Substr(data,3,1) = "*" Then Nop When Substr(data,3,1) = " " | n = 1 Then Do If v2 \= "" & v3 = "DD" Then v2 = v4 If v2 = "DD" Then v2 = v3 If Pos("DSNAME=",v2) \= 0 Then Do col = Pos("DSNAME=",data)+7 Call DSNAME End If Pos("DSN=",v2) \= 0 Then Do col = Pos("DSN=",data) + 4 Call DSNAME End End Otherwise Leave n End End If Queued() > 1 Then Do "NEWSTACK" Say "DD STATEMENT '"ddn"' CONTAINS CONCATENATED DATA SETS." Say Say "PLEASE ENTER A NAME TO BEGIN A MEMBER SEARCH, OR JUST PRESS" Say "ENTER TO" func "EACH DATA SET INDIVIDUALLY." Say Pull mem "DELSTACK" End Return DSNAME: /* - Find beginning/ending DSN characters by searching for first invalid DSN character left and right of current cursor location ** ** - Extract the DSN from the data using above beg/end ** ** - Place the DSN on the stack in FIFO ordre ** ** - Return to original caller */ beg = Verify(Reverse(data),val,"N",(len - col + 1)) If beg = 0 Then beg = 1 ; Else beg = len - beg + 2 end = Verify(data,val,"N",col) ; If end = 0 Then end = len + 1 dsn = Substr(data,beg,Abs(end - beg)) Queue dsn Return SYMBOLIC: /* - Exclude all JCL comment statements ** ** - Set pos1/pos2 to starting/ending symbolic positions ** ** - Set sym variable stripping "&" and trailing "." ** ** - Find next occurence of sym (probably on EXEC for ** ** instream PROC) ** ** - If not found, check for first occurence (probably ** ** on PROC statement) ** ** - If found set pos2/pos3 to start/end literal position** ** - If not found or more than one found, ask user to ** ** supply the symbolic's literal value ** ** - Strip leading and trailing single quotes ** ** - Replace DSN's symbolic variable with literal value ** ** - Continue processing until all symbolics are resolved** ** - Return to original caller */ "ISREDIT EXCLUDE '//*' 1 ALL" DO Forever pos1 = Pos("&",dsn) If pos1 = 0 Then Leave pos2 = Pos(".",dsn,pos1) If pos2 = 0 Then pos2 = Verify(dsn,"()","M",pos1) - 1 /* If pos2 < - Then pos2 = Length(dsn)*/ sym = Strip(Substr(dsn,(pos1 + 1),(pos2 - pos1)),"T",".") "ISREDIT FIND ' "sym"=' NEXT NX" If rc = 4 Then "ISREDIT FIND ',"sym"=' NEXT NX" If rc = 4 Then "ISREDIT FIND ' "sym"=' ALL NX If rc = 4 Then "ISREDIT FIND ',"sym"=' ALL NX "ISREDIT (NUMFINDS) = FIND_COUNTS" If numfinds = 1 Then Do "ISREDIT (LIN,COL) = CURSOR" "ISREDIT (DATA) = LINE" lin pos3 = Pos("=",data,col) + 1 pos4 = Verify(data,", ","M",pos3) lit = Substr(data,pos3,(pos4-pos3)) End Else Do "NEWSTACK" Say Say "WARNING: UNABLE TO DETERMINE THE LITERAL VALUE FOR" Say " SYMBOLIC VARIABLE '"sym"'" Say Say "PLEASE ENTER A VALUE (OR NULL) TO RESUME PROCESSING." Say Pull lit "DELSTACK" lit = Strip(lit,"B","'") End lit = Strip(lit,"B","'") dsn = Insert(lit,Delstr(dsn,pos1,(pos2 - pos1 + 1)),(pos1 - 1)) "ISREDIT CURSOR = " olin ocol End Return EDIT: /* - Edit the desired data set ** ** - Return the appropriate message if edit fails ** ** - Attempt to browse the data set if severe error ** ** - Return to original caller */ "ISPEXEC EDIT DATASET('"dsn"')" Select When rc = 14 Then Say dsn "- DATA SET OR MEMBER IN USE" When rc = 16 Then Say dsn "- NO MEMBERS IN LIBRARY" When rc = 20 Then Call BROWSE Otherwise Nop End Return BROWSE: /* - Browse the desired data set ** ** - Return the appropriate message if browse fails ** ** - Return to original caller */ "ISPEXEC BROWSE DATASET('"dsn"')" Select When rc = 12 Then Say dsn "- ZERO-LENGTH DATA" When rc = 14 Then Say dsn "- MEMBER NOT FOUND" When rc = 16 Then Say dsn "- NO MEMBERS IN LIBRARY" When rc = 20 Then Say dsn "- SEVERE ERROR" Otherwise Nop End Return