Interact March 1994

by Jack Bailie

MPE/iX Command File

Tips and Techniques

Enhancements to the MPE Command Interpreter (CI) in MPE/iX are among the major system improvements over MPE V. The CI has become a programming language. To use the CI in command files and UDCs effectively, however, requires knowledge of these commands and skill in using them.

Several presentations on MPE/iX command files have been given at various Interex conferences, and articles on the subject have been published in Interact. These pieces, listed at the end of this article, and Hewlett-Packard manuals present various aspects of using MPE/iX command files, and I recommend them highly.

Another way to learn about using commands is to peruse command files written by others. A number of command files can be found on your system and in the Interex Contributed Software Library. You may want to examine the following system files:

COMMAND.CSLXL

AUTOPAT.PATCHXL.TELESUP

TREELIST.PUBXL.TELESUP

MKACCT.PUB.SYS.

Very little of this information, however, covers specific techniques, commands, conventions, and standards. This article offers, by example, some tips and techniques I have adopted for command files. I will discuss style, techniques, parameters, predefined variables, help, functions, error handling, and debugging.

A better understanding of command files, or shortcuts for specific commands, can make life much easier.

Style

The few strict rules for command files are both good and bad news. The good news is that you don't have to learn and follow a lot of syntax rules. The bad news is that it is possible to write command files that are unreadable and difficult to maintain. I have adopted my own guidelines for style. Lets look at an example-a simple command file to do a LISTFILE.

    
    
    PARM fileset
    PARM format=DISC
    
    COMMENT Title: LISTFILE a file set
    COMMENT File: L.CMD
    COMMENT By: J.D. Bailie
    COMMENT Rev: 3/12/91
    
    LISTFILE fileset, !format
  

Each parameter is on a separate line. Parameter names are meaningful. (Several good reasons for this will be discussed later.) Use uppercase for keywords and commands and lowercase for variables. Blank lines may be used to separate sections of code, in this case, the parameter list from the comments and the comments from the commands. Comments are used to document the file - the who, what, when information. All these conventions make command files easier to read and maintain.

Notice from the comment that this file is named L.CMD. It is good practice to keep command files in their own group. I use CMD. The Interex CSL uses COMMAND. Either of these names (or one of your own choosing) is fine. I prefer the shorter group name.

Isolating command files in their own group prevents conflicts with other file names and makes them easier to maintain. Some system managers prefer to put their command file group in the SYS account, I don't put anything in the SYS account. I consider SYS to be HPs domain and I don't risk any chance of conflict.

You can give users access to your commands by setting the HPPATH system variable in a logon UDC to point to the command group.

The system default HPPATH is:


    !!hpgroup,PUB,PUB.SYS

but you can change the HPPATH for example:


    SETVAR HPPATH
    "CMD,PUB,!!hpgroup,PUB.SYS"

This command sets the path to the account command group, CMD, the account PUB group, the users current group, and PUB.SYS.

Parameters

The example command file above can be used as shown in the following examples:


    :L C@
    :L C@, 3
    :L FILESET=C@
    :L FORMAT=DETAIL, FILESET=C@

The first two examples use positional parameters, that is, the parameters are determined by their positions. The fileset is C@ and the format is blank or 3. The other two examples use keyword parameters. The parameters are determined by the keywords "FILESET=" and "FORMAT=". Note in the last example that the parameters are found in the reverse order from the way that they are defined in the command file.

You probably wouldn't use this technique for this particular command file; it is used only to point out the technique. If a command file has several parameters, with many that are optional, keyword parameters allow you to specify individual parameters without having to remember the parameter positions or count commas. Using meaningful parameter names, as suggested earlier, makes using keyword parameters easier.

ANYPARM

I have searched the LASER ROM CD and have concluded that, for some unknown reason, Hewlett-Packard has not documented the ANYPARM parameter. ANYPARM can be used instead of PARM as the last parameter of a command file. In the example file above, we could substitute:

  
    ANYPARM format=DISC

ANYPARM captures everything that is entered beyond the last parameter separator, including any punctuation and spaces. As with a regular parameter, it can be assigned a default value. By substituting the ANYPARM parameter specification in our example, we can now execute the command as:


    :L C@, DETAIL; PASS

Now the format argument becomes


    DETAIL; PASS

and the LISTFILE command becomes


    LISTFILE C@, DETAIL; PASS

If the user has sufficient capability, the PASS parameter will cause the command to display file lockwords and creators.

HELP

The MPE HELP command can be used with command files. For our example command file, the MPE HELP would be:


    USER DEFINED COMMAND FILE: L.CMD.CAPS
    
    PARM fileset=@
    ANYPARM format=DISC
    COMMENT Title: LISTFILE a file set
    COMMENT File: L.CMD
    COMMENT By: J.D. Bailie
    COMMENT Rev: 3/12/91
    LISTFILE fileset, !format

MPE HELP shows that it is a user-defined command file and gives the name of the file and its entire contents (except for the blank lines we added for readability). For complex command files, this can be confusing and very little help to users who do not understand command programming.

You can make MPE HELP a little more useful by adding comments that describe the use of the command to the command file. For instance:


    COMMENT
    COMMENT L - LISTFILE a fileset
    COMMENT
    COMMENT Syntax
    COMMENT   :L fileset [,format]
    COMMENT
    COMMENT Parameters
    COMMENT   fileset - The file[set] to LISTF; default @
    COMMENT   format - The LISTFILE format; default DISC
    COMMENT

Using this technique, MPE HELP will list the comments, giving the user more information. The disadvantage is that it still lists the entire contents of the command file, which may confuse the user.

A better technique is to use ECHO commands to provide the command help. For example:

  
    PARM fileset=?
    ANYPARM format=DISC
    
    IF "!fileset" = "?" THEN
      ECHO
      ECHO L - LISTFILE a fileset
      ECHO
      ECHO Syntax
      ECHO   :L fileset [,format]
      ECHO
      ECHO Parameters
      ECHO   fileset - The file[set] to LISTF; default @
      ECHO   format  - The LISTFILE format; default DISC
      ECHO
   
    ELSE
      LISTFILE !fileset, !format

    ENDIF

Notice that the first parameter of the command has been given a default value of "?". If the command is used without any parameters or if it is used with a question mark, the ECHO commands show the user the description of the command.

The output would look like:


    L - LISTFILE a fileset
    
    Syntax 
      :L fileset [,format]
    
    Parameters 
      fileset - The file [set] to LISTF; default
      format  - The LISTFILE format; default DISC

This technique is much clearer and provides only the information the user needs.

To shorten the examples that follow, I will leave out the help code. However, I recommend that you always include help, except in the very simplest command files.

Variables

Let's shift gears now and look at variables. We'll look at an example named FIND. We are going to build on this example through the next several topics.

  
  PARM file
  
  LISTFILE !file, QUALIFY
  SETVAR _find_creator FINFO('!file','CREATOR')
  ECHO Creator is !_find_creator
  DELETEVAR _find_@

This example uses the SETVAR command to set the value of a variable. In this case, since the name of the command file is FIND, I use a variable name that begins with " _ find". This naming convention ensures that variables in the command file do not conflict with variable names in other command files called by your command file. It also makes it very easy to clean up after yourself at the end of the command file. You can delete all variables that begin with the command the name preceded and followed with underlined characters.

The above example uses the FINFO function. FINFO allows you to find 44 different things about a file, such as the EOF, whether the file exists, the creator, various dates, the size, etc. Appendix B of the Commands Reference Manual gives a complete description of the FINFO function.

FINFO has two arguments. The first one is a character string. In this example, the first argument of FINFO is a command file parameter that must be enclosed in quotes and preceded with the exclamation mark. (We'll look at other kinds of arguments in later examples.)

The second argument of FINFO determines the data to be returned. This argument may be either an integer number or a character string describing the data. I much prefer the character string because it documents the command file better. However, some of the character strings are obnoxiously long and it's easier to put in a comment than to use the designated string.

Prompting for Parameters

Another effective technique is to prompt the user when parameters are not entered. For example:


    PARM file=' '
    
    IF '!file, THEN
      INPUT _find_file;PROMPT='Enter a file name ';WAIT=60
    ELSE
      SETVAR _find_file '!file'
    ENDIF
   
    SETVAR _find_creator FINFO(_find_file,'CREATOR') 
    LISTFILE !_find_file, QUALIFY
    ECHO Creator is !_find_creator
    DELETEVAR _find_@
  

Prompting may be used either as an alternative to, or in addition to, command file help. If the user answers a file name, the command continues. If not, the user is prompted to enter a file name.

Notice the "WAIT" parameter on the INPUT command. This will cause the command to wait for input (up to 60 seconds in this case) and then continue execution if the input is not entered.

In this example, the first argument of FINFO is a variable that has been set to a sting. It is not necessary to use quotation marks or an exclamation point.

INPUT from a Flat File

In the next example the INPUT command is used to read from a flat file by redirecting the command input.


    PARM file
    
    SETVAR _find_creator FINFO('!file','CREATOR')
    INPUT _find_line < !file
    LISTFILE !file, QUALIFY
    ECHO Creator is !_find_creator
    ECHO First Line is
    ECHO !_find_line
    DELETEVAR _find_@

When used this way, the INPUT command reads only the first line of the file. No matter how many INPUT commands you execute, you will always read the first line of the file.

I have found this feature useful for our FORTRAN source files. FORTRAN 77 has a VERSION directive that allows you to include a text string in your code that is carried through to the object code. The text string in the object code can be displayed using the VERSION program (in PUB.SYS). We put a $VERSION directive as the first line of all FORTRAN source files. The text string includes the file name, version number, date, programmer's name, and destination of the object module (i.e., XL, NMRL, or program). We have a single command file for compiling. It reads the $VERSION statement, compiles the code and then, based on the $VERSION text string, does the LINKEDIT step to add the module to the appropriate XL, RL, or links it as a program. Using the same command for all compiling greatly simplifies compiling. The VERSION information documents both the source and object files.

INPUT from a Message File

As each line is read from a message file, it is removed and the following line becomes the first line. So, although the INPUT command will read only the first line of a flat file, it can be used in a loop to read all of the lines from a message file.

This example does a LISTFILE to a message file and then reads the message file to get me names of each of the files in the file set. This provides a customized LISTFILE, providing you have sufficient capability to access the file creator information.


    PARM fileset
    
    FILE FINDTEMP;MSG
    LISTFILE !fileset,QUALIFY > *FINDTEMP
    RESET FINDTEMP
    
    WHILE (FINFO('FINDTEMP','EOF') > 0) DO
      INPUT _find_file < FINDTEMP
      SETVAR _find_file RTRIM(_find_file)
      SETVAR _find_creator FINFO(_find_file,'CREATOR')
      ECHO !_find_file !_find_creator
    ENDWHILE
    
    DELETEVAR _find_@
    PURGE FINDTEMP,TEMP

In the first use of FINFO, to determine the number of records in the LISTFILE file, the first argument of FINFO is the file name, which is enclosed in quotation marks. In the second use of FINFO, to determine the creator, the argument is a variable and is not enclosed in quotes.

Notice also that it is necessary to use the RTRIM function to trim blanks from the right end of the file names read from the message file. You must do so because the INPUT from the file is a 128-character string, but the FINFO function can accept only a file name of 1 to 28 characters.

Style

I will point out some more elements of style in the above example. For example, I use parentheses around the WHILE statement conditions. The CI does not require this; it's just a preference of mine, probably from my FORTRAN background. I also indent the WHILE statement logic. That's pretty standard in most languages. The "DO" keyword in the WHILE statement is optional. I use it for clarity. Lastly, I always clean up after myself by deleting variables and purging any files that were created.

INPUT from a Flat File

A few paragraphs back, I noted that the INPUT command would read only the first line of a file. Well, there is a way to use it to read the other lines too. Consider the following two example command files.

The first command file, FIND, does a LISTFILE to a temporary file, FINDTEMP, and then executes the second command file, FINDIT, telling it to read its input from the FINDTEMP file.

Example command file FIND.CMD:


    PARM fileset=@
    
    LISTFILE !fileset,QUALIFY > FINDTEMP
    XEQ FINDIT < FINDTEMP
    PURGE FINDTEMP,TEMP

The second command file, FINDIT, has no parameters. It is called from the other command file and obtains its input from the FINDTEMP file. It determines how many records are in the FINDTEMP file, and then loops, using the INPUT function to read one record at a time from the file.

Example command file FINDIT.CMD:


    SETVAR _find_i 1
    SETVAR _find_eof FINFO('FINDTEMP','EOF')
    WHILE (_find_i <= _find_eof) DO
      SETVAR _find_file INPUT()
      SETVAR _find_file RTRIM(_find_file)
      SETVAR _find_creator FINFO(_find_file,'CREATOR')
      ECHO !_find_file !_find_creator
      SETVAR _find_i _find_i + 1
    ENDWHILE
    DELETEVAR _find_@

This command file accomplishes exactly the same thing as the previous one, but it executes approximately three times faster. I suspect it is faster because the message file system is still (as of 4.0) in compatibility mode. The main disadvantage of this technique is that it requires two command files.

Entry Points

This next example accomplishes the same function as the last one, but it requires only one command file. It uses a technique commonly called "entry points" to provide two separate sections of code in the same command file. An "entry" parameter is tested to determine which section of the code is to be executed.

  
    PARM fileset=@
    PARM entry=MAIN
    
    IF ('!entry' = 'MAIN') THEN
      LISTFILE !fileset,QUALIFY > FINDTEMP
      XEQ FIND ENTRY='NOTMAIN' < FINDTEMP
      PURGE FINDTEMP,TEMP
    
    ELSE
      SETVAR _find_i 1
      SETVAR _find_eof FINFO('FINDTEMP','EOF')
    
      WHILE _find_i <= _find_eof) DO
        SETVAR _find_file INPUT()
        SETVAR _find_file RTRIM(_find_file)
        SETVAR _find_creator FINFO(_find_file,'CREATOR')
        ECHO !_find_file !_find_creator
        SETVAR _find_i _find_i + 1
      ENDWHILE
    
    ENDIF
    
    DELETEVAR _find_@

The first section of code, the "MAIN" entry, does the LISTFILE to the temporary file, FINDTEMP. It then executes the same command file again, passing "NOTMAIN" as the entry argument. This time the second section of code executes to find the number of records in the FINDTEMP file. It then uses the INPUT function to read the records of FINDTEMP. When this section of code is complete, it returns and the first execution of the command file resumes execution at the statement following the XEQ purges FINDTEMP, and deletes the variables.

One disadvantage of the entry point technique is that it requires the name of the file to be embedded in the file. This makes it inconvenient to rename the command file if you don't happen to like the name it was given originally. We'll look at a solution to this later.

SETVAR Function in WHILE

The next example is the same as the last one except that it shows a slightly different technique for incrementing the WHILE loop counter. It uses the SETVAR function within the WHILE statement to increment the loop counter instead of the SETVAR command at the end of the loop.



    PARM fileset=@
    PARM entry=MAIN
    
    IF ('!entry' = 'MAIN') THEN
      LISTFILE !fileset,QUALIFY > FINDTEMP
      XEQ FIND ENTRY='NOTMAIN' < FINDTEMP
      PURGE FINDTEMP,TEMP
    
    ELSE
      SETVAR _find_i 0
      SETVAR _find_eof FINFO('FINDTEMP',IEOF')
     
      WHILE (SETVAR(_find_i,_find_i+l) <= _find_eof) DO
        SETVAR _find_file INPUT()
        SETVAR _find_file RTRIM(_find_file)
        SETVAR _find_creator FINFO(-find_file,'CREATOR')
        ECHO !_find_file !_find_creator
      ENDWHILE
    
    ENDIF
    
    DELETEVAR _find_@

FINFO Function in WHILE

This next example also accomplishes the same function as the last few. It combines the SETVAR and FINFO functions into the WHILE statement. I have included this example because I have seen this technique used by others.

  
    PARM fileset=@
    PARM entry=MAIN
    
    IF ('!entry' = 'MAIN') THEN
      LISTFILE !fileset,QUALIFY > FINDTEMP
      XEQ FIND ENTRY='NOTMAIN' < FINDTEMP
      PURGE FINDTEMP,TEMP
    
    ELSE
      SETVAR_find_i 0
      WHILE SETVAR(_find_i,_find_i+l) <= FINFO('FINDTEMP','EOF')
        SETVAR _find_file INPUTO
        SETVAR _find_file RTRIM(_find_file)
        SETVAR _find_creator FINFO(_find_file,'CREATOR')
        ECHO !_find_file !_find_creator
      ENDWHILE
    
    ENDIF
   
    DELETEVAR _find_@

It is possible to combine multiple functions together in single statements. This technique will shorten command files; however, the statements begin to become difficult to understand. Also, in this particular example, the statement becomes less efficient because the FINFO function is re-executed each time the loop is executed. This is less efficient than determining the number of records before starting the loop.

Handling Error Conditions

Up to this point, for simplicity, I have ignored testing for error conditions in the example command files. (What if files do not exist or there are no files in the file set, etc.?) Good command files test for all possible error conditions, and good coders test command files for all possible errors.

For example, in one of our previous examples, we could use the FINFO function to determine if a file exists with something like:

  
    PARM fileset
    
    LISTFILE !fileset,QUALIFY > FINDTEMP
    IF (FINFO('FINDTEMP','EXISTS')) THEN
      . . . 
    
    ELSE
      ECHO
      ECHO No files in the fileset !fileset
      ECHO
    ENDIF
  

or we could clear and then test the HPCIERR variable to determine if the file exists, i.e.,

  
    PARM fileset
   
    ERRCLEAR
    LISTFILE !fileset,QUALIFY > FINDTEMP
    IF (HPCIERR = 0) THEN
      . . . 
    
    ELSE
      ECHO
      ECHO No files in the fileset !fileset
      ECHO
    ENDIF
  

The ERRCLEAR command clears the variables CIERROR, HPCIERR, HPCIERRCOL, and HPFSERR.

Fancy Error Messages

You can add highlighting to your error messages to make them stand out better with something like:


    ECHO
    ECHO ![CHR(27)+"&dB"] No files in !fileset ![CHR(27)+"&d@"]
    ECHO
  
    ![CHR(27)+"&dB"] turns on highlighting and 
    
    ![CHR(27)+"&d@"] turns it off.

If you have several different error messages that require highlighting, you can set variables for the enhancement strings. This makes the files easier to read, not to mention easier to type.


    SETVAR ON CHR(27)+"&dB"
    SETVAR OFF CHR(27)+"&d@"
    
    ECHO
    ECHO !on No files in ![UPS("fileset")] !off
    ECHO

In this example the UPS function is used to up shift the input argument, a technique that helps to emphasize the error output. An error message from this command might look like:

    No files in X@.CMD

Other Error Conditions

Another type of error condition that must be accounted for is the deletion of variables when no variables have been set. For instance, the following command:


    DELETEVAR _find_@

would result in the message:


    "NO MATCH FOUND FOR THIS VARIABLE SET"

if there were no variables in the variable set. This message would be meaningless and annoying to the command file user. To suppress this type of message, since you really don't care anyway, you can redirect the output of the command to $NULL, i.e.,


    DELETEVAR _find_@ > $NULL

Choosing Your Own Command Name

If you execute the command "!-I" at a colon prompt, it is equivalent to the "DO" command. The command


    SETVAR _my_name "!-1"

results in a variable string containing the last command executed. If you put this command as the first command in a command file, the variable is set to the command that was entered to execute the command file.

The following commands can be used to obtain the name of the command file:


    SETVAR _my_name "!-1"
    SETVAR _my_name UPS(_my_name)
    
    IF POS("XEQ",_my_name) > 0 THEN
      SERVAR _my_name _my_name - "XEQ"
    ENDIF
    
    SETVAR _my_name LTRIM(_my_name)
    
    IF POS(" ",_my_name) > 1 THEN
      SETVAR _my_name LFT(_my_name,POS(" ",_my_name)-1)
    ENDIF

These commands up shift the input, strip off "XEQ" (if it was used), strip off leading blanks, and strip off any arguments that were entered, leaving a variable with the name of the command file.

Now, looking back at the multi-entry point FIND command file mentioned earlier, we could replace the line


    XEQ FIND ENTRY='NOTMAIN' < FINDTEMP

with,


    XEQ !_my_name, ENTRY="NOTMAIN" < FINDTEMP

resulting in the following code:


    IF ('!entry' = 'MAIN') THEN
      LISTFILE !fileset,QUALIFY > FINDTEMP
      XEQ !__my_name, ENTRY="NOTMAIN" < FINDTEMP
      PURGE FINDTEMP,TEMP
    ELSE

Now the command file is independent of its own name. Anyone can rename the file and it will still work. I'll call it FIND, and you can call it WHEREIS.

We can even include the following in the help section of the command file to give the proper command name with the help:


    ECHO !_my_name - LISTF a fileset with Creators name

Continuation Lines

Just as you can use an ampersand to continue a command beyond one line in a session, you can also use ampersands to continue commands in a command file. Sometimes, when commands get too long or have multiple parallel phrases, it is more readable to continue the commands on multiple lines. For example:


    PARM what=" "
    
    SETVAR _S_WHAT UPS("!what")
    
    IF ("!_s_what" = " " &
     OR "!_s_what" = "S" &
     OR "!_s_what" = "J" THEN
      SHOWJOB JOB=@!_s_what
      RETURN
    
    ELSEIF ("!_s_what"' = "M") THEN
      SHOWME
      RETURN
    
    ELSEIF ("!_s_what" = "0") THEN
      SPOOLF @;SHOW
      RETURN
    
    ENDIF

This example also shows the use of the ELSEIF command with multiple commands in a single command file. This is a convenient way to consolidate multiple SHOW commands in one file, I actually include SHOWME, SHOWTIME, SHOWJOB, SHOWDEV, SHOWCOPIOG, SHOWOUT, SHOWQUEUE, SHOWOAR, and a few other custom SHOWs in my command file.

When you combine multiple commands like this in a file, it’s a good idea to put a RETURN statement at the end of each section. This interrupts the command at be point it is logically finished and spares the CI from interpreting the remainder of the file (and spares the user from waiting around for it to finish).

System Message Spacing

The following is excerpted from CHKDAT.COMMAND.CSLXL, a Contributed Library command file to check the status of a DAT tape drive.


    SHOWDEV !ldev > CKTEMP
    . . .
    SETVAR _chkdat_avail STR(_chkdat_ckin,11,1)
    SETVAR _chkdat_vol STR(_chkdat_ckin,43,1)
    SETVAR _chkdat_den STR(_chkdat_ckin,57,1)
   
    IF _chkdat_avail = "A" AND _chkdat_vol = "(" AND &
    (_chkdat_den = "1" OR _chkdat_den = "6") THEN
      . . .

>It checks specific columns (11, 43, 57) of output from the SHOWDEV command. Between MPE/XL 3.1 and 4.0, the format of me SHOWDEV command was changed so the CHKDAT command file no longer worked. You need to be aware of this eventuality anytime you rely on the spacing of MPE output. From what I have read, I expect that there will be changes in the output of numerous commands in Release 4.5.

Purging Files

If you issue the command


    PURGE !file

and the file does not exist, you receive an error message.

As an alternative, you could use something like this:


    SETVAR _find_savemsg HPMSGFENCE 
    SETVAR HPMSGFENCE 2
    PURGE !file
    SETVAR HPMSGFENCE _find_savemsg

By setting the HPMSGFENCE variable to 2, the error message is suppressed. However, if the user aborts the command file while the message fence is suppressed, it will stay suppressed and the user will see no error messages until after they call you to find out what happened and you have them reset it.

By using FINFO to determine if the file exists and executing only the PURGE command if it does, you avoid these pitfalls, i.e.,


    IF (FINFO("!file","EXISTS")) THEN

An even simpler method is to redirect the PURGE command to $NULL:


    PURGE !file > $NULL

This technique works just as well and requires only one line.

Debugging

An invaluable aid in debugging command files is the HPCMDTRACE variable. You can set or unset HPCMDTRACE interactively. While it is TRUE, it lists every command executed. You need to remember to turn it off when you are finished debugging, although it's pretty obvious when it's on and when you are executing a command file.

Another debugging technique is to use OPTION LIST and OPTION NOLIST commands. In MPE V, these statements could be used only in the header of a UDC. In MPE/iX they can be used at any point in a command file. Whenever LIST is on, all commands executed are listed. When it is off, they are not. By using these commands, you can list commands in selected parts of your command file.

For more sophisticated debugging, particularly when you may want to leave the debugging tool in the code but have it transparent to the normal user, you can add a debug parameter to the command file, i.e.,


    PARM debug=O
    
    IF (!debug > 0) THEN
      SETVAR HPCMDTRACE TRUE
      SETVAR HPMSGFENCE 0
      SHOWVAR
    
    ELSEIF !debug = 0 THEN
      PURGE FINDTEMP,TEMP > $NULL
    
    ENDIF

To execute the command in debug mode, specify the debug parameter by keyword,


    :FIND C@, DEBUG=1

The command file can display selected, variables and can even skip the purging when in debug mode.

Documentation

If you expect your users to know and use your COMMAND files, you need to document them. In addition to the ECHO help in command files, we have a documentation file for each command. They are kept with the same name as the command in the DOCCMD group.

In addition, our editor, FSEDIT, allows us to put a 64-character description with a file. The description is kept in the first user label of the file. I also added this capability to the CSL program GSCAN. All of our command files have these one-line descriptions. We use a command file, DESCR, which is similar to the FIND examples I have been discussing to display the descriptions. Listing 1 is a listing of the DESCR command file. The help for DESCR is:


    DESCR - List files in a fileset with Descriptions
    Syntax
    :DESCR - [fileset] [,find-string]
    Parameters
    fileset - The HP fileset; default @.CMD
    find-string - A string to search for

Example output from the DESCR command


    Files in the fileset A@.CMD with FSEDIT Descriptions
    A - ABORT command file
    ACCTINFO - Formatted output of Systems Accounting Structure
    ADDR - Print address lables
    AJ - ABORTJOB
    AS - Alter spool file PRI to 12 so it will print

Conclusion

Hopefully, you now have a better understanding on MPE/iX Command files and will be able to use some of the techniques discussed here to make your work easier. I recommend strongly that you find your old copies of Interact and read the articles in the reference list, which offers a wealth of additional information.

References

  
    IMPE XL Commands Reference Manual 32650-90003
    CI Access and Variables Programmer's Guide 32650-90011
    
    Interact   Page   Title / Author
    Nov, 1988   44   "New Features of MPE XL Users Interface," Thomas Shem and Jeff Vance
    Sept, 1989  26   "Life of an MPE XL Command," Scott Cressler and Jeff Vance
    Mar, 1990   96   "Programming with MPE XL," Heikki Taskinen
    Feb, 1991   83   "Advanced CI Programming, the 2.1 Story," Scott Cressler, Jeff Vance, Steve Elmer
    Sept, 1991  86   "MPE XL Command Files," Fred Ochs, Jr.
    Nov, 1992   26   "Creating Command Files," Rene Martinez
    Nov, 1992   78   "What the Manuals Don't Say," John Dunlop

Jack Bailie is a Technical Advisor with Exxon Company, U.S.A. He supervises the Production Department, Headquarters, Technical Services Computer Automated Procduction System (CAPS) group.

He has been involved with CAPS since 1968 and is currently supervising the conversion of four HP 3000s from Series 70s to 927s.

Listing 1 - DESCR.CMD

  
  PARM fileset="@.CMD", find =" ", entry=MAIN
  
  IF "!fileset" = "?" THEN
    SETVAR S,CHR(14)
    SETVAR B CHR(14)+':'+CHR(15)
    ECHO
    ECHO ![S+'R,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,T']
    ECHO ![B+' DESCR - List files in a fileset with FSEDIT Descriptions '+B]
    ECHO ![S+'199999999999999999999999999999999999999999999999999999999999999992']
    ECHO ![B+' '+B]
    ECHO ![B+' Syntax '+B]
    ECHO ![B+' :DESCR fileset [,find_string] '+B]
    ECHO ![B+' '+B]
    ECHO ![B+' Parameters '+B]
    ECHO ![B+' fileset - The fileset to look at; default @.CMD '+B]
    ECHO ![B+' find_string - a string to search for '+B]
    ECHO ![B+' '+B]
    ECHO ![S+'F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;G']
    DELETEVAR S,B
    RETURN
  ENDIF

  IF '!entry' = 'MAIN' THEN
    ERRCLEAR
    SETVAR _descr_find '!find'
    LISTFILE !fileset,QUALIFY > DESCRTMP
    SETVAR _descr_i 0
    IF HPCIERR = 0 THEN
      SETVAR _descr_eof FINFO('DESCRTMP','EOF')
      ECHO Files in the fileset !fileset with FSEDIT Descriptions
      ECHO
      XEQ DESCR ENTRY='NOTMAIN' < DESCRTMP
   
    ELSE
      ECHO File !fileset NOT found
   
    ENDIF
      PURGE DESCRTMP,TEMP
      DELETEVAR _descr_@
  
  ELSE
    WHILE SETVAR(_descr_i,_descr_i+1) <=_descr_eof DO
      SETVAR _descr_file INPUT()
      COMMENT Does it have User Labels Written?
      IF FINFO(_descr_file,10) > 0 THEN
        COMMENT Yes, read the fisrt user label
        SETVAR _descr_file_descr RHT(FINFO(_descr_file,25),64)
        IF LFT(_descr_file_descr,1) < " " OR &
           LFT(_descr_file_descr,1) >= "}" THEN
           SETVAR _descr_file_descr RPT(".",64)
        ENDIF
       
        SETVAR _descr_len 9-POS(".",_descr_file)
        SETVAR _descr_file_descr RTRIM(_descr_file)+ &
        RPT(" ",_descr_len)+" - "+_descr_file_descr
        IF _descr_find <> " " THEN
          IF POS(UPS(_descr_find),UPS(_descr_file_descr)) <> 0 THEN
            ECHO !_descr_file_descr
          ENDIF
       
        ELSE
          ECHO !_descr_file_descr
        ENDIF
      
      ENDIF
    ENDWHILE
  ENDIF