Can I easily make an ISPF edit line command macro?

The key word in the title is easily. If you search for “Working with an edit line command table”, the documentation gives you instructions on how to create a table, then add your definition, create your macro, and then use it. When you were expecting to do this invisibly for the end user, it is a lot of work.

A command line rexx program can process line commands. I created a command line program so when I use it, and use S or SS..SS line commands, the macro can extract the tagged lines, and so do things with the tagged data.

The command line Rexx

/* REXX */ 
address isredit
'MACRO (a) NOPROCESS '
'process range S '
IF RC = 0
THEN DO
"(first) = LINENUM .ZFRANGE"
"(last) = LINENUM .ZLRANGE"
data = ""
/* build up a long string from the tagged lines */
do i = first to last
"(l) = LINE (i)"
data = data || strip(l) || " "
end
l = data
address ispexec "edit dataset('COLIN.$$TEMP$$') macro(l2) parm(l)"
END

Where the lines of interest are

  • ‘MACRO (a) NOPROCESS ‘
    • Usually when a command line macro is processed, ISPF processes any outstanding line commands (such as D) before processing any commands in the rexx exec. The NOPROCESS says – hold off doing this until instructed.
    • a is the data passed in
  • ‘process range S ‘
    • This locates any line commands beginning with S, for a single line, or SS…SS for multiple lins.
  • if rc = 0 then do
  • “(first) = LINENUM .ZFRANGE”
    • get the line number of the First in the RANGE
  • “(last) = LINENUM .ZLRANGE”
    • get the line number of the Last in the Range.
  • data = “”
  • do i = first to last /* process the data build up the string */
    • “(l) = LINE (i)”
    • data = data || strip(l) || ” “
  • end
  • ldata = data
  • address ispexec “edit dataset(‘COLIN.$$TEMP$$’) macro(l2) parm(ldata)”
    • Invoke edit on a file – invoke macro l2, and pass the data in the rexx variable ldata
  • END

If the “process range” gives a non zero return code, set an error message

else do 
zedsmsg = 'You need to specify line prefix s|ss ss'
zedlmsg = 'You need to specify line prefix s|ss ss long message'
address ispexec 'SETMSG MSG(ISRZ001)'
end

This sets a Short message (zedSmsg) which is display at the top right of the display, and a long message (zedLmsg) if the user presses PF1 on the short message.

Macro L2

This macro is processed when the edit dataset(..) macro(l2) command is issued

/* REXX */ 
address isredit
'MACRO (a) '

say "Passed data" a
...

ISPF find using regular expressions is clever! But…

I had data like OWNER(colin) and wanted to replace the text like “colin” with some other text, regardless of the “colin” value.

I could do it in ISPF edit using

C “OWNER(COLIN)” “OWNER(REPLACE)”
C “OWNER(USER1)” “OWNER(REPLACE)” .

but this quickly got to be tedious. I found you can use regular expressions with ISPF find using regular expressions. Wikipedia says

A regular expression (shortened as regex or regexp), … is a sequence of characters that specifies a match pattern in text. Usually such patterns are used by string-searching algorithms for “find” or “find and replace” operations on strings, or for input validation.

Wikipedia

For example I could use

change rc”owner\(.*\)” “owner(replace)”

which says find the string

“owner” followed by “(” – \( is escaped and not interpreted, followed by zero or more characters, followed by ) - \) is escaped; and replace it with the string “owner(replace)”

What you can do with it

find rc”abc[0-9]” says find a string abc followed by one of the characters in the range 0 to 9 so abc9 is found, but find rc”abc[0-8]” would not find abc9.

But…

Your terminal needs to have the correct code page for square brackets.
If I use “U.S English Code page 37” it works. If I use “Bracket (CP 037 modified) Euro” it does not work.

With the “Bracket (CP 037 modified) Euro”  [ is displayed as Ý, and ] is displayed as ¨, and the ISPF code cannot find [ or ] and so cannot find the string

Old dogs, new tricks: ISPF cut and paste

I had many members with RACF commands within JCL, and wanted to rationalise them so the definitions were in a couple of files, one for userid information, one for define commands, one for permits etc.. I remembered someone once talking about ISPF cut and paste, and this proved to be very useful.

I had a member with

//S1  EXEC PGM=IKJEFT01,REGION=0M 
//* EPLIB DD DISP=SHR,DSN=SYS1.MIGLIB
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *,SYMBOLS=(JCLONLY)
SETROPTS GENERIC(MFADEF) GENCMD(MFADEF)
RDEF MFADEF FACTOR.AZFSTC OWNER(IBMUSER)
SETROPTS RACLIST(MFADEF) CLASSACT(MFADEF)

/*
/*

and wanted to copy the bold text from each file into other files.

Cut

I used the edit command cut .a .b define append with

000007 //SYSTSIN DD *,SYMBOLS=(JCLONLY) 
.a0008 SETROPTS GENERIC(MFADEF) GENCMD(MFADEF)
000009 RDEF MFADEF FACTOR.AZFSTC OWNER(IBMUSER)
.b0010 SETROPTS RACLIST(MFADEF) CLASSACT(MFADEF)
000011 /*

this copied the three lines into a clipboard called define.

You can also use the line commands cc..cc and mm..mm.

For a different file I used CUT add append

000006 //SYSTSIN DD * 
cc ADDUSER AZFSTC DFLTGRP(SYS1) OWNER(SYS1) -
000008 OMVS(AUTOUID) -
000009 NAME('MFA STC') -
000010 NOPASSWORD NOOIDCARD -
cc RESTRICTED
/*

and so on for each file.

If you use the line commands mm … mm it will delete it from the current file after the data has been copied to the clip board.

With PF12 set to retrieve it was easy to recall the cut command in each member.

Paste

After I had finished cutting the text I edited a member ADD and used the paste command. The basic syntax is paste clipboard

Command ===> paste add
A ********************************* Top of Data ***...
****** ******************************** Bottom of Data *...

This takes all the data from the “add” clipboard, and puts it >A<fter the top line. Similarly I edited the DEFS file, and used the “paste defs” command to retrieve the data in the clipboard.

IKJ56500I COMMAND … NOT FOUND. Macro does not exist

Due to some random typing, when I try to edit a member I keep getting

  • IKJ56500I COMMAND M NOT FOUND
  • Macro does not exist

After some playing around, I found this was caused by having a list of PDS members, using the prefix command E, and putting something(M) in the Prompt column.

To fix it, use E and put / in the Prompt column. This gives the EDIT Entry Panel and shows Initial Macro..M . Blank out the M, and press PF3 to clear it.

Easy when you know how.

I expected this to show up under ISPF 2 (Edit) but the initial Macro field was blank.

TSO NETSTAT STACK – doesn’t. Get fullscreen output instead.

I was getting annoyed because the TCPIP NETSTAT command displays the output in line mode, and you cannot scroll back to look at it.

The documentation says you can use NETSTAT … STACK in a Rexx program, and use queued() to see how many lines were on the stack. This did not work for me. I always got 0 lines on the stack, until I exited ISPF when they all tried to execute and produced “IKJ56621I INVALID COMMAND NAME SYNTAX”.

A better (and more efficient way – you have to write less code) is create an Rexx program. I used USER.Z24C.CLIST(NS)

/* REXX */ 
ADDRESS ISPEXEC
'ISREDIT MACRO (a)' 
x = outtrap("var.") 
if a   = "" then a   = "HOME" 
address TSO "netstat "a 
x = outtrap("OFF") 
if var.0  = 0 then exit 

"ISREDIT AUTOSAVE OFF PROMPT" 
do y =1 to var.0 
   fn= var.y 
   "ISREDIT LINE_AFTER  .ZLAST     =  (fn)" 
end 

If you use this command within an ISPF edit session, it will append the output to the bottom of the file.

Note: You pass parameters via ISREDIT MACRO(parms) rather than pars args parms.

You can always use DELETE ALL NX to clear the file before running the exec.

It uses AUTOSAVE OFF PROMPT, to make you explicitly save the output – or cancel from the session, and do not accidentally save it.

Extend it

As the output is in an ISPF Editor session, you can write edit macros to process the content, and filter or reformat it.

Shorthand

I extended it so I say “ns h” and it issues the netstat home command etc.

For example

'ISREDIT MACRO (a)' 
if a   = "" then a  = "HOME" 
else 
if a = "i" then a = "devlinks (intfname ifportcp6" 
else 
if a = "h" then a = "home" 
else 
if a = "r" then a = "route addrtype  IPV6" 
else 
if a = "n" then a = "nd" 
address TSO "netstat "a 

Why can’t I delete the data set?

I had some data sets which I could not delete from ISPF 3;4 as I got

IEC614I SCRATCH FAILED – RC 008, DIAGNOSTIC INFORMATION IS (04060020) ..

where the error code is

04060020 – Verification of SMS flags failed; caller indicates data set is not SMS-managed, but FMT4 DSCB indicates that it is an SMS volume. This error might be caused by a damaged catalog entry. Issuing the recatalog command might clear this error.

I tried to use various DFDSS commands such move, or backup delete, but these failed on the delete.

DATA SET BACKUP.D210201.COLIN.JCL ON VOLUME A4USR1 NOT SCRATCHED, 2-08,02 

IGD17040I ERROR IN DADSM PROCESSING ON VOLUME A4USR1 FOR DATA SET  
BACKUP.D210201.COLIN.JCL HISTORIC RETURN CODE IS 8 DIAGNOSTIC INFORMATION IS 04060020              
IGD306I UNEXPECTED ERROR DURING IGGDAS02 PROCESSING RETURN CODE 4 REASON CODE 32                                             

This all looked pretty broken – until I found an easy command

//S1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE BACKUP.D210118.USER.Z24A.CLIST
/*

That worked! Having found one way of doing it – I could take it to the next level using the MASK option.

//S1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE BACKUP.D210215.** MASK
/*

This gave me

DELETE BACKUP.D210215.** MASK
IDC0550I ENTRY (A) BACKUP.D210215.ADCD.C.SOURCE DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.C DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.JCL DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.RACF DELETED
IDC0550I ENTRY (A) BACKUP.D210215.COLIN.WLM DELETED
IDC0550I ENTRY (A) BACKUP.D210215.IBMUSER.JCL DELETED
IDC0550I ENTRY (A) BACKUP.D210215.IBMUSER.MQ.JCL DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.CLIST DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.PARMLIB DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.PROCLIB DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.TCPPARMS DELETED
IDC0550I ENTRY (A) BACKUP.D210215.USER.Z24A.VTAMLST DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

I thought this was pretty useful!

Just be a bit careful and do not say DELETE BACKUP.* MASK

I didn’t know that z/OS command

On one of the z/OS fora I found the following good stuff from David Mingee. Three of these were new to me.

  1. After using START command to start more than one screen, you can enter =XALL to close all screens.
  2. In ISPF enter CMD SWAPBAR ON.  This will cause a screen name to be displayed at the bottom left of your screen.  There will be a screen name for each START CMD that has been done.  The active screen will have an * e.g. *dslist .  You can go directly to any screen listed by clicking your mouse on the desired screen name.  This feature stays turned on for your next logon and until you enter SWAPBAR OFF. You can change the name of the screen using the command such as SCRNAME SDSF. By default you get names like
    1. ISR@PRIM for the main ISPF panel
    1. ISFPCU4 for SDSF
    2. DSLIST for ISPF 3;4
    3. ISRTSO for ISPF option 6 for TSO
    4. OS390S for z/OS System Programmer Primary Option Menu
  3. When editing a file do CC CC A to copy a range of lines AFTER line A, a new feature allows the use of CC CC AK  on as many lines as wanted and then A on the last location for the copy.  Lines are copied to multiple locations with one command. So do cc, cc, ak,ak,a
  4. In ISPF use command 0 for settings then go to page 2 and change 3278 screen display to 1 for DATA vs. STD. This will automatically allow your screen to display up to 120 columns vs. only 80.
  5. In SDSF change FIND LIMIT to 99999 vs default of 5000 as this will speed up log searches.
  6. Use SRCHFOR command in 3.4 for pds/pdse files to find a ‘STRING’ in all members.
  7. Use KEYS command to change your PF KEY settings, e.g. change F9 to SWAP NEXT vs. SWAP.
  8. Use ISPF APPEND command to create a personal DSLIST of files frequently used with different DSN Qualifiers.
  9. ISPF cut and paste. You can have multiple “clipboards”, and do ASCII or EBCDIC conversion. For example CUT .a .b BOARD2 APPEND UTF8 copies the lines labelled .a to .b to clipboard BOARD2.

What can I use to edit program source in Unix Services on z/OS?

I hit this question trying to edit some Python programs on z/OS in Unix Services.

ISPF services

The easy answer for programs which are in EBCDIC or untagged, is just use ISPF edit, and you can use the HILITE command to highlight the constants and variables in the file. You can use this command to highlite, C, REXX, JCL, XML, assembler etc.

Example output for a C program.

Unfortunately although python supports EBCDIC source files, if you want to compile and package these files, they need to be ASCII files. The Unix Services command OEDIT will detect that the file as an ASCII file, and you can edit it, but not use the HILITE command.

To display the type of the file, use the Unix command ls -Tr *.py . This gave me

t ISO8859-1   T=on  cf.py        
- untagged    T=off aa.py        

Where cf.py is tagged as an ASCII file, an aa.py is an untagged file which defaults to EBCDIC.

Download to your work station

You can download ( FTP) these files to your work station, in binary and edit them. I use gedit on Linux. This has support built in for highlighting source.

IBM developer for z/OS.

This is an eclipse based package which allows you to edit data sets, submit jobs, debug programs etc. It has build in support for C, COBOL etc. When you right click on a file, you can select which editor to use, for example LPEX, a simple editor,a remote C/C++ editor, or an editor on your work station (gedit in my case).

For a python file (*.py), Eclipse downloads the file, and the choice is the eclipse simple text editor, or your workstation standard editor (gedit).

Pydev

Pydev is an Integrate Development Environment for Python on Eclipse (IBM Developer for z/OS). I had a few problems getting it working in Eclipse. (I had to use Pydev 8.2 because of incompatible Java release problem). This provides a Python editor with highlighting, and support for “twisties” where you can hide functions etc. As an editor this worked fine for most of the things I did. There were a couple of surprises.

I could not get the debugger to work, as it tried to debug running the Python program on my laptop – not on z/OS.

Whoops who over wrote my file

With all of the non ISPF techniques there is an integrity problem. If there are two people A and B and they want to edit the file at the same time.
With ISPF and ISPF

  • A edits the file
  • B is prevented from editing the file
  • A saves the updates

If A uses ISPF and B uses IBM developer

  • A edits the file
  • B edits the file
  • A saves the file
  • When B tries to save the file, it detects the last changed time stamp is different, and asks if you want to overwrite it

If A uses ISPF and B uses IBM developer

  • A edits the file
  • B edits the file
  • B saves the file, and as the last changed time stamp has not changed, the save is successful
  • A saves the file, and overwrites the changes B made.

If you use FTP or similar to download the files, there is no locking, and the last person to save will overwrite any previous updates from other people.

ISPF has autocomplete – just like a laptop!

On Linux I can use “ls D” and tab, and it lists Documents/ and Downloads/ . If I type “ls Doc” and press tab it uses autocomplete to give “ls Documents/”. This is a great way to save you typing.

I’ve just found the same function for z/OS. It has been in the product since at least 2004!

  • Set up a pf key to be AUTOTYPE ( type KEYS on the command line) I set PF6 to this
  • Go to ISPF 3.4 and type the start of a data set, for example COLIN.
  • press PF6, it gives me COLIN.JCL, press PF6 again, it gives me COLIN.MP1B.JCL

Of course you could always type COLIN.* and press enter, then tab down the list. But I thought AUTOTYPE was pretty neat.

Setting PF Keys 13 to 24

When I went to set my PF key, I found all 12 keys were allocated. How do I set keys 13 to 24?
If you use PFSHOW TAILOR it allows you to use 12 or 24 keys, and to control what is displayed.

I have my terminal emulator set up so shift PF5 is PF17, and so I set PF17 to AUTOTYPE.

Easy.

Using point and shoot keys in ISPF

ISPF has had hot keys for many years – I have only just got round to using them.

At the top of ISPF screens there is usually an action bar. For example

   Menu  Utilities  Compilers  Options  Status  Help                       
 ────────────────────────────────────────────────────
                   ISPF Primary Option Menu                           
 Option ===>                                                                   

Where the actions are Menu, Utilities etc. The underlined letter is the hot key for the action.

To select Utilities, type U on the command line and press the “Actions” PF key. This will do the same as tabbing to the Utilities action bar item, and pressing enter. For me PF10 is set to Actions.

You can display your PF Key settings using the keys or pfshow command.

For people who like to use short cuts, have your command line at the top, and use the “home” key. This will get you to the command line. So you can do: home, U, PF10 and quickly get to the Utilities action bar item.

Who develops standard?

When the GUI standards came out I wondered why the standard was to put the command line at the bottom, as there was no “go to command line” key, you had to do “Home”, then shift, tab (to do back tab). This was too many keystrokes for me.