Walking through an XEDIT Macro

The following XEDIT macro (Figure 1) is an example of the type of macro you might write to make life a little easier. The application is typical of a text processing file arrangement, where many SCRIPT files are imbedded in a master file, with the SCRIPT control word .im.

The problem with this type of setup is that if you have to make a global change throughout all the files, you have to edit each file, make the change, and then file each file.

When issued from the master file, this macro edits each file, performs a global change, and files it.

The macro is invoked by entering the macro name, GLOBCHG. The arguments passed to the macro are the old data and the new data, enclosed in delimiters:
GLOBCHG /string1/string2/
For example, if a file called MASTER SCRIPT contains:
.im FILE1
.im FILE2
   .
   .
   .
.im FILE100
and the following commands are issued:
XEDIT MASTER SCRIPT

GLOBCHG/WAR AND PEACE/SENSE AND NONSENSE/
WAR AND PEACE is changed to SENSE AND NONSENSE each time it occurs in every file. (In this macro, no attempt is made to execute the change on files that may be imbedded at the next level.)
The GLOBCHG macro can also delete data throughout the files, by changing a string to a null string, for example:
GLOBCHG /bad data//
The following is a listing of the macro, whose file ID is GLOBCHG XEDIT A1. After the listing, each line in the macro is explained. For more information on REXX statements in the macro, see z/VM: REXX/VM Reference.
Figure 1. Sample Macro

00001 /* Do a global change on imbedded Script files                     */
00002 /* Input to this macro is the CHANGE command to be executed on     */
00003 /* the file currently being xedited and on any files it imbeds.    */
00004 parse arg operand                       /* Get passed CHANGE cmd   */
00005 if operand = '' then do                 /* If omitted, then error  */
00006   emsg 'EXE545E Missing operand(s)'     /* Give error message      */
00007   parse source . . me .                 /* Get this macros name    */
00008   cmsg me                               /* Put it on command line  */
00009   exit                                  /* Leave this macro        */
00010   end                                   /* End of DO group         */
00011 preserve                                /* Save current status     */
00012 set wrap off                            /* Set wrap off            */
00013 set msgmode on                          /* Set message mode on     */
00014 set case mixed ignore                   /* Set proper case         */
00015 top                                     /* Go to TOP of file       */
00016 find .im                                /* Find first imbed file   */
00017 if rc ¬= 0 then do                      /* If none found, give msg */
00018   restore                               /* Restore previous status */
00019   emsg 'No IMBED found.'                /* Give message            */
00020   exit                                  /* Leave this macro        */
00021   end                                   /* End of DO group         */
00022 do while rc=0                           /* Imbed found, process it */
00023   extract '/curline/'                   /* Get current line        */
00024   parse upper var curline.3 . fname .   /* Separate out file name  */
00025   address command state fname 'SCRIPT *'/* Does this file exist?   */
00026   if rc ¬= 0 then do                    /* If not, issue message   */
00027     msg 'IMBEDed file' fname 'SCRIPT does not exist, bypassed.'
00028     find .im                            /* Search for next imbed   */
00029     iterate                             /* Cause next loop iterat'n*/
00030     end                                 /* End of DO group   */
00031   xedit fname 'SCRIPT (NOPROFILE'       /* File exists, XEDIT it   */
00032   extract '/fname/ftype/fmode/'         /* Get name, type, mode    */
00033   msg 'Processing file' fname.1 ftype.1 fmode.1 /* Issue message   */
00034   change operand '* *'                  /* Issue CHANGE command    */
00035   file                                  /* Save the file & quit    */
00036   find .im                              /* Find the next imbed     */
00037 end                                     /* End of DO loop   */
00038 restore                                 /* Loop ends, restore      */
00039 msg 'No more .imbeds found, global change completed.' /* Give msg  */
00040 exit                                    /* All done, leave macro   */
Now, let's walk through the macro, a line at a time.
00001-00003 /* Do a global change on imbedded Script files */
REXX comment lines. The first line of any REXX macro must be a comment line to tell the Interpreter this is a REXX file.
00004 parse arg operand
Place the passed arguments into the variable called OPERAND.
00005 if operand = " then do
If no arguments were entered when the macro was invoked, execute the following statements until an END is reached (DO group). (OPERAND was set to a null in line 4.)
00006 emsg ‘EXE545E Missing operand(s)’
Display this message.
00007 parse source . . me .
Look at the source string and place the name of this macro into the variable ME.
00008 cmsg me
The macro name (in the variable ME) is displayed on the command line.
00009 exit
Return control to the editor.
00010 end
This statement signals the end of the DO group that began in line 5.
00011 preserve
This subcommand saves the editor settings until a subsequent RESTORE subcommand is issued (line 38).
00012 set wrap off
Wrapping during the target search is turned off. When the end of the master file is reached the macro ends, rather than wrapping around, searching for .im, and getting caught in a loop.
00013 set msgmode on
Messages will be displayed. By turning the message mode on and off, you can select which messages you want displayed.
00014 set case mixed ignore
In target searches, uppercase and lowercase representations of the same letter will match.
00015 top
Move the line pointer to the top of the master file, which is the file from which the macro was invoked.
00016 find .im
Search forward in the master file for the first line that contains .im in column 1, that is, locate the first line that imbeds a file.
00017 if rc ¬= 0 then do
If there is a nonzero return code from the FIND subcommand, no .im was found, (previous statement), then do the following statements up to the END (another DO group).
00018 restore
Restore the settings of XEDIT variables to the values they had when the PRESERVE subcommand was issued (line 11).
00019 emsg ‘No IMBED found.’
Display this message.
00020 exit
Return control to the editor.
00021 end
This statement signals the end of the DO group that was started in line 17.
00022 do while rc=0
Repeat the following statements (up to the END in line 37), as long as the return code (RC) is 0. The initial value for RC is set with the FIND subcommand in line 16; this point is only reached if RC was set to 0, which means an imbedded file was found. The last statement in this loop is also a FIND subcommand, and RC is reset to the return code for that FIND subcommand just before returning to this point to execute the statements again. When the return code is not 0, this macro continues with the statement following the END (line 37).
00023 extract ‘/curline/’
Return information about the current line in macro variables, in the form curline.n, where the subscript distinguishes among the variables.
00024 parse upper var curline.3 . fname .
CURLINE.3 contains the contents of the current line (as returned by the preceding EXTRACT subcommand). In this case the current line is the .im statement that was found through “find .im.” This statement takes the second blank delimited word from the variable CURLINE.3 and puts it into the variable fname.
00025 address command state fname 'SCRIPT *'
The STATE command is a CMS command that verifies the existence of a file. This statement checks to see if the file named in the .im statement exists. The quotation marks are needed around the asterisk to avoid confusion with the REXX multiplication operator. Enclosing the word SCRIPT and the asterisk in quotation marks makes it a literal string.
00026 if rc ¬=0 then do
If the return code from the STATE command is not zero, then do the following statements up to the END statement in line 30 (DO group).
00027 msg ‘IMBEDed file’ fname ‘SCRIPT does not exist, bypassed.’
Display this message. REXX substitutes the value of fname in the message before it is displayed.
00028 find .im
This locates the next imbed control word in the file.
00029 iterate
This statement tells REXX to go to the END statement and complete the processing for this iteration of the DO loop.
00030 end
This statement signals the end of the DO group that was started in line 26.
00031 xedit fname ‘SCRIPT (NOPROFILE’
This statement invokes the editor (XEDIT) for the file specified. REXX substitutes the value of fname in this line before passing it to XEDIT.
00032 extract ‘/fname/ftype/fmode/’
Returns the file name, file type, and file mode in macro variables.
00033 msg ‘Processing file’ fname.1 ftype.1 fmode.1
Displays the message, with the file identification as returned by EXTRACT.
00034 change operand ‘* *’
The global change is executed. OPERAND contains the arguments entered when the macro was invoked (see line 4).
00035 file
The changed file is written to disk or directory.
00036 find .im
The editor resumes editing the master file, searching for the next “.im” statement.
00037 end
This statement signals the end of the DO loop that was started in line 22.
00038 restore
Restore the settings of XEDIT variables to the values they had when the PRESERVE subcommand was issued (line 11).
00039 msg ‘No more .imbeds found, global change completed.’
Display this message.
00040 exit
Return control to the editor. You can then issue a QUIT subcommand for the master file.