Editor's note! This file has been converted from Word Perfect, and still needs some cleanup! (coming soon...) TUTORIAL A Beginner's Guide to UDCs and JCWs: How to Use Them to Your Benefit (MPE XL Edition) David L. Largent The N.G. Gilbert Corporation 700 South Council P.O. Box 1032 Muncie, Indiana 47308-1032 U.S.A. Telephone 317/284-4461 Facsimile 317/288-2125 Telex 361285 Copyright 1988, 1991, 1992 David L. Largent TUTORIAL A Beginner's Guide to UDCs and JCWs: How to Use Them to Your Benefit (MPE XL Edition) Table of Contents 1 Introduction -- "Is this for me?" . . . . . . . . 1 1.1 About this tutorial -- "So tell me, what's new?". 2 2 What are UDCs?. . . . . . . . . . . . . . . . . . 2 2.1 A brief comparison of UDCs and Command Files. . . 3 2.2 How can UDCs help me? . . . . . . . . . . . . . . 4 2.3 How do I create a UDC?. . . . . . . . . . . . . . 5 2.3.1 Defining the UDC. . . . . . . . . . . . . . 5 2.3.1.1 The header section.. . . . . . . . . . . 6 2.3.1.2 The execution options section. . . . . . 8 2.3.1.3 The body section.. . . . . . . . . . . . 11 2.3.1.4 The UDC separator section. . . . . . . . 14 2.3.2 Put your UDC definitions in a UDC file. . . 14 2.3.3 Account-level and system-level UDCs.. . . . 15 2.3.4 Telling the system about your UDC file(s).. 17 2.3.4.1 Cataloging your first UDC file(s). . . . 18 2.3.4.2 Appending UDC files to those already cataloged. 19 2.3.4.3 Disabling individual UDC files.. . . . . 20 2.3.4.4 A couple seldom-used SETCATALOG parameters. 21 2.3.4.5 SETCATALOG use by account or system managers. 21 2.4 How do I alter a UDC file after it has been cataloged? 23 2.5 What happens when I logon and have some UDCs enabled? 23 2.6 How do I find out what UDCs are available?. . . . 24 2.7 How about some examples?. . . . . . . . . . . . . 26 2.8 What are some problems I may have while using UDCs? 36 2.9 Are we done with UDCs yet!?!. . . . . . . . . . . 38 3 What are JCWs?. . . . . . . . . . . . . . . . . . 38 3.1 A brief comparison of JCWs and session-level variables. 38 3.2 How can JCWs help me? - or - Why would I want a program to talk to my commands?. . . . . . . . . . . . . . . . . . . . . . . . . 39 3.3 OK, I think I see how they could help me. So, how do I create and use a JCW? . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.3.1 User-defined JCWs.. . . . . . . . . . . . . 39 3.3.2 System-defined JCWs.. . . . . . . . . . . . 40 3.3.3 System-reserved JCWs. . . . . . . . . . . . 40 3.3.4 JCW usage in jobs and/or sessions.. . . . . 41 3.3.4.1 The SHOWJCW command. . . . . . . . . . . 41 3.3.4.2 The SETJCW command.. . . . . . . . . . . 42 3.3.4.3 The DELETEVAR command. . . . . . . . . . 43 3.3.4.4 The JCW value mnemonics. . . . . . . . . 44 3.3.5 JCW usage in programs.. . . . . . . . . . . 45 3.3.5.1 The FINDJCW intrinsic. . . . . . . . . . 45 3.3.5.2 The PUTJCW intrinsic.. . . . . . . . . . 47 3.3.5.3 The HPCIDELETEVAR intrinsic. . . . . . . 48 3.3.5.4 Interprocess communication with JCWs.. . 50 3.3.5.5 The GETJCW and SETJCW intrinsics.. . . . 50 3.4 How about some examples?. . . . . . . . . . . . . 50 3.4.1 Batch job examples. . . . . . . . . . . . . 50 3.4.2 Programmatic examples.. . . . . . . . . . . 54 3.5 What are some problems I may have while using JCWs? 56 4 How can I use UDCs and JCWs together? . . . . . . 57 4.1 Examples of combining UDCs and JCWs.. . . . . . . 57 5 Closing thoughts -- "Is it worth the effort of learning something new?" 62 Acknowledgements . . . . . . . . . . . . . . . . . . . . . 63 Bibliography . . . . . . . . . . . . . . . . . . . . . . . 64 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . 66 TUTORIAL A Beginner's Guide to UDCs and JCWs: How to Use Them to Your Benefit (MPE XL Edition) David L. Largent The N.G. Gilbert Corporation 700 South Council P.O. Box 1032 Muncie, Indiana 47308-1032 U.S.A. Telephone 317/284-4461 Facsimile 317/288-2125 Telex 361285 Copyright 1988, 1991, 1992 David L. Largent 1 Introduction -- "Is this for me?" How many times have you forgotten to issue a "FILE" command before running a program? How often have you typed a FILE command wrong? Do you ever get tired of typing "SPOOLF spoolid; DELETE"? Have you been looking for a way to make your jobstreams a little "smarter?" Would a way to automate some of your procedures be helpful? If you have any of these problems and have never considered using UDCs and/or JCWs, now is the time to do so. If you are like me, you have known UDCs and JCWs existed, but thought they were some difficult, mysterious, (impossible?) thing to master. This is not so! On the following pages will be found answers to questions relating to User Defined Commands (UDCs) and Job Control Words (JCWs) such as: What are they? How can they help me? How are they created? How are they used? What are some common problems that arise? Are they worth the effort of learning something new? To find the answers, we will first examine what UDCs are and how they are created and used. We will look at numerous UDC examples to reinforce your learning. Next, we will examine JCWs in detail. And lastly, we will look at how to use JCWs and UDCs together effectively to create a synergism of the two. This tutorial is directed at new users of an HP3000 MPE XL computer system who have not yet explored the world of UDCs and/or JCWs. However, any user may find some tidbits to put in his or her "tool box" that will prove useful either now or in the future. This tutorial assumes you have a general knowledge of the HP3000; specifically, the following are "prerequisites": Knowledge of the HP3000 accounting structure (i.e., File/Group/Account/User). Knowledge of how to use an ASCII text editor (e.g., EDIT/3000). Knowledge of many MPE XL system commands and how to use them. Knowledge of jobstreams and how to use them. 1.1 About this tutorial -- "So tell me, what's new?" This tutorial is based on my award-winning MPE V-based tutorial of the same name, and my award-winning MPE V-based paper JCWs: An Underutilized MPE Feature, both presented at past INTEREX conferences. This version reflects information as it pertains to the MPE XL operating system. The information provided here is correct and up-to-date (to the best of my knowledge) and reflects the way UDCs and JCWs are used and work as of the A.41.01 release of MPE XL (2.2). For better or worse, I am yet to make the jump to a more recent version of MPE XL (excuse me... MPE/iX). Also note that I will continue to refer to the operating system as XL rather than iX in this tutorial. I've barely gotten used to calling it XL and now they're changing it again! The MPE XL operating system does a wonderful job of pretending that it's good ol' MPE V. There are, however, a number of new commands, added functionality, and just plain different ways of getting things done which make MPE XL a much richer and more enjoyable operating system to work with. A few of the new items that relate to this tutorial's subject matter include: Another way to specify UDC parameters (PARM) A non-parsed parameter for UDCs (ANYPARM) Recursion for UDCs (OPTION RECURSION) Programmatic access to UDCs (OPTION PROGRAM and HPCICOMMAND) Deletion of JCWs (DELETEVAR and HPCIDELETEVAR) A looping structure (WHILE and ENDWHILE) New I/O commands (INPUT, ECHO and PRINT) Additional SETCATALOG parameters (APPEND, DELETE and RESET) Command Files Variables All of these items will be touched upon in this tutorial -- some in a great deal of detail; others just in passing. 2 What are UDCs? UDC is one of many acronyms used in the HP3000 world. This one comes from the phrase User Defined Command. A UDC is a command designed for the user's convenience. It is made up of MPE XL system commands, command file references, and/or other UDCs. A UDC can replace a single, long command or a long sequence of many commands. UDCs provide a short cut (a more precise way!?!) to accomplish some particular task. By entering the UDC name, the predefined commands are automatically executed. Think of them as just another MPE XL system command. 2.1 A brief comparison of UDCs and Command Files. Another MPE XL feature, the Command File, is very similar to UDCs in that Command Files can execute several commands in response to a single command. Most of the options available for UDCs are also available for Command Files. Some instances may dictate the use of a UDC. In many situations, however, a Command File may work as well, or better than a UDC. In general, Command Files are a bit easier to work with than UDCs. They do lack some of the added capabilities of UDCs, however. With time and experience you will come to learn the best tool to use for the task at hand. I encourage you to learn all you can about Command Files from other references -- they do have their place in the scheme of things. An in-depth study of Command Files will not be provided here. However, the following tables are offered for your information. Many of the items will make more sense after reading the following pages. The entries in the tables are not being presented as advantages or disadvantages, but rather as comparisons of UDCs and Command Files. Which is the better tool for a given situation is left for you to determine. Comparison of User Defined Commands (UDCs) and Command Files Execution Considerations User Defined Commands Command Files Invoked by typing the name provided Invoked by typing the command in the header section of the UDC. file's file name. Automatic execution at logon time Automatic execution at logon time is available. is not available. Executed before MPE XL system Executed after UDCs and MPE XL commands and command files. system commands (unless XEQ is May override CI commands. used). May not override CI commands. User-, account-, and system-level Only "user-level" definitions are definitions are available. available. (Easy access at any level could be established with the PATH command.) SHOWCATALOG lists currently Cannot easily list currently available UDC names. available command file names. UDC file is more secure. (More Command file is less secure. difficult to purge or alter a UDC (Easier to purge or alter command file.) file.) Best used for production or stable Best used for testing, command definitions. development, or frequently changing command definitions. Comparison of User Defined Commands (UDCs) and Command Files Content Considerations User Defined Commands Command Files Multiple command definitions are Only one command definition is allowed per file. allowed per file. Header section is required. Contains no header section. May have long, descriptive command Command name is limited to eight name. characters (the file name). Comparison of User Defined Commands (UDCs) and Command Files Maintenance Considerations User Defined Commands Command Files Cataloging of the UDC file(s) is Command files are not cataloged; required before use. available immediately after creation. Must un-catalog the UDC file before May make changes to, or purge the making changes to, or purging the command file directly. file. May provide better organization of Organization may not be as good commands (fewer files). (more files to keep track of). System resource use is heaviest at System resource use is heaviest logon time. at command file execution time. Less disk space is required. More disk space is required. 2.2 How can UDCs help me? A UDC can be used in almost any situation where an MPE XL system command is used, even within another UDC. They can be used in both sessions and jobstreams. Under some circumstances, they can be executed from within programs and subsystems, and when you are in BREAK. UDCs are perfect solutions for many "problem" situations. A long sequence of MPE XL system commands can be replaced by a single UDC name, thus decreasing the time it takes to accomplish the task (less typing), and also eliminating typing errors. A lengthy command like "SPOOLF spoolid; DELETE" can be replaced by a UDC name such as "RPUR". A complicated sequence of commands, such as a long list of "FILE" commands before running a program, can be reduced to one UDC name such as "PAY". Many of your boring, repetitive tasks can be automated by using UDCs. UDCs can also be used to protect your system from both the naive user and the too-knowledgeable user. They can also cause something to happen automatically at logon time. These all serve as examples of ways to make the HP3000 more "user-friendly." By this point in time, you probably have half a dozen UDC ideas in your head just waiting to get out. So... 2.3 How do I create a UDC? First of all, slow down! UDCs, as with most everything in life, are best created with PPP -- Proper Prior Planning. If thought is given to each UDC you create, a lot of changes can be avoided later and you will likely end up with a more functional set of UDCs that are easier to use and maintain. For some people, creating a good UDC is an art, rather than a science -- they may put as much thought and care into a UDC as they put into developing a program. Now that you have slowed down a bit (you have, haven't you?!), give some thought to what MPE XL system commands are used often on your system. Are there particular tasks that always require the same sequence of commands? Are there commands or tasks that may not be difficult for us programmers to master, but may be intimidating for the user? Now take your list (you did write them down, didn't you?) and evaluate each command or task. Some of them may be used so seldom that it is not worthwhile to create a UDC. (That can also be a reason to create a UDC for a task, so that the sequence of steps need not be remembered!) Some of the commands may be so short that creating a UDC for them would only save two or three key strokes. You must make a judgement call for each command or task as to whether the convenience of having the UDC available for use is worth the time and effort of creating it. You must also consider whether it would be more appropriate to use a command file rather than a UDC. For example, is the command definition likely to change often, or do you want the added security of UDCs? 2.3.1 Defining the UDC. Let us assume that you have chosen to create a UDC for the SHOWJOB command in its simplest form. You would like to be able to type the letter "J", and have the system behave as if you had typed "SHOWJOB". A UDC to do this could look like: J Header section OPTION LIST, HELP Execution options section SHOWJOB Body section ** UDC separator section As shown above, every UDC consists of four main sections: a header section, an optional execution options section, a body section, and a UDC separator section. The first line in this example is the header section, containing the actual command the user will type. The second line provides some execution options to the system. The third line makes up the body section, containing the actual command to be executed. The fourth line serves as a separator between UDC definitions in a UDC file. 2.3.1.1 The header section. The header section of a UDC consists of the command name, parameters, and their optional default values. A UDC header may extend over more than one physical line for up to a maximum of ten lines, and may not exceed 279 characters in total. Each line to be continued must have as its last non-blank character an ampersand (&). The command name is what the user will actually type (along with any needed parameter values) to cause the UDC to be executed. It is composed of a maximum of 16 alphabetic or numeric characters and must begin with an alphabetic character. Use common sense when naming your UDCs. Use a derivative of the actual MPE XL system command(s), or if naming a UDC for a particular task, give it a name that is descriptive of the task. It is a good idea to avoid single letter UDC names to reduce the chance of executing the command by mistake (at least for any that may be "destructive"). Parameters are variables for a UDC that are assigned either a default value or a value provided by the user when the UDC is executed. These variables are specified on the same line as the command name and may be used in the body of the UDC to make the UDC more flexible and less specific. Hewlett-Packard Company documentation claims you may have up to 255 parameters defined in one UDC. I have successfully defined 122 parameters. However, when I tried to define 123 or more parameters in one UDC, I got various error messages when I executed the UDC. Regardless of what the real answer is, you can still define more parameters than you will ever know what to do with!! Besides, who wants to type that many names? Each parameter must have a name. A parameter name must begin with an alphabetic character; the remainder may be alphabetic or numeric characters. The maximum length for a parameter name is seventy characters. However, the actual maximum may be less; a parameter name may not be split between physical lines. The same is true for default values for parameters. Further constraints on the length of the parameter name may apply depending on the position where the parameter is used in the body section. In addition to specifying parameters on the command name line, you may use the PARM statement to specify parameters. PARM statements must be placed immediately after the line containing the command name (or other PARM statements if any are specified), and must start with "PARM", followed by a space and one or more parameters defined in the same way as on the command name line. Either or both methods may be used in a given UDC definition. A special parameter type, ANYPARM, is also available. ANYPARM may be used in place of PARM, and causes all normal delimiters to be ignored. This implies that delimiters (actually everything) are now considered part of the parameter's value. For this reason, only one parameter in a UDC may have ANYPARM specified, and it must be the last parameter of the UDC, since the equal sign(=), comma, semicolon, quotation mark, etc. are all treated as data for the parameter's value. Without the use of ANYPARM in the UDC definition, the user is forced to enclose their parameter value in quotation marks if it contains characters that MPE XL interprets as delimiters. With the use of ANYPARM, a lot more flexibility can be built into UDCs. If a UDC parameter does not have a default value specified, it is considered a required parameter and a value must be provided by the user when the UDC is executed. If a value for a required parameter is not provided by the user, an appropriate error message is displayed and the UDC is not executed. Let us change the requirements for our "J" UDC. We now want it to do one of three things: SHOWJOB JOB=@ (show all jobs) SHOWJOB JOB=@S (show sessions only) SHOWJOB JOB=@J (show batch jobs only) This can be accomplished with one UDC if we use a parameter. The header section will now look like: J WHAT2SHOW = " " The command name is still J. The character string "WHAT2SHOW" is the parameter name. A default value of a space has been specified. This means that if a user just types "J", a list of all jobs will be displayed. Similarly, if the user types "J S" the list will show sessions only. As can be seen in the example above, a default value for a parameter is specified by placing an equal sign (=) after the parameter name, and then following that with the default value. If the default value contains any spaces or special characters, it must be enclosed in quotation marks ("). If no spaces or special characters are needed in the default value, the quotation marks are optional. When a default value is not provided for a parameter, the only thing that appears in the header section is the parameter name. If you choose to use the PARM statement, the above UDC header section would look like: J PARM WHAT2SHOW = " " If more than one parameter is used in a UDC, default values may be specified for all, some, or none of them. That is, some of the parameters can be required while others are optional. A comma is used to separate a parameter name from the previous parameter name (or default value if one is specified). From the user's point of view, there are two ways UDC parameters can be thought of: keyword and positional. When a user is executing a UDC, either approach may be used, but not both at the same time. A keyword parameter is one in which the parameter name is typed, followed by an equal sign, followed by the parameter value. In this way, values for parameters may be provided in any order. For example: J WHAT2SHOW=S is the way the user would execute the J UDC using a keyword parameter. A positional parameter is one in which the value is specified for each parameter in the order they were defined in the UDC. If a new value is not provided for an optional parameter, its position must still be "held" by a comma. The J UDC executed with a positional parameter would look like: J S The concept of keyword and positional parameters is the same as for the standard MPE XL system commands, except that only one approach may be used on a given execution of a UDC. When providing numeric values for parameters (either the default values or the user's actual values), both decimal and octal numbers may be used. Octal numbers are indicated by preceding them with a percent sign (%). As you would expect, if the user provides a value for a parameter that has a default value, the user's value is the one that will be used. If the parameter value a user provides contains spaces or special characters, that value must be enclosed in quotation marks. 2.3.1.2 The execution options section. The execution options section of a UDC consists of choices from each of six pairs of options. Each of these six pairs has a default and, therefore, if the defaults are what is desired, this entire section can be left out. These options control the operation and use of the UDC. If the execution options section is provided, it must appear immediately after the header section and will consist of one or more lines. Each line must start with the word OPTION. The rest of the line contains the option or options you have chosen with a comma between each, if you list more than one. You may chose to put any number of options on a given execution option line. The six option pairs, along with their defaults, are shown in the table below and discussed in the following paragraphs. There are two exceptions to the placement rule for the option statements. The RECURSION/NORECURSION and LIST/NOLIST options may be placed in the body section, as well as in the execution option section of the UDC. This permits additional control over these two aspects of UDC execution, as they can be "turned on and off" as they are required. The format of the line is the same for both the execution options and the body sections. All other options may only be specified in the execution options section. Execution Option Pairs and their Defaults Execution Option Pair Default Used if Not Specified List / NoList NoList Break / NoBreak Break LogOn / NoLogOn NoLogOn Help / NoHelp Help Recursion / NoRecursion NoRecursion Program / NoProgram Program LIST/NOLIST. The default is NOLIST. The LIST option will cause the text of the body section to be listed on the standard list device with the parameter values substituted as each line is executed. The NOLIST option will not list any of the text of the body section. It is a good idea to use the LIST option on UDCs that are replacements for MPE XL system commands. This way the actual command is before you and you will be less likely to forget what the MPE XL system command is when you need to use it on another system that doesn't have your UDC! The NOLIST option is generally a good choice for UDCs that are implementing user tasks. BREAK/NOBREAK. The default is BREAK. If the NOBREAK option is chosen, the commands that make up the body of the UDC will be nonBREAKable. That is, pressing the BREAK key will not cause the command or program to stop. If the BREAK option is chosen, the commands that make up the body of the UDC will be BREAKable (if they are normally BREAKable as MPE XL system commands). It is a good idea to use the NOBREAK option on any UDC that runs a VPlus application. This eliminates the problems that occur when BREAK is pressed while in block mode. The use of the NOBREAK option will prohibit certain users from using any MPE XL system commands and can serve as a way to discourage simple security breaches. If the BREAK key is pressed during the execution of a UDC using the BREAK option, the following happens: If it was executing a non-program command, the UDC terminates. If it was executing a program, and the RESUME command is entered, the UDC will also resume execution. An exception to this occurs if a SETCATALOG command is executed while in BREAK. In this case, the program is resumed but the remainder of the UDC will not be executed. For you programmers, the NOBREAK option overrides the CAUSEBREAK intrinsic. A program containing CAUSEBREAK will not BREAK if it is executed from a UDC that has the NOBREAK option specified. LOGON/NOLOGON. The default is NOLOGON. If the LOGON option is chosen, the commands specified in the body of the UDC will automatically be executed when the user logs on. Only one LOGON UDC at the user level will be executed. If more than one LOGON UDC exists for the user level, only the first one will execute. The LOGON option can be put to good use on user task UDCs. By using this option, the user can logon and automatically be put into a menu or application program. If the NOBREAK option is also used, you can keep a user from gaining direct access to MPE XL system commands. An example of this will be shown later. If you have one or more tasks you want done every time a user logs on, but the tasks seem to change often, consider setting up a LOGON UDC that references a command file. By doing this, you will be able to easily alter the command file, but still have the LOGON functionality of UDCs. HELP/NOHELP. The default is HELP. If the HELP option is chosen, you may type HELP followed by the UDC name and see the definition of the UDC. If the NOHELP option is chosen, this possibility does not exist. More will be said later about the use of the MPE XL HELP subsystem. It is good to choose the HELP option unless you have a security sensitive situation. If you specify both the NOLIST and NOHELP options and an error occurs during execution of the UDC, the error will be reported but the line containing the error will not be listed. A small security breach you should be aware of: Even if you specify the NOHELP option, the definition of that UDC will still list when it is cataloged if the SHOW parameter is used on the SETCATALOG command. RECURSION/NORECURSION. The default is NORECURSION. If the NORECURSION option is chosen, MPE XL will search for UDC definitions from the current command in the executing UDC to the end of the UDC directory. (This is the way MPE V works.) As a result, UDCs that are defined "before" the current command are not available for use following the current command in the UDC. If RECURSION is specified, MPE XL starts at the beginning of the UDC directory to satisfy UDC usage. This allows a UDC to reference any other UDC -- even if the referenced UDC is defined "before" the current one. Note that the RECURSION option is only in effect for the UDC(s) in which it is specified. Other UDCs in the file are not affected -- not even those referenced by a UDC with RECURSION in effect. To prevent endless loops when the RECURSION option is specified (since two UDCs could call each other, or a UDC could reference itself, for example), MPE XL places a limit of thirty on how many times any UDC can call any other UDC, including itself, in a "circular" fashion. When the limit is reached, the system interrupts the process, and displays the error message shown below. We will talk more about RECURSION/NORECURSION later. USER COMMAND NESTING DEPTH LEVEL HIT. (CIERR 2030) PROGRAM/NOPROGRAM. The default is PROGRAM. If the PROGRAM option is chosen, programmatic access to UDCs will be available, provided the program calls a new MPE XL system intrinsic, HPCICOMMAND. Programs or subsystems that use the COMMAND intrinsic will not have access to UDCs, even if the PROGRAM option is specified in a UDC. (More information is available on these intrinsics in the MPE XL Intrinsics Reference Manual.) If NOPROGRAM is chosen, programmatic access to UDCs is not available. 2.3.1.3 The body section. The body section of a UDC consists of one or more MPE XL system commands and/or UDCs that will be executed when the user types the UDC name. Other non-command text such as data for subsystems or application programs may not be included. A logical line of the body may extend over more than one physical line for up to a maximum of ten lines, and may not exceed 279 characters in total. Each line to be continued must have as its last non-blank character an ampersand (&). The body section follows the execution options section, if any options have been listed. If the execution options section is not present, the body section will follow the header section. There are a few restrictions to be aware of. The REDO and DO commands may not be used in a UDC. The HELLO command may be used, however, it will cause the current session to logoff and effectively terminate execution of the UDC. Let us go back to our last version of the J UDC. We wanted it to do one of three things: SHOWJOB JOB=@ SHOWJOB JOB=@S SHOWJOB JOB=@J We last defined the header section as: J WHAT2SHOW = " " The body section needed to satisfy our requirements will consist of a single MPE XL system command: SHOWJOB JOB=@!WHAT2SHOW In this example, all the characters preceding the exclamation point (!) will be left as shown. The character string "!WHAT2SHOW" will be replaced by either the default value of a space, or whatever the user types as a parameter value following "J". This revised command image is then what is sent to the MPE XL system command interpreter (CI) for execution. Thus, if the user types: J S the command image executed will be: SHOWJOB JOB=@S Alternatively, if the user just types: J and uses the default parameter value, the command image executed will be: SHOWJOB JOB=@ As shown above, placing an exclamation point (!) immediately before a parameter name in the body section of a UDC will cause MPE XL to substitute the value of that parameter into that position of the command. If an exclamation point does not precede a parameter name, no substitution will be attempted, and the parameter name will be left in the command. If anything resembling a parameter name, other than a parameter name, follows an exclamation point, an error will be reported to the user. Normally, an exclamation point signifies a parameter name. If you want to use the exclamation point immediately before a character string that MPE would normally interpret as a potential parameter, but not have MPE XL attempt parameter substitution, use an even number of exclamation points. An odd number of exclamation points will cause MPE XL to attempt a substitution. Each pair of exclamation points will be translated into a single exclamation point provided a character string immediately follows them that could be interpreted as a parameter name. For example, consider the following UDC: EXAMPLE PARM OPTION NOLIST ECHO !!PARM ECHO !!!!!PARM ECHO PARM = !PARM ECHO PARM = !PARM! ** If the user were to execute it by typing: EXAMPLE TEST the ECHO statements would cause the following to be displayed: !PARM !!TEST PARM = TEST PARM = TEST! Sometimes you will need to insert a parameter into the middle of a character string in the UDC body section. As an example: LINKI PROGNAME, XL="XL.PUB" OPTION LIST LINK ^!"PROGNAME"L,!"PROGNAME"X;XL=!XL ** In this UDC, two parameters are used: PROGNAME and XL. XL has a default value of XL.PUB. When the UDC is executed, it will LINK a file, using an indirect file as input. The parameter PROGNAME is enclosed in quotation marks in the body to separate it from the letters "L" and "X" that follow. Without the quotation marks, there would appear to be invalid parameter names following the exclamation points. This is only a concern if the character immediately following a parameter name is a letter or number. If the UDC was to be executed by typing: LINKI PAY the actual command image executed would be: LINK ^PAYL,PAYX;XL=XL.PUB The parameter value "PAY" corresponds to parameter PROGNAME because they are both the first item provided in the list. Since a second parameter value was not provided when the UDC was executed, the default value for XL was used. If an error is encountered as the commands of a UDC are executed, an error message will be displayed and the UDC will terminate. If the UDC is being executed in a jobstream, the jobstream will also terminate. Sometimes it is desirable for the UDC to continue with the next command regardless of whether the previous command results in an error. To accomplish this, a CONTINUE command must be inserted immediately preceding the command that may result in an error. Consider the following UDC: REPORTS OPTION LIST CONTINUE RUN PROG1X RUN PROG2X SHOWTIME ** In this example, two programs are run and then the time of day is displayed. If program PROG2X results in an error (i.e., it aborts) when it is run, the remainder of the UDC will not be executed. That is, if program PROG2X aborts, nothing else will be done. Program PROG2X will always be run regardless of whether program PROG1X results in an error. The CONTINUE command tells MPE XL to continue with the next command, even if the current command fails. This "override" capability applies only to the command immediately following the CONTINUE command. UDCs can perform tasks much more complex than those already covered by using sophisticated command sequences and/or referencing other UDCs from within the body section of the UDC. By using control characters and escape sequences, you can control the appearance and location of information as it is displayed by a UDC. The terminal's function keys can be "loaded" by a UDC, thus making your terminal a little more user- friendly. Examples of these will be provided later. As mentioned earlier, a UDC may reference or execute another UDC. This process is referred to as nesting. Unless the RECURSION option is used, there is a limitation, however: A UDC can only reference another UDC that is defined later in the UDC file. As long as the reference occurs before the definition, UDCs can be written in a structured way. If the RECURSION option is used, the order of the UDC definitions generally is not important. Consider the following UDCs: INFO OPTION LIST ME J T ** J OPTION LIST SHOWJOB ** ME OPTION LIST SHOWME ** T OPTION LIST SHOWTIME ** In this example, we have defined four UDCs: INFO, J, ME, and T. The INFO UDC will cause the J, ME, and T UDCs to be executed one after the other in the order listed in the INFO UDC. When the J UDC is executed, it will execute the SHOWJOB command; the ME UDC will execute the SHOWME command; and the T UDC will execute the SHOWTIME command. So, by simply typing "INFO", the user will be provided information from all three of the MPE XL system commands automatically. 2.3.1.4 The UDC separator section. The last section of a UDC definition is the UDC separator. This consists of a single line that must start with an asterisk (*) in column one. The rest of the line is yours to do with as you wish. The purpose of this section is to separate one UDC from the next in the UDC file and must be the last line of the UDC definition. So, there you have it in ten words or less (give or take a few thousand). You now know how to define a UDC. But once you have a number of UDCs defined, what do you do with them? The answer to that question is... 2.3.2 Put your UDC definitions in a UDC file. A UDC file is simply an ASCII text file that contains one or more UDC definitions. Any ASCII text editor may be used to create a UDC file. MPE XL is expecting eighty- character records. (According to HP documentation. My testing, however, seems to indicate that any record length will work -- at least on this release of MPE XL. Nonetheless, I recommend you use eighty-character records, or be prepared to make changes in the future if and when HP decides to follow their documentation.) A UDC file may contain any number of UDC definitions (restricted, of course, by MPE XL's maximum file size). The UDCs should be entered in some logical sequence to make maintenance easier -- my suggestion is alphabetically by the UDC name. An exception: Remember if you are using nested UDCs without the RECURSION option, the definition of a UDC must be after its reference(s). So, either name them appropriately or include them in the file out of sequence. If you are using the escape character in your UDCs, an easy way to key it in is to type in some otherwise unused character (e.g., the ^ character) in place of the escape character. Then when you are finished entering the UDC definitions, globally change all occurrences of that character to the escape character. The reverse sequence can be used if you need to modify an existing UDC file. Just remember to change them back before you keep the file. Once you have entered all of the UDC definitions using your text editor, save the file with some meaningful name. My preference is to use the letters "UDC" as the last three characters of the file name. Doing so makes it easy to locate UDC files with the LISTF command. You may keep your file with or without line numbers -- MPE XL does not care. You may create multiple UDC files; however, for performance reasons (to be discussed later), it is best to limit the number of UDC files that exist for one user. If you wish, a lockword may be assigned to the UDC file. Simply creating a UDC file with a text editor does not yet make the UDCs available for use. The next step is to tell MPE XL that you have a UDC file you wish to use. However, before we discuss that, let us take a look at account and system level UDCs. 2.3.3 Account-level and system-level UDCs. Up to this point, we have been discussing UDCs in general. There are actually three different levels of UDCs: user, account, and system. A UDC file may be set up by a user for his/her own use. An account manager may create a set of UDCs for use by all users of that account. The system manager may create a set of UDCs for use by all users on the system. So now you have one more item to consider when you are creating a UDC: Who should have access to it? When the MPE XL system command interpreter is given a command (an MPE XL system command, a UDC, a command file, or an implied RUN of a program), it follows a predefined hierarchy to decide what to do with the command in question. Shown below is that hierarchy. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ First User-Level UDC File ³ ³ . ³ ³ . ³ ³ . ³ ³ N'th User-Level UDC File ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³First Account-Level UDC File ³ ³ . ³ ³ . ³ ³ . ³ ³ N'th Account-Level UDC File ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ First System-Level UDC File ³ ³ . ³ ³ . ³ ³ . ³ ³ N'th System-Level UDC File ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ MPE XL System Commands ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ File Names ³ ³ (Command Files & Programs) ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ This hierarchy is followed regardless of whether it is trying to locate a command provided at a colon (:) prompt or a command that is coming from a UDC. This is the reason that when using nested UDCs, the UDC definition must follow the reference(s) to that UDC (unless the RECURSION option is specified). There is an exception to this hierarchy: UDCs with LOGON listed as an option. When a user logs on, one logon UDC, at most, will be performed from each UDC level. The system-level logon UDC (if present) will execute first, then the account-level logon UDC (if present), and finally, the user-level logon UDC (if present) will be executed. If more than one logon UDC exists at a level, only the first logon UDC at that level will be executed but it will not affect the execution of other levels' logon UDCs. Another implication of this hierarchy is that when a UDC at one level has an identical name to a UDC or command at another level, the following rules apply: 1. A UDC in user-level UDC file 1 takes precedence over a UDC in user-level UDC file n. 2. A UDC in user-level UDC file n takes precedence over a UDC in account-level UDC file 1. 3. A UDC in account-level UDC file 1 takes precedence over a UDC in account-level UDC file n. 4. A UDC in account-level UDC file n takes precedence over a UDC in system-level UDC file 1. 5. A UDC in system-level UDC file 1 takes precedence over a UDC in system-level UDC file n. 6. A UDC in system-level UDC file n takes precedence over the MPE XL system commands. 7. An MPE XL system command takes precedence over command and program files. What all of this means is that you can set up a UDC with exactly the same name as an MPE XL system command (or UDC, command file, or program file) and effectively redefine that command. For instance, if you want to keep a user from using the PURGE command, the following UDC could be established: PURGE FILENAME = " ", TEMP = " " ECHO YOU HAVE NOT BEEN GIVEN ACCESS TO THIS COMMAND. ** Unless you are specifically taking advantage of this capability, it is best to give all of your UDCs unique names from anything else on the system. Here is another example of these rules and the hierarchy: If both a system-level and a user-level UDC have the same name and an account-level UDC (with the NORECURSION option) references a UDC by that name, then the system-level UDC will be executed rather than the user-level UDC because the system-level UDC is "after" the account-level UDC that referenced it, whereas the user-level UDC would be "before" that reference. If, on the other hand, the account-level UDC is defined with the RECURSION option, the user-level UDC will be executed rather than the system-level UDC because the RECURSION option causes the search to start at the beginning of the UDC directory, rather than starting where it currently is. (Anybody lost?!?) A user must have special capabilities to establish account- or system-level UDCs. To establish account-level UDCs, the user must have the AM capability; to establish system- level UDCs, the user must have the SM capability. Additionally, if system-level UDCs are established, the system-level UDC files must either have their access security released or have the access security such that all users will have READ and LOCK access to the UDC file(s). (For security reasons, the latter is preferred.) 2.3.4 Telling the system about your UDC file(s). If there is any one thing that makes people stop using UDCs in favor of command files, it is likely the fact that UDCs must be cataloged, and command files do not. It is because of this cataloging that UDCs are not good candidates for command definitions that change often. In my experience, however, the large majority of user commands are pretty stable and seldom change. Those that do change often should probably be defined as command files. The new SETCATALOG parameters, APPEND and DELETE, make the cataloging task a bit more palatable. To continue with the creation of your UDCs, we need to tell the system about them. 2.3.4.1 Cataloging your first UDC file(s). As stated earlier, simply creating a UDC file with a text editor does not yet make the UDCs available for use. The next step is to tell MPE XL that you have a UDC file you wish to use. The MPE XL system command to do this is SETCATALOG. The simplest syntax of the SETCATALOG command is: SETCATALOG udcfilename[/lockword] where udcfilename is your UDC file name and lockword is an optional lockword assigned to the UDC file. This version will enable a UDC file for the user level only. The user executing the SETCATALOG command must have READ and LOCK access to the UDC file. Unless you have account or system manager capabilities, you must logon as the user that you want to enable the UDC file for. The SETCATALOG command may be issued from a session, job, or in BREAK. It may not be issued from a program, nor is it BREAKable. When SETCATALOG is executed with a file name provided, three things occur. The command interpreter searches the UDC file for errors: Problems like specifying an option that is not a valid option are caught; problems like syntax errors in the body section of the UDC are not caught. If no errors are found in a UDC, then an entry is established in a directory that will eventually contain entries for all UDCs in the UDC file. The UDC file name and optional lockword is stored in a system catalog of all UDC users. This system catalog is file COMMAND.PUB.SYS. The directory is stored as an "object" in transient space. Since the lockword (if one is provided) is stored in COMMAND.PUB.SYS, a user does not need to know the lockword to logon or to access a UDC. In addition to the UDC file name (and lockword), the user name and account and the UDC level (user, account, system) are also stored in COMMAND.PUB.SYS. As you could probably guess, the file COMMAND.PUB.SYS must exist before any SETCATALOG is attempted. If the file does not exist, the system manager or supervisor must build it. The file should be built with a record size of 128 words. The number of records required for the file can be determined by calculating the sum of: 1 for each user.account that will have user-level UDCs; plus 1 for each user-level UDC file to be used; plus 1 for each account that will have account-level UDCs; plus 1 for each account-level UDC file to be used; plus 1 if system-level UDCs are to be used; plus 1 for each system-level UDC file to be used. So, the BUILD command used by the system manager might look like: BUILD COMMAND.PUB.SYS;REC=128;DISC=500 To secure this file so all users may utilize UDCs, but only the system manager may read or modify it (since there could be sensitive information stored there), the system manager should enter: ALTSEC COMMAND.PUB.SYS;(X:ANY;R,L,W,A:CR) Taking this last step will provide execute access to all users (which is all they need), and restrict all other access to the creator of the file (in this instance, the system manager). If you have more than one UDC file that you wish to enable at the user level, the syntax of the SETCATALOG command becomes: SETCATALOG udcfilename[/lockword],udcfilename[/lockword]... The UDC file names are listed (with the optional lockwords) with a comma inserted between each one. The position of a UDC in the directory determines which other UDCs it may reference (remember the hierarchy discussed a few paragraphs back?). The UDC files are opened and scanned in the order they appeared in the last SETCATALOG command for that UDC level. All user-level UDCs are entered into the directory first, followed by all account-level UDCs, and finally, all system-level UDCs. 2.3.4.2 Appending UDC files to those already cataloged. If you simply want to add another UDC file to what has previously been cataloged, an option in MPE XL is to use a new parameter on the SETCATALOG command: SETCATALOG udcfilename[/lockword]...;APPEND When the APPEND parameter is specified, the UDCs defined in udcfilename are added to the end of the UDC directory. If you are using nested UDCs, or for some other reason the order in which the UDC files are cataloged is important, you likely do not want to use the APPEND parameter. Suppose sometime previously you typed: SETCATALOG UDC1,UDC3 You therefore have the UDCs from two UDC files enabled (plus any account or system level UDCs!). For whatever reason, you want to add a third UDC file, UDC2, to the UDC directory. To add this file, and retain the other two, you could type: SETCATALOG UDC1,UDC2,UDC3 - or - SETCATALOG UDC2;APPEND Unless the APPEND or DELETE (you will hear about it in a moment) parameters are used when the SETCATALOG command is executed, it has the effect of removing all user-level UDCs for the user entering the command. Additionally, if a UDC file name(s) is provided, those UDCs are re-cataloged and available for use. If file UDC2 must be cataloged between files UDC1 and UDC3, the first example must be used. If the sequence of the files is unimportant, the APPEND parameter provides the better solution. 2.3.4.3 Disabling individual UDC files. So, now you know how to "turn on" or enable user-level UDCs. What if you want to disable or "turn off" user-level UDCs? To accomplish this, you again use the SETCATALOG command, except this time do not provide a UDC file name: SETCATALOG When a UDC file name is not provided with the SETCATALOG command, all entries and references to any user-level UDC files in the UDC directory and COMMAND.PUB.SYS that are currently enabled for the user issuing the command are eliminated. The UDC files themselves, however, are not purged. To re-enable your UDC files, you would simply type the SETCATALOG command, followed by your UDC file name(s) again. Alternatively, an option in MPE XL is to use a new parameter on the SETCATALOG command: SETCATALOG udcfilename;DELETE When the DELETE parameter is specified, the UDCs defined in udcfilename are removed from the UDC directory. The original order of the remaining cataloged UDC files is retained. Disabling user-level UDCs does not have an immediate affect on other jobs or sessions that are logged on with the same user name. They may continue to use the disabled UDCs until they logoff. Conversely, if you enable some UDCs, other users will not have access to them until they logon again. Now, suppose sometime previously you typed: SETCATALOG UDC1,UDC2,UDC3 You therefore have the UDCs from three UDC files enabled (plus any account- or system- level UDCs!). For whatever reason, you no longer need the UDCs in file UDC2. To eliminate them, but still keep the others, you could type: SETCATALOG UDC1,UDC3 - or - SETCATALOG UDC2;DELETE As we found before, the first example has the effect of removing all user-level UDCs for the user entering the command, and re-cataloging the listed UDC files, effectively eliminating the UDCs defined in file UDC2. The use of the DELETE parameter on the second SETCATALOG command is the simpler approach in this instance, and causes the UDCs found in the file UDC2 to be removed from the directory, while leaving all others intact. 2.3.4.4 A couple seldom-used SETCATALOG parameters. A parameter I have never found a need to use is RESET. (Just in case you find it interesting, I will tell you about it anyway.) SETCATALOG udcfilename[/lockword][,udcfilename[/lockword]]...;RESET This causes the UDC file(s) being cataloged to replace all files that are already cataloged. If that sounds familiar it is because it is exactly the same thing that occurs if you don't provide any parameters. In other words: Including RESET is the same as leaving off APPEND and DELETE. One last parameter that you may wish to know about: SETCATALOG udcfilename[/lockword][,udcfilename[/lockword]]...;SHOW This will list the UDC file names and definitions in the files as they are scanned. This is helpful for locating where an error is occurring when you use the SETCATALOG command. I don't suggest it for general use, however; It can take a while to list all of the UDC definitions in a large UDC file. Also, a small security breach you should be aware of: Even if you have specified the NOHELP option on a UDC, the definition of that UDC will still list if SHOW is used on the SETCATALOG command. 2.3.4.5 SETCATALOG use by account or system managers. You now know everything (well almost everything) I know about using the SETCATALOG command with user-level UDC files. But what about account- and system-level UDC files? How do they get enabled and disabled for use? The answer again is the SETCATALOG command! We add one more parameter to the previous syntax: SETCATALOG udcfilename[/lockword][,udcfilename[/lockword]]...;ACCOUNT SETCATALOG udcfilename[/lockword][,udcfilename[/lockword]]...;SYSTEM The ACCOUNT parameter specifies that the UDC file(s) being enabled should be available for all users in the account. This parameter requires the account manager capability. Reading between the lines, you have probably realized that you must logon to the account that the UDC file is to be enabled for. For example, if you want to enable UDC file ACCTUDC for account XYZ, first logon as the account manager of account XYZ, then enter: SETCATALOG ACCTUDC;ACCOUNT If you wish to disable the account-level UDC files, you would enter: SETCATALOG;ACCOUNT Again, you must have the account manager capability to use the ACCOUNT parameter. Taking this new information into account, all previous information pertaining to the SETCATALOG command and user-level UDC files also applies to account level UDC files. The SYSTEM parameter specifies that the UDC file(s) being enabled should be available for all users of the system. This parameter requires the system manager capability. For example, if you want to enable UDC file SYSUDC for all users of the system, just logon as the system manager, then enter: SETCATALOG SYSUDC;SYSTEM If you wish to disable the system-level UDC files, you would enter: SETCATALOG;SYSTEM Again, you must have the system manager capability to use the SYSTEM parameter. Taking this new information into account, all previous information pertaining to the SETCATALOG command and user-level UDC files also applies to system-level UDC files. If you have the account manager or system manager capability, you may use another parameter of the SETCATALOG command: SETCATALOG udcfilename[/lockword][,udcfilename[/lockword]]...;USER=user[.account] where user is a user name and account is an account name. This allows you to enable a UDC file for a user other than the one you are logged on as. Account managers can enable UDC files for any user in their account. The system manager may enable UDC files for any user on the system. They will not take effect, however, until the next time the user logs on. This parameter can also be used to disable UDC files for other users: SETCATALOG;USER=user[.account] The same restrictions and capabilities apply for account managers and the system manager, as were just discussed. 2.4 How do I alter a UDC file after it has been cataloged? At some point (probably very soon after you start using UDCs), you will need to modify or add to an existing UDC file. There is not much more involved than simply using a text editor to make the changes or additions; however, you do need to know about a "gotcha". Because of the way UDCs are enabled, whenever a user is logged on to the system, any UDC file(s) associated with that user (including account- and system-level UDC files) are considered "open". What this means is that you may not alter that UDC file in any way as long as the user is logged on and has the UDC file enabled. You may not PURGE, RENAME, or (in EDIT/3000) modify and KEEP that UDC file. Any attempt to alter the file will result in the error message "EXCLUSIVE VIOLATION". So, how do you ever make changes or additions?!? You have five options (take your pick -- they all work well under different situations): 1. Have all users (and jobs) that are using the UDC file logoff (except you, of course). You use the SETCATALOG command to disable the UDC file in question. Make your changes to the file, and keep it. Re-enable the UDC file by using the SETCATALOG command. Notify the users they may logon again. 2. Have all affected users (including yourself) disable the UDC file by using the SETCATALOG command. Make your changes to the file, and keep it. Have all users re-enable the UDC file by using the SETCATALOG command or you use the SETCATALOG command and have the other affected users logon again. Watch out for batch jobs when using this option. 3. Have all affected users (and jobs) logoff the system. You logon so you can modify and keep the UDC file, but as a user who does not have this UDC file enabled. Make your changes to the file, and keep it. Notify the users they may logon again. 4. Logon so that you can modify and keep the UDC file. Make your changes to the file and keep it under a new file name. Later, after all affected users and jobs have logged off, disable the UDC file, PURGE the old UDC file, RENAME the new file to the old file's name, and re-enable the UDC file with the SETCATALOG command. 5. Any combination or variation of the above four options that you can get to work. It is important to understand that all affected users must take some action (log off/on or SETCATALOG) because the SETCATALOG command takes effect only for the session or job that issues it and for future logons. It does not affect other jobs or sessions currently logged on. 2.5 What happens when I logon and have some UDCs enabled? At logon time, any user who has one or more UDC file(s) enabled for his/her use (user, account, or system!) will cause a fair amount of CPU and disc utilization to occur. As a result of previous SETCATALOG commands, the file COMMAND.PUB.SYS contains the UDC file names enabled for every user, as well as those enabled for each account and the system. At logon time, this file is searched to identify what UDC files are enabled for the user in question. As each one is identified, that UDC file is opened and the contents of it are read. As the UDC file is scanned, entries are created and placed in a directory of UDCs for the session or job. That directory is created as an "object" in transient space, according to Hewlett-Packard. (It sounds like a table to me!) When you enter an MPE XL system command or UDC name, the command interpreter searches the UDC directory for that which you typed in, starting at the beginning of the directory. Remember entries are placed in the UDC directory in user-level, account- level, system-level sequence. If the command is found in the UDC directory, the UDC body for that command is read one line at a time and parameters are substituted into the line where appropriate. The command interpreter is then re-entered at a special internal entry point to interpret the new expanded command string and goes through the same steps just mentioned, except that this time, the UDC directory scan begins with the directory entry that follows the UDC currently being executed. (Now do you understand why the definition of a UDC must be after its reference?) If the RECURSION option is in effect, the directory scan starts at the beginning of the UDC directory again. If the command interpreter fails to find a match for a command string in the UDC directory, it then checks to see if it is a valid MPE XL system command. This cycle is repeated until the end of the UDC definition that is being executed. By the way, if you have system manager (SM) capability, and want to logon but not have any UDCs set up for your use, simply add ";PARM=-1" to your HELLO command. In this way, the system manager can logon and gain immediate access to an MPE XL prompt, without any interference from logon UDCs. This option is only available to users with system manager capability. 2.6 How do I find out what UDCs are available? There is a handy MPE XL system command that will list all of the UDC names enabled for your session or job: SHOWCATALOG [listfile] where listfile is the name of the file (disc or printer) you wish the list to be sent to. Unless directed elsewhere with a prior FILE command, if you specify listfile, the listing is sent to device class LP. If listfile is not provided, the list of UDC names will be displayed on $STDLIST (your terminal for a session). This command may be issued from a session, job, program or in BREAK. The SHOWCATALOG command is BREAKable (it aborts execution of the command). The output from the SHOWCATALOG command lists the UDCs currently enabled for your use, the level at which they are defined (user, account, system), and the file name in which they reside. A sample execution follows: :SHOWCATALOG UDC1.GROUP.ACCT AA USER BB USER UDC2.GROUP.ACCT CC USER ACCTUDC.PUB.ACCT DD ACCOUNT SYSUDC.PUB.SYS EE SYSTEM FF SYSTEM GG SYSTEM This example shows seven UDCs enabled from four different UDC files: Three at the user level, one at the account level, and three more at the system level. The SHOWCATALOG command has another parameter that can be useful, especially for account and system managers: SHOWCATALOG [listfile];USER=user[.account] where user is the name of a user, and account is an account name. This parameter permits you to specify a user other than yourself for which you want the SHOWCATALOG done. The output when this parameter is used will consist of only enabled UDC file names and which level they were defined at. No UDC names will be listed. For example if you want to know what UDC file(s) are enabled for a user, you could type: SHOWCATALOG;USER=DAVE and the system would respond with: USER UDC CATALOG FILE NAMES: UDC1.GROUP.ACCT UDC2.GROUP.ACCT ACCOUNT UDC CATALOG FILE NAMES: ACCTUDC.PUB.ACCT SYSTEM UDC CATALOG FILE NAMES: SYSUDC.PUB.SYS There are a few limitations when using the USER= parameter: 1. A user with neither account nor system manager capabilities can specify only his/her own user name. This type of user may not obtain information for any other user. 2. A user with account manager capability can specify any user in his/her account. Additionally, if "@" is used for the user name, only the account-level UDC file name(s) will be displayed. 3. A user with system manager capability can specify any user on the system. Additionally, if "@" is used for the user name and an account name is specified, the account-level UDC file name(s) will be displayed. Also, if "@" is specified for both the user and account, only the system-level UDC file name(s) will be displayed. A way of getting more information about a particular UDC is to use the MPE XL HELP command. Unless the NOHELP execution option was specified when the UDC was created, if you type: HELP udcname where udcname is the name of a UDC, you will receive a listing of the UDC definition. For example, if you typed: HELP J (and the UDC we discussed sometime back was enabled), the system would respond with: USER DEFINED COMMAND: J WHAT2SHOW=" " OPTION LIST SHOWJOB JOB=@!WHAT2SHOW If the NOHELP execution option is specified when a UDC is created, and the HELP command is used for that UDC, the system will respond with: Can't find anything under this command or in table of contents. unless the UDC name is the same as an MPE XL system command, in which case you will receive information about the MPE XL system command. It should be noted that you may not enter the HELP subsystem itself and get information about your UDCs. Only by using the HELP command as described earlier will you receive this information. 2.7 How about some examples? Good idea! Before we start, a few words of explanation: Anytime you see the characters in this tutorial, read it as an escape character. That is, for purposes of this tutorial, I have used the characters in place of the escape character. However, if you were to type in the UDC, you would need to use the escape character instead. Similarly, the control character will be represented by the characters . Let us start with a look at some games -- I mean UDCs for a games user. I have a variation of the following UDC file set up on my system: StartGames Option LogOn Echo &dA*********************************************** Echo &dA WELCOME TO THE HP3000 GAME ROOM Echo &dA*********************************************** Echo Type LIST to get a listing of the available games. ** Games Echo ADVENT.... (Adventure) A game of exploration. Echo AMORT..... Creates amortization (loan) tables. ...continued for other games available... ** Advent Continue Run ADVENT List ** Amort Echo &dBIf you want the loan schedule printed on paper, Echo &dBwait for this phrase to appear... Echo &dB ENTER THE LISTING DEVICE (RETURN FOR $STDLIST)? Echo &dBthen press the BREAK key. You will get a colon prompt. Echo &dBType AMORTPRINT, and press the RETURN key. Echo &dBThe screen will now say... Echo &dB READ pending Echo &dBNow type LP, press the RETURN key, and go on to Echo &dBanswer the other questions. Echo &dBIf you just want the schedule to print on the screen, Echo &dBpress the RETURN key instead of doing all of the above. Continue Run AMORT Reset List List ** AmortPrint File LIST=AMORTRPT;Forms=8 1/2 by 11 INCH PAPER REQUIRED G. Resume ** ...continued for other games available... ** Stop Abort ** List Echo Available Games... ADVENT AMORT ANIMAL BJ Echo CHESS FIVEROW FOOTBALL GRIC Echo OTHELLO SAHARA STARTREC TREK2640 Echo If you would like a one line description of each of the games, type GAMES. ** Items of interest in the games UDC file: 1. The LOGON execution option is used so the welcome message appears automatically. 2. Escape sequences are used to control the appearance of text on the screen. In the case of STARTGAMES, it will blink, and in AMORT, the text will be shown in inverse video. 3. The CONTINUE command is used in all of the individual game UDCs to guarantee that the LIST UDC will always be executed, even if the program aborts. 4. The RESUME command is used in AMORTPRINT to put them back in the program automatically after they press the BREAK key. 5. Notice no options were provided in most UDCs. Since the default is NOLIST, the command(s) will not be displayed on the screen. The ECHO commands, however, will cause the messages to be displayed. 6. The LIST UDC must be at the end after all of the individual game UDCs because each one of them ends with a reference to LIST, and I did not want to specify the RECURSION option in each one. 7. The STOP UDC exists to provide the user a "graceful" way to end a game they do not wish to continue. The users know to press the BREAK key and type STOP if they find themselves in this situation. OK, we have had our fun with the games. Time to get back to some serious work. The next examples come from some of my application systems. These UDCs are generally user level UDCs. First, a few UDCs from the accounts payable system. In UDC file APINUDC, I have the following UDC: Payable Option LogOn,NoBreak Continue Payable Bye ** In UDC file APUDC, the following UDCs exist (among others): Payable Option NoBreak File TODAT=TODAT.GLXEQ;Shr File AP830WRK=VENNAMES;Rec=-80,16,F,ASCII;Save Run PAYABLEX ** VendorMaint Option NoBreak Echo Use this program with extreme care.G Run AP429X ** Items of interest in the accounts payable examples: 1. There are two classes of users for most application systems: A "data entry" user who only needs access to one main menu-driven program (for example, PAYABLEX) and a user who needs access to that same program, as well as other utility programs (for example, AP429X) for the application system. I have implemented this by creating two UDC files. The "data entry" user has both UDC files enabled in the order listed above. However, the other user has only the second UDC file enabled. In this way, the UDC to run the program PAYABLEX only needs to be entered in the second UDC file (in this example that UDC is relatively short; however, some others have numerous FILE commands), with a reference made to it in the first, rather than needing to define it twice. 2. Even though the "data entry" users have both UDC files enabled for them, they effectively have only one thing they can do: RUN the PAYABLEX program. This is because of the LOGON execution option which automatically starts up the program at logon time, and logs them off (because of the BYE command) when the program stops running. Two more items are required to guarantee that this will work, however. The NOBREAK execution option must be specified to keep the user from pressing the BREAK key and gaining access to MPE XL. The CONTINUE command is also needed, so that if the PAYABLEX program should abort for any reason (I know -- you write perfect programs that never abort -- I have problems sometimes though!), the next command (in this case, BYE) will still execute. Here is a neat idea for use with the SORT program (it works well with many others too!): EquipmentSort Purge EQPSORTD Run SORT.PUB.SYS;StdIn=SDEQPSRT;StdList=$NULL ** Almost any program can have its standard input and output files redirected (i.e., provided from, or sent to, some place other than normal). See the RUN command for more details on this. In this UDC, the interactive input is coming from a disc file named SDEQPSRT, and the interactive output is discarded. File SDEQPSRT contains the commands that would normally have been provided to the SORT program (i.e., the names of the input and output files, and the key information). Here are some examples from the financial system that show how to execute the same program, but provide for different input and/or output. They also provide examples of nesting UDCs. BalanceSheet BalShRun 11,";Forms=BLANK 8 1/2 by 11 INCH PAPER REQG." ** BalanceSheetGB BalShRun 2 ** BalShRun Copies,Forms=" " File BALSHLST;Dev=LP,,!Copies!Forms Run BALSHX ** ClientPL PrintPL 2,9 ** CorporatePL PrintPL C,12 ** DivisionPL PrintPL 1,13 ** PrintPL FileCode,Copies=1 File PLFLA=PLFL!FileCode,Old File PRPALLST=PRPL!"FileCode"LST;Dev=LP,9,!Copies;& Forms=BLANK 8 1/2 by 11 PAPER REQ G. Run PRPALX ** Here is what to look for in these examples: 1. There are seven UDCs, but only two actually RUN a program; the other five just reference those two. 2. In the case of the balance sheet program (BALSHX), we need to print the report on both blank paper and regular green bar paper. The program takes very little time to run, so we run it twice, once with each UDC, to create two different spool files with a different number of copies for each. In one case, the FORMS parameter and value is provided, and in the other case, the default value is used. 3. In the case of the profit and loss program (PRPALX), we need to print a different number of copies of each type of statement. Additionally, because of the way the program is set up, there is a different input file for each type of statement. There is actually only one character different in each file name, so the FILECODE parameter is used to provide that. 4. In UDC PRINTPL, notice the use of quotation marks (") around the FILECODE parameter. This is because it needs to be substituted in the middle of a "word". 5. In that same UDC, also notice the use of the ampersand character (&) to continue the logical line onto the next physical line of the UDC. Were all of that to have been typed on the same line, it would have gone beyond the 80-character limit for a line. 6. In this example, the UDC definitions have been provided after their references, so RECURSION does not need to be specified. If, however, they were not listed in this sequence, RECURSION would be required in each of the UDCs that does not have a RUN command. What if you have two different users that need to use the same program, but do not use the same "terminology?" Create two UDCs that RUN the same program. The invoicing/accounts receivable system provides a good example. There is one set of users who work with the invoicing part of the system and a second set who work with the accounts receivable part of the system. It is really all one application system, but the two user groups tend to think of them as (related, but) separate entities. So... Invoices InvRecRun ** ARec InvRecRun ** InvRecRun Option NoBreak File ENAME.PUB;Shr File TODAT=TODAT.GLXEQ;Shr Run INVRECX;Lib=G ** In this example, each user group has a UDC that makes sense to them but both end up at exactly the same place! Since most of you are probably programmers, let us look at a couple of UDCs you may find useful in your day-to-day existence. A list of two is by no means an exhaustive list, but rather some ideas to get you started: DBSchema SchemaFile Option List File DBSTEXT=!SchemaFile File DBSLIST;Dev=LP Run DBSCHEMA.PUB.SYS;Parm=3 Reset DBSTEXT Reset DBSLIST ** LinkI ProgName, XL="XL.Pub" Option List Link ^!"ProgName"L,!"ProgName"X;XL=!XL ** There is not a whole lot to explain here -- nothing fancy -- just examples of commands and tasks that you may do every day. The only item I will mention is the use of OPTION LIST which displays the command as it is executed. This helps remind me I am using a UDC and that some day, somewhere, I may need to type this longer command. Now for some UDCs the system operator would likely find useful: AfterChecks LDevNum Option List Spooler !LDevNum;Start ** BackUp Option List Stream BackUpJ.Oper.Sys Limit 1,1 ** BeforeChecks LDevNum Option List Continue Spooler LP;Start Spooler !LDevNum;Stop HeadOff !LDevNum ** JobF Priority = 0 Option List JobFence !Priority ** OutF Priority=1 Option List OutFence !Priority ** RCop FileNumber, Copies=1 Option List SpoolF !FileNumber;Alter;Copies=!Copies;Show ** RPri FileNumber, Priority=8 Option List SpoolF !FileNumber;Alter;Pri=!Priority;Show ** RPur FileNumber Option List SpoolF !FileNumber;Delete;Show ** SetOpKeys Option LogOn SFK 1 0 " Reply " " " 6 "Reply " SFK 2 0 " Redo " " " 4 "Redo" SFK 3 0 " Recall " " " 6 "Recall" SFK 4 0 " System " " Up " 5 "SysUp" SFK 5 0 " Show " "Reports " 16 "ListSpF @;Detail" SFK 6 0 " SpoolF " "(First) " 7 "SpoolF " SFK 7 0 " ... " "UnDefer " 8 ";UnDefer" SFK 8 0 " System " " Down " 7 "SysDown" UserKeys ** Just the same as the last examples, this is by no means an exhaustive list, but rather a starting point as you consider what makes sense for your system. Now a couple points of interest: 1. We print our checks "hot" to the printer. That is, we stop the spooler process for the printer itself. Two UDCs make life easier in this situation: BEFORECHECKS and AFTERCHECKS. Nothing fancy; just some steps that have to be done over and over -- and done CORRECTLY every time. 2. In the SETOPKEYS UDC, the SFK UDC is referenced. This will be discussed later. For the time being, just understand that the SETOPKEYS UDC will cause the terminal function keys to be loaded with this information. If you are getting tired of examples, feel free to go on to the next section. For those of you who want more examples, we will next look at some of the UDCs from my system- level UDC file, and then finish up with some unique "goodies" that may prove useful to some of you. AboJ JSNumber Option List AbortJob #!JSNumber ** AltJ JobNumber,InPriority=8 Option List AltJob #J!JobNumber;InPri=!InPriority ** Files Option LogOn, List File LP;Dev=LP File FastLP;Dev=FastLP File SlowLP;Dev=SlowLP File T;Dev=TAPE Comment The above file commands are in effect. ** L FileSet="@",Detail=2,ListFile=$STDLIST Option List ListF !FileSet,!Detail;!ListFile ** LEq Option List ListEq ** LT FileSet="@",Detail=2,ListFile=$STDLIST Option List ListFTemp !FileSet,!Detail;!ListFile ** LUDC Option List ShowCatalog ** Out Detail= " " Option List ListSpF @;!Detail ** Purges FL1,FL2=$NULL,FL3=$NULL,FL4=$NULL,FL5=$NULL,FL6=$NULL Option List Purge !FL1 Purge !FL2 Purge !FL3 Purge !FL4 Purge !FL5 Purge !FL6 ** Quad Command = " " Option List Run QUAD.PUB.CSL3000;Info="!Command" ** SetUDC AnyParm AllParms = $Null Option List SetCatalog !AllParms ** Sort Input,Output Option List File INPUT=!Input File OUTPUT=!Output Reset LIST Run SORT.PUB.SYS ** T Option List ShowTime ** Make note of the FILES UDC. Option LOGON has been specified so that the file commands are established for every session or job that logs onto the system. Also note the use of ANYPARM in SETUDC. This makes this UDC extremely flexible by permitting the user to specify any required files and/or parameters for a given situation. The remainder of the UDCs simply exist to make it easier to accomplish a particular task, generally by eliminating some of the keystrokes that would be required without the UDC. OK, now for those unique "goodies" I promised you. Have you been looking for a way to load information into your terminal's function keys automatically? If you have, keep reading. If you have not, perhaps you want to know why you would want to. Using the function keys to execute commands is a good alternative to UDCs because the overall system overhead is usually less. Function keys also provide a one or two keystroke execution of commands. Why am I telling you about an alternative to UDCs?!? Because the solution is accomplished with UDCs. My source for this information is the November 1987 issue of Interact magazine. In that issue, Michael J. Parker and Lynn Wilson of State Farm Insurance in Bloomington, Illinois, had a short piece in the "Users' Forum" section of the magazine. I have successfully used a modification of their ideas on all of the terminals I have (HP 2392A, HP 700/92, and HP Vectra PC using Reflections 1). I believe it will work on any "HP" "terminal" that has the capability of "labeling" the function keys on the screen. There are three parts to the solution: Two UDCs that need to be defined once -- probably as system- level UDCs, and one (or more) additional UDC(s) defined that uses the first two. The two system-level UDCs are defined as: SFK Key=1, Attr=0, Head1=" ", Head2=" ", Length=40,& Function=" " Echo &f!"Attr"a!"Key"k16d!"Length"L!Head1!Head2!FunctionMA ** UserKeys Echo &jBMA ** The SFK UDC accepts the information for one function key and "loads" that information by causing it to be displayed on the terminal with the ECHO command. Be careful when you type this one in: Upper and lowercase makes a difference in how it will execute! The KEY parameter signifies which function key (1 through 8). The ATTR parameter indicates what should happen when the function key is pressed: Values for the Attribute (ATTR) parameter of the SFK UDC Value Action to be Taken 0 NORMAL. The defined string is displayed. To execute it, the user must press the RETURN key. 1 LOCAL ONLY. The defined string is displayed; it may not be executed, however. 2 TRANSMIT. The defined string is displayed and immediately executed. The HEAD1 and HEAD2 parameters provide values to be placed in the labels on the screen. LENGTH indicates how many characters are in the function string. And finally, the FUNCTION parameter provides the actual character string to be "loaded" into the function key. The USERKEYS UDC simply causes the function key labels to be displayed on the terminal screen (if they are not already). The "MA" sequence in both UDCs effectively "erases" the lines from the screen as the UDC executes. If you would like them left on the screen, that sequence could be left off the end of the line. What might the UDCs that use these look like? Here is an example: SetMainKeys SFK 1,2," "," Query ",17,"Run QUERY.PUB.SYS" SFK 2,2,"DataBase","Utility ",18,"Run DBUTIL.PUB.SYS" SFK 3,2," Show "," Jobs ", 7,"ShowJob" SFK 4,2," ","FormSpec",20,"Run FORMSPEC.PUB.SYS" SFK 5,2," "," Quad ",20,"Run QUAD.PUB.CSL3000" SFK 6,2," List ","Reports ",16,"ListSpf @;Detail" SFK 7,0,"Link Prg","Indirect", 6,"LinkI " SFK 8,0," Change "," Group ", 8,"ChGroup " UserKeys ** It is important to note that two eight-character labels must be provided for each of the function key labels. Also, either the actual lengths of the commands must be provided, or the command string must supply forty characters (the default value in SFK). If this advice is not followed, the function key load will likely not work. If you want to take this a step further (although you do get back your saved UDC overhead), instead of RUNning each of the programs, execute a UDC to do so. In the UDC for each program, execute a UDC before and after the RUN command to load the keys for the program about to be run and then reset them afterwards. For example: Query SetQueryKeys Run QUERY.PUB.SYS SetMainKeys ** DBUtil SetDBUtilKeys Run DBUTIL.PUB.SYS SetMainKeys ** Do remember to place these in the UDC file prior to the SETMAINKEYS and each of the SETxKEYS UDCs, or use the RECURSION option. By using this nesting technique, you can set up a "menu" system with only UDCs and terminal function keys. Neat, huh?!? Now for "goodie" number two. Have you ever wanted to get rid of a set of files but did not really want to type PURGE over and over and did not have access to MPEX? Now you can (maybe)! This idea came from the March 1988 issue of The HP Chronicle. Victoria Shoemaker (of Taurus Software) in her :NEWUSER column, presented this novel solution to the problem: PurgeFS FileSet Option List Store !FileSet;$Null;Show;Purge ** This UDC STOREs the file set you specify to $NULL (which does nothing -- you do not even need to REPLY to a console request!) and then PURGEs the files afterwards. This format of the STORE command is normally used to archive information and then remove it from the system -- we just happen to be archiving to the "bit bucket". Any file set that the STORE program will accept (including the "-" option) can be provided to this UDC. Be careful with this one -- it can be very powerful. Make sure you have a good backup before you type PURGEFS "@.@.@"! "Goodie" number three. Do you need a way to provide different "welcome" and/or "news" messages for each user? If so, read on. This one comes from an article M.E. Kabay (of JINBU Corporation) wrote in the March 1988 issue of The HP Chronicle. Originally, his UDC utilized a program named LIST found in the TELESUP account. MPE XL's PRINT command now serves the same purpose. Here's a system-level UDC: SysMessage Option LogOn Print NEWS.PUB.SYS ** If an account needs a special message or "news" file, set up an account-level UDC for it: AcctMessage Option LogOn Print NEWS.PUB.ACCT ** Special needs for a user? Try this user-level UDC: UserMessage Option LogOn Print NEWS.GROUP.ACCT ** By having all of these separate files, you can easily provide different information to different users or accounts by including it in their own news file. To update a file, simply use your favorite text editor. One last "goodie". This one permits you to send a message or list the contents of an entire file on any terminal screen that is turned on but not logged on: Send LDev,Source File TERM;Dev=!LDev Continue FCopy From=!Source;To=*TERM Reset TERM ** This UDC, when executed, uses the FCOPY program to copy the specified file to the specified terminal. Again, the destination terminal must be turned on but logged off for the message to be displayed. If $STDIN is provided for the SOURCE parameter, then the user can type whatever he/she wishes at the time of the UDC execution. (This can be a little tricky though -- there is no prompt and you must type ":EOD" to end your message.) A situation where I find this UDC helpful is after a backup has completed, and I need to let users know they can logon. Consider the following: SendToAll Source Send 100,!Source Send 101,!Source Send 102,!Source Send 103,!Source Send 104,!Source Send 105,!Source Send 110,!Source Send 111,!Source Send 112,!Source Send 113,!Source Send 114,!Source Send 115,!Source Send 120,!Source Send 121,!Source Send 122,!Source Send 123,!Source Send 124,!Source Send 125,!Source ** If I type: SENDTOALL SYSTEMUP.OPER.SYS then it will attempt to transmit the contents of file SYSTEMUP.OPER.SYS to each terminal. If a particular terminal is not turned on, or is already logged on, that FCOPY will fail, but because of the CONTINUE command, the next one will still be attempted. 2.8 What are some problems I may have while using UDCs? Throughout the tutorial, I have provided a number of warnings and gotchas. Listed here (in somewhat random order) are a few worth repeating and a few not mentioned previously. If a system- and a user-level UDC have identical names and an account-level UDC (with NORECURSION in effect) references a UDC by this name, then the system- level UDC will be executed because of the UDC hierarchy. If RECURSION is in effect, the user-level UDC will be executed instead. If an error or warning occurs as a UDC executes, MPE XL will: 1. Print an appropriate error message. 2. Unless NOHELP is specified, print a caret (^) pointing to the error. 3. Unless NOHELP and NOLIST are specified, print the line in which the error occurred. Every time a user logs on, a UDC directory is created for that session or job. If an error occurs during this initialization, only the UDC level in which the error occurs will fail to be initialized. All others will still be enabled. If the SETCATALOG is executed as part of a UDC, it will be the last command executed in the UDC body. Additionally, if the SETCATALOG was part of a nested UDC, all levels of UDC execution are terminated after completion of the SETCATALOG command. If you execute a UDC that RUNs a program, you press BREAK, and then execute the SETCATALOG command while in BREAK, you may type RESUME, and continue with that program; however, any further execution of the UDC that issued the RUN command will be terminated. UDCs are not always as secure as you might think. Certain programs and subsystems enable users to enter MPE XL system commands, RUN programs, and execute UDCs and command files. So even if you have a UDC with LOGON and NOBREAK specified, the user may still gain access to MPE XL. When you run a program, you may no longer have access to your UDCs. The COMMAND intrinsic can be used only to execute MPE XL system commands. To have access to your UDCs, they must have been defined with OPTION PROGRAM, and the program must use the HPCICOMMAND intrinsic to execute a UDC. Consider using the CONTINUE command wherever possible. This will help prevent a program from aborting and terminating the UDC execution. Even though it may seem unlikely that a program will abort, it can be accomplished in many programs by typing :EOD when prompted for input. This causes an end of file condition on $STDIN and gives many programs problems. Even though you have disallowed certain commands to a user (by redefining them with a UDC), be careful. If the user has access to the COMMAND intrinsic (e.g., through EDIT/3000), the user can still execute most MPE XL system commands. If instead, the user's access is to the HPCICOMMAND intrinsic, the UDCs should still redefine the commands. When modifying a UDC file, make sure all users (sessions and jobs) accessing that file have either logged off or disabled UDCs with the SETCATALOG command. If you are working on a system-level UDC file, that means every session and job on the system is affected! If you get rid of a user (with the PURGEUSER command) who has UDCs enabled, the entries are NOT removed from COMMAND.PUB.SYS. Always execute a SETCATALOG command to disable UDCs for the user before purging the user. Here is a question you have not asked yet: Is there a maximum number of UDCs that may be enabled for a user? The answer is: Not really. Every UDC enabled for a job or session must have an entry placed in a UDC directory stored in transient space. When transient space is completely used, you have reached the maximum number of UDCs. In practical terms, however, you will likely experience poor system response (especially at logon time) before you ever create the maximum number of UDCs! UDCs bring with them system resource overhead at logon time, and they use up part of the system's transient space. The transient space is used to store the UDC directory for each job or session. To reduce overhead and improve system performance when UDCs are used, do whatever you can to reduce the number of UDC files. This will reduce the number of FOPEN calls. If you keep these potential problems and limitations in mind as you start your adventure into the wonderful world of UDCs, you should do well in avoiding most of the problems and pitfalls along the way. 2.9 Are we done with UDCs yet!?! Yes! At least for the time being. And now for something completely different... 3 What are JCWs? JCW is one of the many acronyms used in the HP3000 world. This one comes from the phrase Job Control Word. A JCW is MPE XL's way of permitting programs and commands to communicate with each other within a given job or session. JCWs are unsigned 16-bit integer variables used at the operating system level with values ranging from zero through 65,535. Each JCW has a name and can be set and/or interrogated either by the operating system, MPE XL system commands, or programs. 3.1 A brief comparison of JCWs and session-level variables. An extremely close relative (adopting parents?) of the JCW is the variable. JCWs are actually a subset of session-level variables, being restricted by values and naming conventions. The MPE V idea of providing users with operating system-level variables was expanded in MPE XL to include data types other than numeric. MPE XL session- level variables can retain data in boolean form, 32-bit numeric form, and string form. JCWs are able to retain information in 16-bit numeric form only. These new variable types have made it possible for MPE XL to provide a wealth of new information not readily available to the user previously. The information in the predefined variables range from the formatted time of day, and job count, to the interactive state and CPU time used. Other variables are able to control the user's environment, such as changing the MPE XL prompt and automatically logging the user off if there has been no activity within a given amount of time. A further discussion of variables is outside the scope of this tutorial. As we progress through the JCW material, however, there will be occasional references to variables. I strongly encourage you to learn all you can from other sources about variables. They will open up many doors you may not even know you want open! 3.2 How can JCWs help me? - or - Why would I want a program to talk to my commands? Good questions! Properly used JCWs will permit you to create "smarter" jobstreams. They can help to automate some of the decision making process in procedures. JCWs will permit a program to pass a numeric value to another program without the use of a file, or interprocess communication. They can even help you catch errors before they become a problem! All of this is to say: JCWs can help make the system more user friendly. By testing JCWs against specific values, the user can program conditional statements that take action(s) based on the results of the test. JCWs can be set to predetermined values to indicate completion of steps within a procedure. JCWs can be checked to determine if certain events (usually errors) have occurred within MPE XL. With some limitations, JCWs can be used to pass control totals between programs. 3.3 OK, I think I see how they could help me. So, how do I create and use a JCW? First, some background information. JCWs are stored, along with standard variables, in the session Variable Table managed by MPE XL. This table is shared by all processes in a given job or session. Three classes of JCWs exist: user-defined JCWs; system- defined JCWs; and system-reserved JCWs. In some ways, they are exactly the same -- in other ways, they are completely different. 3.3.1 User-defined JCWs. User-defined JCWs are named and assigned values solely by the user. MPE XL never changes the value of, or interrogates a user-defined JCW. The user creates and assigns a value to this class of JCWs with the SETJCW command or the PUTJCW intrinsic. The JCW name must begin with an alphabetic character and consists of a maximum of 255 alphabetic or numeric characters. The JCW name may not contain an underscore ( _ ) even though this is acceptable for standard variable names. You may not begin a JCW name with the mnemonic names OK, WARN, FATAL, or SYSTEM except under very specific conditions. (If you want to know what the conditions are, see the HP "Commands" manual.) The value assigned to a user-defined JCW must be in the range of zero to 65,535 inclusive. User-defined JCWs can be interrogated by the user with the SHOWJCW command and the FINDJCW intrinsic. These new commands and intrinsics will be discussed later, so please be patient. 3.3.2 System-defined JCWs. System-defined JCWs are named by the system and assigned values by the system and/or by the user. Both the system and the user may interrogate system-defined JCWs. Only two system-defined JCWs exist: JCW and CIERROR. Both are created and set to zero at the beginning of every job or session. They will remain zero unless an error occurs or the user changes their value. The JCW named JCW is set by MPE XL and some subsystems. It is checked before each step (process) in a session or job. Based on its value, MPE XL may abort the job or UDC execution. (See a discussion of the CONTINUE command elsewhere.) The JCW named JCW has two special values as identified in the table below. Special values for the JCW Named JCW Value of the JCW JCW Message Displayed / Meaning 49,152 (System 0) Program aborted per user request. A value greater than 49,152 Program terminated in an error state. The CIERROR JCW keeps track of command interpreter (CI) errors: When a CI error occurs, CIERROR is set to reflect the error number. Valid commands do not reset CIERROR to zero. Thus, it always contains the number of the last error that occurred, unless the user resets its value. Generally, it is best not to alter the values of the system- defined JCWs. If you need to control a JCW, it is best to use a user-defined JCW. 3.3.3 System-reserved JCWs. System-reserved JCWs are named and assigned values solely by the operating system. Users may not change the value of a system-reserved JCW. They can, however, interrogate it. There are six system-reserved JCWs: HPMINUTE, HPHOUR, HPDAY, HPDATE, HPMONTH, and HPYEAR. The following table briefly explains each system-reserved JCW. The Six System-Reserved JCWs JCW Name JCW Description Possible JCW Values HPMINUTE Minute of the hour 0 through 59 HPHOUR Hour of the day 0 through 23; Midnight = 0 HPDAY Day of the week 1 through 7; Sunday = 1 HPDATE Day of the month 1 through 31 HPMONTH Month of the year 1 through 12; January = 1 HPYEAR Year of the century 0 through 99 3.3.4 JCW usage in jobs and/or sessions. OK, so now you know what JCWs are. You even know about the three classes of JCWs and what who can do to what. But, how do you look at or set their values? How do you delete a JCW? For jobs or sessions, the answer is: With the SHOWJCW, SETJCW, and DELETEVAR commands. The first two correspond to the MPE XL system commands SETVAR and SHOWVAR used on standard variables. (Actually, these variable commands may be used to set and display existing JCWs. However, with the SHOWVAR command you will also get a list of all standard variables along with your JCWs.) MPE XL distinguishes between variables created by the SETJCW command and those created by the SETVAR command by way of an internal "flag". 3.3.4.1 The SHOWJCW command. The SHOWJCW command displays the current value of one or more JCWs. Its syntax is: SHOWJCW [jcwname] where jcwname is a valid JCW name (any class). If a name is provided, then only the value for that JCW will be displayed. If a name is not provided, then all system-defined and user-defined JCWs and their values are displayed -- system-reserved JCWs are not displayed. This command can be executed from a session, job, program, or in BREAK. It is BREAKable (it aborts execution of the command). If no user-defined JCWs have been created and the user types: SHOWJCW the system will respond with: CIERROR = 0 JCW = 0 unless some error has occurred prior to this command. If you wish to see the current value of a specific JCW, you might type: SHOWJCW HPDAY and the system would respond with: HPDAY = 3 SYSTEM RESERVED JCW Or, if you typed: SHOWJCW UPDATEERRORS and UPDATEERRORS was a valid user-defined JCW name, the system would respond with: UPDATEERRORS = 2 3.3.4.2 The SETJCW command. Big deal, so you can look at the value of a JCW. So what?!? OK, let me tell you how you can change or set the value of a JCW -- that is a little more productive. We need the SETJCW command to do this: [+ value] SETJCW jcwname = value [- value] where jcwname is the name of a new or existing user- or system-defined JCW and value represents one of the following: An octal number between zero and %177777, inclusive. A decimal number between zero and 65,535, inclusive. An MPE XL-defined JCW value mnemonic (OK, WARN, FATAL, or SYSTEM) The name of an existing JCW. All values must be in the range of zero to 65,535, inclusive. That is, if the "+" or "-" option is used, the result of the arithmetic must be in the range as well. (The equal sign following the jcwname may actually be one or more punctuation characters or spaces, except "%" and "-". If you prefer some other notation, feel free...) This command can be executed from a session, job, program, or in BREAK. It is not BREAKable. When the SETJCW command is executed, it causes the MPE XL session Variable Table for your job or session to be scanned for the name of the specified JCW. If the name is found, the JCW is set to the value provided. If the name is not found, it is added to the table and then set to the value provided. If "@" is used for jcwname, all user-changeable JCWs for your job or session will be set to the value provided. Once a JCW is created, it exists for the duration of that session or job, or until the DELETEVAR command or the HPCIDELETEVAR intrinsic is used to delete it. For example, to set a JCW called UPDATEERRORS to a value of 3, you would type: SETJCW UPDATEERRORS=3 To set all user-changeable JCWs to zero, you could type: SETJCW @=0 And finally, if you wanted to create a JCW that had a value representing 2 days from now, you could type: SETJCW TWODAYSFROMNOW=HPDAY+2 This will take the current value from the system-reserved JCW HPDAY and add two. Obviously you would need to follow the statement with an "IF" statement to handle the end of the week, but I think you probably get the idea. You can change the value of an existing JCW by using either the SETJCW or SETVAR commands or the PUTJCW or HPCIPUTVAR intrinsics. If you assign a value to a JCW with the variable command or intrinsic that is not valid for JCWs, but is valid for standard variables, then MPE XL reclassifies the JCW as a standard variable, sets it to the new value, and prohibits you from using it as a JCW. If, however, you later set it to a valid JCW value with the SETJCW command or PUTJCW intrinsic, it is again reclassified as a JCW. When MPE XL reclassifies a JCW or standard variable it provides one of the following messages, as appropriate: JCW VARIABLE RECLASSIFIED AS A STANDARD VARIABLE. (CIWARN 8126) STANDARD VARIABLE RECLASSIFIED AS A JCW VARIABLE. (CIWARN 8127) 3.3.4.3 The DELETEVAR command. There is no command designed specifically to delete JCWs. However, since JCWs are a subset of session-level variables, the DELETEVAR command may be used to delete JCWs. Its syntax is: DELETEVAR variablename [,variablename]... where variablename is the name of an existing user-defined JCW (or user-defined variable). Wildcard characters may be used to delete multiple JCWs (and variables) at one time. If "@" is used for variablename, all user-defined JCWs (and all user-defined variables!) for your job or session will be deleted. It should be noted that only user- defined JCWs (and user-defined variables) can be deleted. This command can be executed from a session, job, program, or in BREAK. It is not BREAKable. For example, to delete a JCW called UPDATEERRORS, you would type: DELETEVAR UPDATEERRORS To delete all user-defined JCWs (and all user-defined variables), you could type: DELETEVAR @ 3.3.4.4 The JCW value mnemonics. A word or two about the four JCW value mnemonics. They are shown in the table below. JCW Value Mnemonics Mnemonic Value OK Zero WARN 16,384 FATAL 32,768 SYSTEM 49,152 These are strictly mnemonics for specific values -- they cannot be used as JCW names. You may use a combination of a mnemonic and a number to indicate a value between two mnemonics. If you specify: FATAL32 for example, an implied addition takes place (32,768 + 32) and the value would be 32,800. The "+" and "-" option can also be used with mnemonics. For example: FATAL - 768 will result in a value of 32,000. If the SHOWJCW command is used to display current JCW values, and a value is greater than one of the mnemonics, then the value will be displayed as the mnemonic plus the amount over. For example, a value of 16,386 will be displayed as: WARN2 An exception to this is that any value less than 16,384 will be shown as the actual number. You are still not feeling very productive with JCWs yet, right!?! OK, here is the good stuff. JCWs are most often used to control the flow of batch jobs (they can also be used in UDCs and/or in sessions), taking various actions based on the results of previous steps. To do this, the IF/THEN, ELSE, ELSEIF, ENDIF, WHILE and ENDWHILE commands are used. For purposes of this tutorial, I am going to assume you either know how these MPE XL system commands work or can easily acquire the knowledge as we look at examples. (Some examples will come later that should clear up some of your questions.) 3.3.5 JCW usage in programs. Now, for you programmer-type people, we will look at how to interrogate, set, and delete JCWs from within a program. The intrinsics FINDJCW, PUTJCW, and HPCIDELETEVAR will be utilized. The first two correspond to the MPE XL system commands HPCIGETVAR and HPCIPUTVAR used on standard variables. (Actually, these variable intrinsics may be used to set and display existing JCWs. However, with the HPCIGETVAR intrinsic you will also have access to all standard variables along with your JCWs.) MPE XL distinguishes between variables created by the PUTJCW intrinsic and those created by the HPCIPUTVAR intrinsic by way of an internal "flag". My examples are based on COBOL II/XL usage; however, I will try to provide information in a general way. 3.3.5.1 The FINDJCW intrinsic. The programmatic equivalent to the SHOWJCW command is the FINDJCW intrinsic. Its syntax (in COBOL II/XL format) is: CALL INTRINSIC "FINDJCW" USING jcwname,jcwvalue,status where jcwname is an alphanumeric variable (character array) containing the name of the JCW to be found, jcwvalue is an unsigned 16-bit integer variable to which the JCW value is returned and status is a signed 16-bit integer variable to which a value denoting the execution status of the intrinsic is returned. The jcwname parameter may contain up to 255 alphanumeric characters, starting with a letter and ending with a non-alphanumeric character, such as a blank. If the requested JCW is found in the session Variable Table, its value is returned to the program in the jcwvalue parameter; if not found, no change is made to this parameter. The status parameter will be returned with one of four possible values shown in the following table. Status Parameter Values for the FINDJCW Intrinsic Status Value Result or Meaning 0 Successful execution: The JCW was found. 1 Error: jcwname is longer than 255 characters. 2 Error: The value of jcwname does not start with a letter. 3 Error: The JCW was not found in the session Variable Table. The FINDJCW intrinsic can be used to return the value of any of the three classes of JCWs. To accomplish the same task in RPG/XL, use the FNDJW operation. Specify the JCW to be found in the Factor 2 Field, either as an alphanumeric variable or literal. Enter the name of the variable to contain the JCW value in the Result Field. This field must be numeric with zero decimal positions. At least one indicator must be provided in the Resulting Indicators Field. The Factor 1 Field is left blank. When FNDJW is executed in an RPG/XL program, the FINDJCW system intrinsic is called. One of the Resulting Indicators is set on to indicate the outcome of the operation as shown in the following table. Resulting Indicator Settings for the FNDJW Operation Resulting Indicator Meaning if the Resulting Indicator is On High Subfield The JCW was not found in the session Variable Table. Low Subfield The JCW name provided does not start with a letter. Equal Subfield Successful execution; The JCW was found. For example, to find what the current value of the JCW JCW is, you could use the following line of RPG/XL code: 6 28 33 43 51 58 <--- (Column numbers) | | | | | | V V V V V V C FNDJW"JCW" JCWVAL 60 20 If the FNDJW operation is successful, indicator 20 will be ON after execution of the line. 3.3.5.2 The PUTJCW intrinsic. The SETJCW command's programmatic equivalent is the PUTJCW intrinsic. Its syntax (in COBOL II/XL format) is: CALL INTRINSIC "PUTJCW" USING jcwname,jcwvalue,status where jcwname is an alphanumeric variable (character array) containing the name of the JCW to be created or changed, jcwvalue is an unsigned 16-bit integer variable containing the value for the JCW, and status is a signed 16-bit integer variable to which a value denoting the execution status of the intrinsic is returned. The jcwname parameter may contain up to 255 alphanumeric characters, starting with a letter and ending with a non- alphanumeric character, such as a blank. If "@" is the value used, all changeable JCWs for your job or session will be set to the value provided. If the specified JCW already exists in the session Variable Table, its value is changed to the value provided in the jcwvalue parameter; if not there, an entry is created and then it is assigned the specified value. The status parameter will be returned with one of eight possible values as shown in the following table. Status Parameter Values for the PUTJCW Intrinsic Status Value Meaning or Result 0 Successful execution: Value entered in the session Variable Table. 1 Error: jcwname is longer than 255 characters. 2 Error: The value of jcwname does not start with a letter. 3 Error: Session Variable Table overflow; No room to create this new JCW. 4 Error: Attempted to assign a value to a JCW value mnemonic. 5 Error: Attempted to assign a value to a system-reserved JCW or a read-only standard variable. 6 Warning: The value of jcwname was a standard variable and has now been reclassified as a JCW. 7 Error: Attempted to reclassify a predefined standard variable. The PUTJCW intrinsic can only be used to assign a value to a user-defined JCW, system- defined JCW, or user-defined variable. See the information about reclassification of JCWs and standard variables in the previous SETJCW section. To accomplish the same task in RPG/XL, use the PUTJW operation. Specify the value to be assigned to the JCW in the Factor 1 Field, either as a numeric literal or field. This field must be no more than 8 digits long with zero decimal positions, and must contain a number in the range, 0 - 65,535. A run-time error will occur if the value is outside of this range. Specify the JCW to be set, or created and set, in the Factor 2 Field, either as an alphanumeric variable or literal. At least one indicator must be provided in the Resulting Indicators Field. The Result Field is left blank. When PUTJW is executed in an RPG/XL program, the PUTJCW system intrinsic is called. One of the Resulting Indicators is set on to indicate the outcome of the operation as shown in the following table. Resulting Indicator Settings for the PUTJW Operation Resulting Indicator Meaning if the Resulting Indicator is On High Subfield The session Variable Table overflowed; No room to create this new JCW. Low Subfield The JCW name provided does not start with a letter. Equal Subfield Successful execution; Value entered in the session Variable Table. For example, to create and set JCW NUMERR to the value of ERRCNT, you could use the following line of RPG/XL code: 6 18 28 33 58 <--- (Column numbers) | | | | | V V V V V C ERRCNT PUTJW"NUMERR" 20 If the PUTJW operation is successful, indicator 20 will be ON after execution of the line. As mentioned earlier, if the JCW named JCW is set to exactly 49,152, when the program stops running, the system will display: PROGRAM ABORTED PER USER REQUEST (CIERR 989) If it is set to any value greater than 49,152, then the message displayed will be: PROGRAM TERMINATED IN AN ERROR STATE (CIERR 976) In either case, if the program is running in a batch job or a UDC, the job or UDC will terminate unless a CONTINUE command precedes the RUN command. 3.3.5.3 The HPCIDELETEVAR intrinsic. The DELETEVAR command's programmatic equivalent is the HPCIDELETEVAR intrinsic. Its syntax (in COBOL II/XL format) is: CALL INTRINSIC "HPCIDELETEVAR" USING variablename,status where variablename is an alphanumeric variable (character array) containing the name of the JCW (or standard variable) to be deleted, and status is a signed 32-bit integer variable to which a value denoting the execution status of the intrinsic is returned. The variablename parameter may contain up to 255 alphanumeric characters, starting with a letter (or the underscore, if a standard variable name) and ending with a non-alphanumeric character, such as a blank. (The underscore is not a valid delimiter since it is a valid standard variable name character.) It should be noted that only user-defined JCWs (and user-defined variables) can be deleted. Wildcard characters may be used to delete multiple JCWs (and user-defined variables) at one time. If "@" is the value used for variablename, all user-defined JCWs (and user-defined variables!) for your job or session will be deleted. If no errors or warnings are encountered, all 32 bits of the status parameter are set to zero. If an error or warning is encountered, the first 16 bits (0-15) provide an error or warning number. Error conditions are represented by negative values; warnings are represented by positive values. In an error or warning situation, the second set of 16 bits (16-31) will be set to 166 which is the subsystem identifier for HPCIDELETEVAR. Shown in the table below is at least a partial list of possible error numbers that may be returned. This list was obtained from an old edition of the MPE XL Intrinsics Reference Manual. The current edition does not specifically list the errors, so I am not sure if the list is complete and up to date. Status Parameter Values for the HPCIDELETEVAR Intrinsic (First Word Only) Status Value Meaning or Result 0 Successful execution: JCW or standard variable has been deleted from the session Variable Table. -8106 Error: The JCW or standard variable was not found in the session Variable Table. -8108 Error: Delete failed (internal error). -8110 Error: variablename is not valid. -8114 Error: Internal error (unexpected nil pointer encountered). -8117 Error: Attempted to delete a system-defined JCW, system- reserved JCW, or a read-only standard variable. -8125 Error: Attempted to delete a JCW value mnemonic. -8141 Error: Parameter one bounds violation. -8142 Error: Parameter two bounds violation. -8156 Error: jcwname is longer than 255 characters. 3.3.5.4 Interprocess communication with JCWs. Since JCWs are stored in the session Variable Table (along with standard variables) which is shared by all processes in a job or session, JCWs can be used to permit separate processes within the same job or session to communicate with each other. If a process were to set a JCW to a given value when a certain event occurred, then any other related process could check that JCW to find out when it occurred or what has occurred. Remember, however, that only numeric information can be assigned to JCWs. An example of this is to have program "A" calculate a control total for a file that is needed in program "B". Rather than write the value to a file, display the value on the screen for later human input, or use interprocess communication, we could have program "A" set a JCW to the control total value (as long as it was less than 65,536). Then when program "B" needed the control total, it would simply call FINDJCW to retrieve the value, thus eliminating the need for human intervention, a file, or interprocess communication. The two programs must be run from the same session or batch job however, since JCWs are lost when a logoff occurs. 3.3.5.5 The GETJCW and SETJCW intrinsics. Just so you can't say I didn't tell you about them, two other intrinsics exist: GETJCW and SETJCW. They only permit you to interrogate and set, respectively, the value of the system-defined JCW named JCW. Since they have limited usability and you can use FINDJCW and PUTJCW to accomplish the same thing, I do not suggest learning about them. 3.4 How about some examples? Good idea! First, we will look at some examples in batch jobs, then we will take a look at a couple example programs that use JCWs. 3.4.1 Batch job examples. Since most of us are likely programmers, I will start with an example jobstream I use when working with a program. Virtually all programs created at the N.G. Gilbert Corporation are written in the PROTOS language. For those not familiar with PROTOS, it is a program generator whose output is a complete, structured, COBOL II/XL program. Once the program has been written in PROTOS (and keyed into a file), the next step is to have PROTOS create the COBOL II/XL source program. When PROTOS completes that task, you need to compile the COBOL II/XL source program. The final step is to link the object program to produce the program file. Since I do not want to tie up a terminal, the system, and myself while all of this transpires, I use an "intelligent" jobstream to handle the various tasks (it really does not take that long, but it is more convenient to use a jobstream). !Job prog,Prgrmr.Develop;Pri=ES;InPri=7;OutClass=,1 !Comment This jobstream performs a ProWrite, COBOL II/XL compile, and LINK !Comment of a program. If any errors are encountered along the way, a message !Comment is sent to Prgrmr.Develop, and the jobstream stops running. !SetJCW CIError = OK !SetJCW JCW = OK !Continue !ProWrite progP, prog, $StdList,2000 !If JCW <> OK Then ! Tell Prgrmr.Develop; ProWrite of prog abortedG. !ElseIf PROTOSError <> OK Then ! Tell Prgrmr.Develop; Errors in ProWrite of progG. !Else ! Tell Prgrmr.Develop; ProWrite of prog done. Compile started. ! File CopyLib = PROCopy ! Continue ! COB74XL prog, $NewPass ! If JCW <> OK Then ! If JCW = Warn Then ! Tell Prgrmr.Develop; prog had questionable errorsG. ! Else ! Tell Prgrmr.Develop; Compile of prog had severe errorsG. ! EndIf ! Else ! Tell Prgrmr.Develop; Compile of prog done. Link started. ! Purge progM ! Save $OldPass, progM ! SetJCW CIError = OK ! Continue ! Link progM,$NewPass; XL = XL.Pub ! If CIError <> OK Then ! Tell Prgrmr.Develop; Link of prog was abnormalG. ! Else ! Purge progX ! Save $OldPass, progX ! Tell Prgrmr.Develop; Program prog is done G. ! EndIf ! EndIf !EndIf !EOJ This example demonstrates how you can structure a jobstream to check for errors and take different actions based on the occurrence or non-occurrence of errors. Some points of interest: 1. JCWs JCW, and CIERROR are set to OK (i.e., zero) at the start of the job to guarantee they start at zero. It is possible a LOGON UDC may have failed, and thus one or both of them may have a non-zero value. 2. Even if one of the programs (PROWRITE, COBOL II/XL, or LINK [LINKEDIT]) aborts, the jobstream will continue because of the CONTINUE commands. This permits us to check JCW after each one to see if it aborted. If the CONTINUE commands were not used, the jobstream would abort before we could check the JCWs. 3. PROTOSERROR is a JCW that the PROWRITE program creates and sets equal to the number of errors found in your PROTOS program. By checking it, we can determine whether it is worthwhile to continue with the compile and link steps. 4. Notice that you may nest the IF statements to create whatever logic might be required. Here is a variation of this same jobstream. This version just tells the programmer there is an error, but does not report in detail like the previous version: !Job prog,Prgrmr.Develop !SetJCW CIError = OK !SetJCW JCW = OK !SetJCW False = 1 !SetJCW NoProblems = OK !Continue !ProWrite progP,prog,$STDLIST,2000 !If JCW <> OK Then ! SetJCW NoProblems = False !ElseIf PROTOSError <> OK Then ! SetJCW NoProblems = False !Else ! File CopyLib = PROCopy ! Continue ! COB74XL prog, $NewPass ! If JCW <> OK Then ! SetJCW NoProblems = False ! Else ! Purge progM ! Save $OldPass, progM ! SetJCW CIError = OK ! Continue ! Link progM, $NewPass; XL = XL.Pub ! If CIError <> OK Then ! SetJCW NoProblems = False ! Else ! Purge progX ! Save $OldPass, progX ! EndIf ! EndIf !EndIf !If NoProblems = False ! Tell Prgrmr.Develop; Errors in program prog G. !Else ! Tell Prgrmr.Develop; Program prog is done. !EndIf !EOJ In this version, JCW NOPROBLEMS is set to indicate when an error has occurred and then is checked at the end of the jobstream to determine what to tell the programmer. (Note the creation of JCW FALSE.) Speaking of errors, RPG/XL provides an easy way to identify when a program fails due to an EXCLUSIVE VIOLATION error (FSERR 90 or 91) when trying to open a file. If the program has been compiled with $CONTROL ...any other parameters...;EXCQUIT and a file cannot be opened due to some other process having the file opened exclusively, RPG/XL will close any open file(s) and abort the program immediately (as opposed to printing a formatted dump). RPG/XL also sets the JCW JCW to either FATAL90 or FATAL91. So, this specific error condition can be checked for as shown in this job stream fragment: !Continue !Run RPGPROG !If JCW = Fatal90 or Fatal91 then ! TellOp RPGPROG failed due to an Exclusive Violation error. !EndIf The only change required to the RPG/XL program to cause JCW to be set is to use the EXCQUIT parameter on the $CONTROL statement when compiling the program. The following is a modified version of the jobstream we use to do our daily backups. It serves as an example of using system-reserved JCWs, and a few variables as well. !Job BackUp,Operator.Sys !SetJCW True = 0 !SetJCW False = 1 !SetJCW Monday = 2 !If HPDay = Monday or HPDay = Monday + 3 then ! SetJCW BackUpIsFull = True !ElseIf FInfo("FullDate",0) then ! SetJCW BackUpIsFull = False !Else ! TellOp Full back up date file (FullDate.Oper.Sys) is missing. ! TellOp Performing a Full back up instead of the usual Partial. ! SetJCW BackUpIsFull = True !EndIf !If BackUpIsFull = True then ! SetVar BackUp_Date_F "" !Else ! SetVar BackUp_Date_I FInfo("FullDate",-6) ! SetVar BackUp_Date_C "!BackUp_Date_I" ! SetVar BackUp_Date Str("!BackUp_Date_C",5,2) + "/" + & ! Str("!BackUp_Date_C",7,2) + "/" + Str("!BackUp_Date_C",3,2) ! SetVar BackUp_Date_F ";Date>=" + "!BackUp_Date" !EndIf !SetVar BackUp_File_Set "@.@.Sys,@.@.@-@.@.Sys" !If BackUp_Is_Full = True then ! TellOp Today's back up will be a Full back up. !Else ! TellOp Today's back up will copy all files modified on or after !BackUp_Date. !EndIf !TellOp Please mount a tape for the back up. !If FInfo("LastBack",0) and FInfo("LastBack",6) = HPDateF then ! TellOp It appears that a back up has already been performed today. ! TellOp Abort the job if you do not want it done a second time. !EndIf !File BackUpT;Dev=Tape !Store !BackUp_File_Set; *BackUpT; Directory; Show !BackUp_Date_F; Progress = 5 !If BackUpIsFull = True and HPDay <> Monday + 3 then ! If FInfo("FullDate",0) then ! Purge FullDate ! EndIf ! Build FullDate !EndIf !If FInfo("LastBack",0) then ! Purge LastBack !EndIf !Build LastBack !TellOp The Back Up has completed. The BACKUPJ job stream is done. !EOJ Points of interest in the backup jobstream: 1. Notice the creation of JCWs MONDAY, TRUE, and FALSE. They are not necessary, but make the IF commands read a little nicer. 2. Full back ups should be performed on Monday and Thursday; Otherwise, a partial back up is done. Which to do is decided by checking HPDAY. 3. Notice the use of variables where the required value is not legal for a JCW. Actually, the JCWs could be variables just as easily in this instance. 4. The creation date of file LASTBACK is the last time a back up was performed. The creation date of file FULLDATE is the last time a full back up was performed. Both of these files are built, but contain no data, and as such, do not require any disk space. Their sole purpose in life is to provide the last date an event occurred by way of their creation date. 5. There are over forty MPE XL expression evaluator functions that do and/or tell you virtually anything you want. Used in this jobstream are two of them. FINFO(...,0) returns a value of TRUE if the file exists, and FALSE if the file does not. FINFO(...,-6) returns the creation date of the file as an integer in the form yyyymmdd. FINFO(...,6) returns the formatted creation date of the file. STR(...) extracts individual characters from a character string variable. Here is an example of using the IF command and JCWs to do something they were not designed for, but it works, so why not? The following could be included at any point in a jobstream where JCW would not be equal to FATAL (which could be virtually anywhere): !If JCW = Fatal Then From this point on (up to an ELSE, ELSEIF, or ENDIF command), you can type whatever you wish. The lines do not even need to start with an exclamation point! The reason this works is that when the condition in an IF command is false (which it is in this instance), all command lines are ignored until an ELSE, ELSEIF, or ENDIF command is read. Thus, this provides an easy way to include comments without using the COMMENT command. The "IF" could actually be written "If 1 = 2 Then" (or anything that would evaluate to false), but then it wouldn't be an example of JCW usage! !EndIf Another source of examples is virtually any jobstream from HP. They tend to make extensive use of JCWs (and variables) to control the flow of the jobstream logic. 3.4.2 Programmatic examples. The following is a COBOL II/XL subroutine (actually it was written in PROTOS) I created to call in any situation where I want to end a program and have: PROGRAM ABORTED PER USER REQUEST (CIERR 989) displayed afterwards (granted, this is not very often!). The sole purpose of this program is to set the JCW JCW to a value of 49,152 (octal 140000). $CONTROL DYNAMIC,BOUNDS IDENTIFICATION DIVISION. PROGRAM-ID. SETABORTJCW. AUTHOR. DAVID L LARGENT. DATE-WRITTEN. TUE, OCT 20, 1987, 3:41 P.M. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. ******************************* * Sets JCW to "Program Abort" * ******************************* 01 JCW-NAME PIC X(4) VALUE "JCW ". 01 JCW-STATUS PIC S9(4) COMP. 01 JCW-VALUE PIC 9(4) COMP VALUE %140000. PROCEDURE DIVISION. MAIN-LINE-SECTION SECTION. MAIN-LINE. MOVE ZERO TO JCW-STATUS. CALL INTRINSIC "PUTJCW" USING JCW-NAME JCW-VALUE JCW-STATUS. IF JCW-STATUS NOT = ZERO DISPLAY "Program SETABORTJCW: JCW not set." . GOBACK. This may not be a very useful program to you, as it is printed; however, it does show the basics of what needs to be done to create and/or set a particular JCW to a given value. If your JCW name is longer than three characters, make sure you increase the length of field JCW-NAME. Also, make sure you have at least one blank or other non- alphanumeric character following your JCW name. The value for JCW-VALUE can be specified as a decimal number if you prefer, provided it is less than 10,000. In the example, the octal value was required because 49,152 was too large. If you want the program to stop instantly, you are better off calling the QUIT intrinsic with a parameter value of 16384. However, if you want the program to continue running, so you can perform a "controlled shutdown" of the program, you must take the approach shown above. Here is a trivial example of the FINDJCW intrinsic, but again it shows the basics of what needs to be done to retrieve the value of an existing JCW. $CONTROL BOUNDS IDENTIFICATION DIVISION. PROGRAM-ID. DISPLAYJCW. AUTHOR. DAVID L LARGENT. DATE-WRITTEN. WED, APR 27, 1988, 4:24 A.M. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. ***************************** * Displays the Value of JCW * ***************************** 01 JCW-NAME PIC X(4) VALUE "JCW ". 01 JCW-STATUS PIC S9(4) COMP. 01 JCW-VALUE PIC 9(4) COMP. PROCEDURE DIVISION. MAIN-LINE-SECTION SECTION. MAIN-LINE. MOVE ZEROS TO JCW-STATUS JCW-VALUE. CALL INTRINSIC "FINDJCW" USING JCW-NAME JCW-VALUE JCW-STATUS. IF JCW-STATUS NOT = ZERO DISPLAY "Program DISPLAYJCW: JCW not found." ELSE DISPLAY "JCW = " JCW-VALUE . STOP RUN. Same comments as last time: Make sure you set up JCW-NAME large enough to hold your JCW name and make sure you end it with at least one blank or other non- alphanumeric character. 3.5 What are some problems I may have while using JCWs? Throughout the tutorial, I have provided a number of warnings and limitations. Listed here (in somewhat random order) are a few worth repeating. A JCW name must start with a letter and can consist of a maximum of 255 alphabetic or numeric characters. The value assigned (whether a number or a calculated value) must be in the range of zero to 65,535, inclusive. The system-reserved JCWs may not be assigned a value by a program or the user, nor may they be deleted. If you want to check for program errors (e.g., program aborts), make sure to include a CONTINUE command before the RUN command. Also, make sure JCW and CIERROR are set to zero (or OK) beforehand. Remember, the only thing that changes the values of CIERROR and JCW (except the user) is another error. That is, a valid command does not set them to zero! Although JCWs can have any value from zero through 65,535, only values from zero through 16,383 will be displayed as numbers by the SHOWJCW command. Values larger than 16,383 will be displayed as a JCW value mnemonic and an offset beyond the mnemonic value. When calling PUTJCW or FINDJCW from a COBOL II/XL program, make sure the JCW-STATUS field is defined as S9(4) COMP, and the JCW-VALUE field is defined as 9(4) COMP. The program will not compile or run correctly if they are not. When you use the PUTJCW intrinsic or the SETJCW command to set or alter the value of a standard variable, that variable will be "flagged" as a JCW, and must be treated as such. When you create a new standard variable with the HPCIPUTVAR intrinsic or the SETVAR command, it will not be flagged as a JCW, even though its value may be within the valid range for a JCW. It is possible to reset the value of an existing JCW with the HPCIPUTVAR intrinsic or the SETVAR command. As long as the new value is still within the valid range for a JCW, it will remain classified as a JCW. Is there a maximum number of JCWs that may be created for a user? The answer is yes. Every JCW (and standard variable) created for a job or session must have an entry placed in the session Variable Table. When that table becomes full, you have reached the maximum number of JCWs (and standard variables). The size of the table is governed by the amount of space left for your session or job after file equations, temporary files, and data space is allocated. In practical terms, however, I doubt you will ever create that many JCWs! 4 How can I use UDCs and JCWs together? UDCs and JCWs can be used together very effectively. JCWs can control the flow of logic within a UDC. A UDC (by way of its parameters) can gather information and use that information to set JCWs so that a program can then interrogate them and take appropriate actions. So, let us look at some examples of combining these two powerful capabilities. 4.1 Examples of combining UDCs and JCWs. To start off with, we will look at some logon UDCs. First, a simple addition to the system-level logon UDC to make use of the system-reserved JCW HPDAY easier. By including this UDC (or its functionality) in the system-level logon UDC, the following seven JCWs will always be available for use in IF commands. SysLogOn Option LogOn,NoBreak SetJCW Sunday = 1 SetJCW Monday = 2 SetJCW Tuesday = 3 SetJCW Wednesday = 4 SetJCW Thursday = 5 SetJCW Friday = 6 SetJCW Saturday = 7 ** Next, a way to have one thing automatically happen when a session logs on, and something else when a job logs on. This makes use of the HPINTERACTIVE standard variable which has a value of "true" if checked from a session, and "false" if checked from a jobstream. Also note that a job can be setup to do other things after the logon program runs because there is not an automatic BYE as there is for the session. UserLogOn Option LogOn, NoBreak If HPInteractive then Continue Run ... (online program) Bye Else Run ... (batch program) EndIf ** Here is a way to control when people logon and play games: GamesLogOn Option LogOn,NoBreak If HPDay = Sunday or HPDay = Saturday or HPHour < 8 or HPHour > 17 or HPHour = 12 Then Echo Welcome to the Game Room Else Echo Sorry, the Game Room is closed. Echo Hours: Saturday and Sunday: all day Echo Monday-Friday: Before 8 a.m., After 5 p.m. Echo and Noon to 1 p.m. Bye EndIf ** If it is Saturday or Sunday, or before 8 a.m., after 5 p.m., or sometime during the noon hour, this UDC will let the user stay logged on -- any other time and the user will automatically be logged off. Note that if the user gets logged on during an "open" time, they can continue playing forever -- there is nothing to force them off when the game room closes. To accomplish this, a check could be added to each of the UDCs set up to run the individual games. If you ever need a UDC to know whether you are running on an MPE V machine, or an MPE XL machine, take a look at the following UDC. MachineTest Option NoList SetJCW CIError = OK Continue ShowVar If CIError = 8116 then <<< Commands for MPE XL system >>> Else If CIError = 975 then <<< Commands for MPE V system >>> Else <<< Who knows what we're running on! >>> EndIf EndIf ** The premise behind finding out what machine type you are running on is to issue a command such that it will produce a different error on MPE V and MPE XL. The SHOWVAR command satisfies this requirement. Have you ever gotten frustrated with yourself when you logged off because you typed EXIT at a colon prompt and did not realize you were running your first level of the CI? Well, here is a solution to that problem. This will be most effective as a system-level UDC. It actually uses standard variables rather than JCWs, but I still feel it is worth your seeing. Exit If HPInteractive and HPCIDepth = 1 then Input Answer, "Do you really want to logoff? (N/Y)" If Answer = "Y" or Answer = "y" or Answer = "YES" or Answer = "yes" then Bye EndIf Else Exit EndIf ** Notice the use of the INPUT command to get a response from the user. The quoted phrase is displayed, and then MPE XL waits for a response from the user. HPInteractive and HPCIDepth are standard variables. We already talked about HPInteractive; HPCIDepth returns a number indicating what copy of the command interpreter (CI) you are currently running. In case you are not aware, you can run the CI from within the CI from within the CI, etc.. To back up to the previous copy of the CI, you use the MPE XL EXIT command. If EXIT is used at the first level, however, it performs as if you had typed BYE. This UDC gives you a second chance to change your mind before MPE logs you off. Now let us look at a UDC in which information is passed to a program by way of JCWs. This example is from the UDCs PROTOS Software Company provides with the PROTOS language: PROWRITE F,C="C",L=$NULL,S=1023,R=ROOTDB,Q=0,G=PROTOS,A=PROTOS SETJCW PROBUILDWRITE=2 SETJCW QEDITOUT=!Q FILE SEMPASS=SEMPAS01.!G.!A;SHR FILE SEMDOPE=SEMDOP01.!G.!A;SHR FILE SSERR=SSERR.!G.!A;SHR FILE SEMTEMP=SEMTMP01.!G.!A;SHR FILE ATNIN1=!F FILE ATNOUT2=!L PURGE !C BUILD !C;REC=-80,16,F,ASCII;CODE=EDTCT;DISC=!S FILE COBOLOUT=!C FILE ROOTDB=!R IF QEDITOUT=1 THEN PURGE QECOBOUT,TEMP FILE QECOBOUT;REC=256;DISC=!S;TEMP ENDIF RUN PROTOS.!G.!A IF QEDITOUT=1 THEN PURGE !C RENAME QECOBOUT,!C,TEMP SAVE !C ENDIF RESET SEMPASS RESET SEMDOPE RESET SSERR RESET SEMTEMP RESET ATNIN1 RESET ATNOUT2 RESET COBOLOUT RESET ROOTDB ** In this example, there are two JCWs used to pass information to the PROTOS program: PROBUILDWRITE and QEDITOUT. The QEDITOUT JCW gets its value from the Q parameter of the UDC. Also, based on the QEDITOUT JCW, different parts of the UDC are executed. JCWs can only be assigned numeric values. So how do you make use of character string information from a UDC parameter? Here is one way: CopyW2ToTape CharSet=X SetJCW A = OK SetJCW E = OK SetJCW !CharSet = 1 If A = OK and E = OK Then Echo An 'A' or an 'E' must follow the copy command.G Else File W2TAPE;Dev=TAPE;Rec=-276,25,F,ASCII If A = 1 Then FCopy From=PR997TAP;To=*W2TAPE Else FCopy From=PR997TAP;To=*W2TAPE;EBCDICOUT EndIf ListF PR997TAP,1 Echo dJ Check the number of records copied.G EndIf ** The purpose of this UDC is to copy a disc file to magnetic tape. The catch is that we need the option of copying it in EBCDIC format; thus, the CHARSET parameter. There are two "correct" responses: A and E. At the beginning of the UDC, two JCWs (A and E) are created and set to zero, then the user's choice is set to one. By having a default value that is not correct, if the user does not provide a value, the UDC will provide a message to the user and "remind" him/her of the correct values. Here is another example of using parameter values from a UDC to establish JCWs that control what the UDC actually does. This UDC comes from Eric Omuro of Complimate, Inc., and is an example of how to eliminate multiple UDCs that are each a slight variation on the same theme -- in this instance, the SHOWJOB command. SJ Parm1 = "EO", Parm2 = " ", Parm3 = " " SetJCW SEO = Warn SetJCW SJ = Warn SetJCW SS = Warn SetJCW SSC = Warn SetJCW SST = Warn SetJCW SU = Warn SetJCW SW = Warn SetJCW SX = Warn SetJCW S!Parm1 = OK If SJ = OK Then ShowJob Job = @J;!Parm2 ElseIf SS = OK Then ShowJob Job = @S;!Parm2 ElseIf SX = OK Then ShowJob Job = @J;Exec ElseIf SW = OK Then ShowJob Job = @J;Wait ElseIf SSC = OK Then ShowJob = @J;Sched ElseIf SST = OK Then ShowJob Status ElseIf SU = OK Then ShowJob Job = !parm2;!parm3 ElseIf SEO = OK Then ShowJob !Parm2 Else ShowJob #!Parm1 EndIf ** The first parameter of the SJ UDC, "Parm1", identifies which format of the SHOWJOB command to execute. Generally, "Parm2" and "Parm3" are only used when executing SJ U. The occurrences of "Parm2" on the other commands offer additional flexibility and challenge the advanced SJ UDC user to figure out how they can be used. Now let us wrap up with one final example: A UDC to present a menu to the user, accept the users choice, perform the selected task, and re-display the menu. Menu WhichReport = Warn Option NoList, NoBreak SetJCW ReportNumber = !WhichReport While ReportNumber <> OK Do If ReportNumber = Warn then Echo Echo Your options are: Echo 1 - Run Report A Echo 2 - Run Report B Echo 3 - Run Report C Echo 9 - Exit to the Command Interpreter Echo 0 - Exit this Menu SetVar Response, " " Input Response,"Enter the number of your selection: " Continue If Numeric(Response) then If !Response <= 65535 then SetJCW ReportNumber = !Response Else SetJCW ReportNumber = Warn EndIf Else SetJCW ReportNumber = Warn EndIf EndIf If ReportNumber = 1 then Continue Run Prog1 ElseIf ReportNumber = 2 then Continue Run Prog2 ElseIf ReportNumber = 3 then Continue Run Prog3 ElseIf ReportNumber = 9 then Echo Echo Type EXIT to return to this menu when done. Continue Run CI.Pub.Sys ElseIf ReportNumber <> OK Echo Echo Your selection was invalid. EndIf If ReportNumber <> OK then SetJCW ReportNumber = Warn EndIf EndWhile ** Since the UDC has a parameter, the user may indicate which report to run without the necessity of displaying the menu the first time. If no parameter value is provided, the menu will be displayed, and the user prompted for their selection. Unless the user has chosen to leave the menu, the JCW REPORTNUMBER is set to the mnemonic WARN at the end of the UDC to force the menu to be displayed. NUMERIC(...) is used to determine if the user typed anything other than digits; This will be false if they did. Also note the provision for temporarily exiting to the command interpreter. 5 Closing thoughts -- "Is it worth the effort of learning something new?" We have looked at User Defined Commands and Job Control Words. Numerous examples have been explored to see how they work and how they can be used. They are a very powerful feature of the HP3000. There is overhead associated with them (especially UDCs), yet, my feeling is that the convenience and "user-friendliness" gained outweighs that overhead. They must be controlled however -- people can get carried away when creating UDCs. So, is it worth the effort? My answer is a (qualified) resounding YES! The qualification is that UDCs and JCWs must be carefully planned and monitored to reap the greatest benefit, but, oh, what a benefit it is: Increased operator, programmer, and user productivity and a computer system that is easier to use overall. HP is a trademark of Hewlett Packard Company. PROTOS is a trademark of PROTOS Software Company. Acknowledgements A special thanks go to the following people who assisted in creating this tutorial (and its predecessors) in some way -- all of their efforts (and tolerance!) are greatly appreciated: H. Lyle Harp Dan Hinds Jonathan Largent Julia Largent Lois Largent Karen Morgan Dawn Thomas Martha Walsh Bibliography Cressler, Scott; Vance, Jeff; and Elmer, Steve "Advanced CI Programming: The 2.1 Story", Interact, February, 1991, page 83ff. Fisher, Sharon "Setting up UDCs", Interact, July, 1984, page 48ff. Griffin, Brad "Another Way to SetJCWs as Part of a Log-on UDC", SuperGroup Association Magazine, June, 1986, page 12. Hewlett-Packard Company Command Interpreter Access and Variables Programmer's Guide, Second Edition, 1990, Chapters 2, 5 and 6. Hewlett-Packard Company Getting Started as an MPE XL Programmer, First Edition, Update 2, 1988, Chapters 1, 2 and 3. Hewlett-Packard Company Getting System Information Programmer's Guide, First Edition, Update 1, 1988, Chapter 3. Hewlett-Packard Company Hewlett-Packard Response Center Questions & Answers, August 1, 1986, page 1. Hewlett-Packard Company HP RPG/XL Programmer's Guide, First Edition, 1988, Chapter 8. Hewlett-Packard Company HP RPG/XL Reference Manual, Second Edition, 1989, Chapters 8 and 12. Hewlett-Packard Company Interprocess Communication Programmer's Guide, First Edition, 1987, Chapter 2. Hewlett-Packard Company MPE V to MPE XL: Getting Started, Third Edition, 1989, Chapter 4. Hewlett-Packard Company MPE XL Commands Reference Manual, Third Edition, 1990, Chapter 2 and Appendix A. Hewlett-Packard Company MPE XL General User's Reference Manual, First Edition, 1988, Chapters 4 and 8. Hewlett-Packard Company MPE XL Intrinsics Reference Manual, Third Edition, 1990, Chapter 4. Hewlett-Packard Company Using the 900 Series HP 3000: Advanced Skills, First Edition, 1989, Modules 5 and 6. Hewlett-Packard Company Atlanta Response Center (specifically B.A.) Calls to the Atlanta HP Response Center during April, 1988. Hewlett-Packard Company Atlanta Response Center (specifically D.F. and R.L.) Calls to the Atlanta HP Response Center during May, 1991. Hewlett-Packard Company Mountain View Response Center (specifically R.R. and K.K.) Calls to the Mountain View HP Response Center during May, 1991. Hewlett-Packard Company North American Response Centers HP3000 Application Note #21: COBOLII and MPE Intrinsics, January 15, 1987. Kabay, M.E. "Making the Most of Your WELCOME Message", The HP Chronicle, March, 1988, page 54. Largent, David L. "A Beginner's Guide to UDCs and JCWs: How to Use Them to Your Benefit (Part 1)", Interact, March, 1989, page 100ff. Largent, David L. "A Beginner's Guide to UDCs and JCWs: How to Use Them to Your Benefit (Part 2)", Interact, April, 1989, page 50ff. Largent, David L. "A Beginner's Guide to UDCs and JCWs: How to Use Them to Your Benefit (Part 3)", Interact, May, 1989, page 130ff. Largent, David L. "Function Key Labelling", Interact, February, 1988, page 15. Largent, David L. "JCWs: An Introduction", Interact, April, 1991, page 36ff. Lund, Robert A. "UDCs: A Primer", Interact, April, 1987, page 71ff. Omuro, Eric "Smarter UDCs", Interact, April, 1990, page 22ff. Parker, Michael J. and Wilson, Lynn "Labelling F-keys", Interact, November, 1987, page 22ff. PROTOS Software Company PROTOS/XL Documentation, version 3.6. Shem, Thomas and Vance, Jeff "New Features of the MPE XL User Interface", Interact, November, 1988, page 44ff. Shoemaker, Victoria "UDCs: Marvelous and Misunderstood", The HP Chronicle, March, 1988, page 34. Volokh, Eugene "Burn Before Reading - HP 3000 Security and You", Thoughts and Discourses on HP 3000 Software, Third Edition, 1987, page 19ff. Volokh, Eugene "Conditional Execution - :IF, :ELSE, :ENDIF, ET. AL.", SuperGroup Association Magazine, February, 1986, page 28ff. Index $CONTROL 52, 53, 55 Account 2, 3, 15-26, 35, 36 Account Manager 15, 21, 22, 25 Account-level 15-19, 22, 24-26, 35, 36 ALTSEC 19 Anyparm 2, 6, 32, 33 Append 2, 17, 19-21 Block Mode 9 Body Section 5, 6, 8, 9, 11-13, 18 Break 4, 9, 18, 24, 27-29, 37, 41, 42, 44 Catalog 4, 18, 25 Cataloged 4, 10, 17, 19-21, 23 Cataloging 4, 17, 18, 20 CAUSEBREAK 9 CI 3, 11, 40, 59, 62, 64 CIERROR 40, 42, 51, 52, 56, 59 Command File 2-5, 10, 15, 17 Command Files 2-4, 16, 17, 37 Command Interpreter 11, 15, 18, 24, 40, 59, 61, 62, 64 Command Name 4, 6, 7 COMMAND.PUB.SYS 18-20, 23, 38 Control Character 26 Decimal 8, 42, 46, 47, 55 Default 6-13, 28, 30, 34, 60 Define 6, 14, 28 Defining 5 Delete 1, 2, 4, 17, 19-21, 31, 41, 43-45, 49 DELETEVAR 2, 41, 43, 44, 48 EOD 36, 37 Errors 4, 18, 39, 40, 49, 51, 52, 56 Escape Character 15, 26 Exclamation Point 11, 12, 54 Exclusive Violation 23, 52, 53 Execution Options Section 5, 8, 11 EXIT 59, 61, 62 FATAL 39, 42, 44, 54 File Name 3, 4, 15, 18-20, 23, 24, 25, 26, 30 FINDJCW 40, 45, 46, 50, 55, 56, 57 FNDJW 46 Function Keys 13, 32-34 GETJCW 50 Header Section 3-8, 11 Help 1, 4, 5, 9, 10, 26, 37, 39 Hierarchy 15-17, 19, 37 HPCICOMMAND 2, 10, 37 HPCIDELETEVAR 2, 43, 45, 48, 49 HPDATE 40, 41 HPDAY 40-43, 53, 54, 57, 58 HPHOUR 40, 41, 58 HPMINUTE 40, 41 HPMONTH 40, 41 HPYEAR 40, 41 Implied Run 15 JCW JCW 40, 46, 52, 55 JCW Name 39, 41, 42, 46, 48, 55, 56 Keyword 7, 8 List 3-5, 7-10, 12-14, 21, 24, 26, 27, 28, 30-32, 34, 35, 41, 49 Lockword 15, 18 LogOn 3-5, 9, 10, 16, 18, 20, 21, 22-24, 27-29, 31-33, 35, 36, 37, 38, 51, 57, 58 Maximum 6, 11, 15, 38, 39, 56, 57 Menu 10, 28, 34, 61, 62 Mnemonic 39, 42, 44, 45, 47, 49, 57, 62 NoBreak 9, 10, 28-30, 37, 57, 58, 61 NoHelp 9, 10, 21, 26, 37 NoList 8-10, 12, 28, 37, 58, 61 NoLogOn 9, 10 NoProgram 9, 10 NoRecursion 8-10, 17, 36 Octal 8, 42, 55 Parameter 2, 6-13, 19-22, 25, 30, 33, 34, 36, 45-47, 49, 53, 55, 60-62 Parameter Name 6, 7, 12, 13 Parm 2, 6, 7, 12, 24, 31 Positional 7, 8 Problems 1, 9, 18, 29, 36-38, 56 PROTOS 50, 51, 54, 59, 60, 63, 65 PURGEUSER 38 PUTJCW 39, 43, 45, 47, 48, 50, 55, 57 PUTJW 47, 48 Quotation Marks 6-8, 13, 30 Recursion 2, 8-10, 14-17, 24, 28, 30, 34, 37 Resulting Indicator 46, 48 Resume 9, 27, 37 RPG 46-48, 52, 53, 64 Security 5, 9, 10, 17, 21, 65 SETCATALOG 2, 9, 10, 17, 18, 19-23, 32, 37, 38 SETJCW 39, 41-43, 47, 50-53, 57-62 SHOWCATALOG 3, 24, 25, 32 SHOWJCW 40-42, 45, 57 Special Characters 7, 8 Status 45-47, 49, 55-57, 61 Substitute 12 Substituted 9, 24, 30 Substitution 12 System Manager 15, 18, 19, 22, 24-26 System-defined 39-42, 47, 49, 50 System-level 3, 15-24, 26, 32, 33, 35, 37, 38, 57, 59 System-reserved 39-41, 43, 47, 49, 53, 56, 57 UDC File 3-5, 14-28, 32, 34, 37, 38 UDC Name 3, 4, 10, 11, 15, 24, 26 UDC Separator Section 5, 14 Underscore 39, 49 User-defined 39-42, 44, 47, 49 USER= 25 Variable Table 39, 43, 45-50, 57 Variables 2, 6, 38, 39, 41, 43, 44, 45, 47, 49, 50, 53, 54, 57, 59, 64 VPlus 9 WARN 39, 42, 44, 51, 61, 62 Warning 37, 47, 49 Warnings 36, 49, 56