GUIDE TO WRITING A VMS UTILITY This talk will cover, working from the outside of a utility towards the internals: - The different methods of invoking a VMS utility. - DCL command line structure. - Use of the Command Definition Utility. - Internal to the application: - The Command Language Interface routines. - Defining and signalling messages. - Creating and displaying HELP libraries. - A brief discussion of callable utilities. Before implementation of a utility has begun, as part of the design phase, some of the following questions should be asked: - What functions will the utility perform? - Will the utility have a command line interface? Will it have a callable interface? For example, CDD, the Common Data Dictionary, is used almost exclusively through its callable interface, while CONVERT, which can be called, is invoke from DCL most of the time. - How much information is needed by the utility at image activation time versus how much will be gathered by the utility during processing. - Are the the capabilities that DCL can provide needed to invoke the new utility, or is a simple RUN command enough? - Will information be retrieved from the command line? If so, how? These, among other criteria, will help determine an implementation strategy for the application. ________ _ ________ INVOKING A UTILITY There are three different mechanisms for invoking a utility: - THE DCL COMMAND RUN - No installation; user must know name and location of the image. - No information can be passed to the image from the command line. - Utility must do all of its own prompting and syntax checking. - VMS utilities: AUTHORIZE, INSTALL - THE FOREIGN COMMAND FACILITY - Simple installation; process or system LOGIN.COM needs modification to couple the image and the command. (RUN for_image /QUAL /QUAL works, too.) - DCL does not automatically prompt for missing parameters or check the syntax of the command line before activating the image. But it will perform symbol substitution, allowing symbols and lexical functions to be used on the command line. - Utility can retrieve the command line (LIB$GET_FOREIGN) and use the callable DCL parser to parse the input. - VMS utility: DISKQUOTA - The Command Definition Utility - Prompts are automatically provided for missing parameters. - DCL will parse the command line for syntax errors, before activating the image. - An association is created between the command line syntax and the image. This coupling is maintaned in the DCL command tables. - Another benefit is that installation can be done with VMSINSTAL. - The vast majority of VMS utilities and commands are implemented using the Command Definition Utility. ___ _______ ____ _________ DCL COMMAND LINE ELEMENTS Before discussing how to design a command syntax for a utility, I would like to take a quick look at the structure of a DCL command line. Command line elements fall into two categories: (IMPORTANT DEFINITIONS) 1. KEYWORD - a predefined string recognized by DCL as a distinct unit. (i.e. COPY, MATCH, BLOCK, SPAWN) 2. USER SUPPLIED - a sequence of arbitrary characters provided by the user, such as file or time specifications. - COMMANDS - Usually an imperative verb (instruction). - Specifies the command to be executed. - Always first element on the line. - Optionally followed by one or more keywords which further define the operation. (TERMINAL in second example ... /RMS_FILE or /SYSTEM for ANALYZE) ___ _______ ____ _________ DCL COMMAND LINE ELEMENTS - PARAMETERS - Specifies what the command acts upon; parameters are objects. - Preceeded by blanks or tabs. - May be required to perform operation (input and output files for COPY example) or may be optional (file specifications for DIRECTORY example). - A parameter is either present or absent. In the DIRECTORY example, the parameter is present. If only the command DIRECTORY had been specified, without any file names, then the parameter would have the characteristic of being absent from the command line. - May consist of a single item or a list. Lists can be separated by commas (DIRECTORY example) or pluses (MACRO example). For most cases commas and plus signs are equivalent. Sometimes pluses act concatenation operators. - Parameters may take arguments (SET PROTECTION=O:REWD). Arguments will be described later. ___ _______ ____ _________ DCL COMMAND LINE ELEMENTS - QUALIFIERS - Qualifiers modify parameters or commands; they do NOT modify other qualifiers. - Preceeded by a slash. - May be optional or they may be present on the command line by default, in which case, the application behaves as if the qualifier appeared on the command line even if it is missing. (/HEXADECIMAL for DUMP). - Types of qualifiers: - COMMAND or GLOBAL QUALIFIERS - Modifies the entire command, no matter were the qualifier appears on the command line. (/CONCATENATE for COPY) - LOCAL QUALIFIERS - Can appear only after a parameter; effects only that parameter. - Can not be placed after the command. MACRO/LIBRARAY x,y will produce an error. - POSITIONAL QUALIFIERS - Semantics depend on the position of the qualifier. ___ _______ ____ _________ DCL COMMAND LINE ELEMENTS - ARGUMENTS - Act as modifiers or supply a value. - Preceeded by an equal sign (=) or a colon (:); the delimeters are equivalent. - Can effect parameters, qualifiers and other arguments. - Can consist of a list. Lists are enclosed in parentheses and separated by commas. - Arguments can be nested. But it is not recommended, for clarity's sake. ______ ___________ ___ _________ _ _______ ____ _______ DESIGN SUGGESTIONS FOR DESIGNING A COMMAND LINE SYNTAX - Consider DCL syntax when designing the utility's semantics The functions which the new utility is to provide should be the primary basis for the command syntax. Even so, the benefits and limitations of DCL should be considered while designing and implementing those functions. A design which facilitates a straight-forward DCL interface will in turn facilitate user interaction. Capabilities should be designed so that they can be expressed in the clearest and most useful manner, given the language structure of DCL. - Chose descriptive keywords Early in the utility's design the developer must decide which functions are to be invoked from DCL. Each function should be paired to a DCL keyword. It should not be possible to invoke a function by more than one set of keywords. For example, there should be only one way to specify to BACKUP, that you want to make an incremental backup of a particular directory. Multi-word phrases, like RMS_FILE or BY_OWNER, are valid DCL keywords. The underscore character should be used to separate the words. - Use "natural" language Try to use words that are associated with the functions provided by the utility (CONFIRM, COPY, SUBJECT). The user's learning time and anxiety level will be reduced, if the semantics of the command line can be deduced by simply looking at the syntax. Avoid computer-ese. Unless the users of your utility are other software developers, they are not going to understand, remember or feel comfortable with the command syntax, you (worked so hard to) design. Even if the users are programmers, it isn't guaranteed that they will understand YOUR terminology. - Three parts of a DCL interface: 1. Syntax: command, parameters, qualifiers and arguments. 2. Defaults: Are optional qualifiers present by default? What are the default values for arguments and parameters? 3. Semantics: what functions are invoked from DCL? ___ _______ ____ __________ DCL COMMAND LINE STRUCTURE GENERALIZED: Command Parameter=Argument Parameter/Qualifier=Argument ENGLISH GRAMMAR EQUIVALENT: Verb Object=Adjective Object/Modifier=Adjective EXAMPLE NEW UTILITY (more complesed than necessary): Clean Floor=Kitchen/Wash=(Mop:big, Water:hot) _____ ___ _______ __________ ________ USING THE COMMAND DEFINITION UTILITY Example: I want to create a new utility which will paint objects different colors, and I have an idea of what the syntax will look like. How do I describe the syntax to DCL and let DCL know about the new command? - Based on the functions provided by the new utiltiy and the structure of the DCL syntax, choose a name and syntax for the new command. - Create a file that defines the command, its qualifiers, parameters and arguments; This file is called a Command Definition File. - Using the Command Definition File as input, modify either the process or system command tables to include the new command with the DCL command SET COMMAND. - Write the code for your new utility, using the appropriate command language routines to retrieve the command line information. CLI$PRESENT and CLI$GET_VALUE being the "appropriate" routines. _____ ___ _______ __________ _______ _______ USING THE COMMAND DEFINITION UTILITY (cont) Syntax for a Command Definition File Using these statements in a Command Definition File, you can define the syntax for a utility's command line: - DEFINE VERB verb-name [verb-clause[,...]] - Defines a new command and specifies the different characteristics of the command. - The verb-name becomes the name of the command; the first four letters must be unique. - The verb-clause specifies additional information: - The name and location of image to be invoked. - What parameters can be specified, if any. - Qualifiers. - Whether certain entities, or a combination or entities, cannot appear in the command line. (i.e. you can indicate that two qualifiers are mutually exclusive or that a particular value is not valid for a certain parameter) - DEFINE TYPE type-name [type-clause[,...]] - Defines keywords that can be used as values for parameters, qualifiers or other keywords. - Builtin types (These are predefined): $ACL, $DATETIME, $DELTATIME, $FILE, $NUMBER, $QUOTED_STRING, $REST_OF_LINE - User Defined Types: Establishes the keywords that can be used as values. _____ ___ _______ __________ _______ _______ USING THE COMMAND DEFINITION UTILITY (cont) Syntax for a Command Definition File - DEFINE SYNTAX syntax-name [verb-clause[,...]] - Defines a syntax change. A syntax change replaces something that has already been defined by a DEFINE VERB, DEFINE TYPE or another DEFINE SYNTAX statement. - A syntax change allows a verb to use a different syntax depending on the parameters, qualifiers or keywords that are present on the command line. - For example, the DCL ANALYZE command uses DEFINE syntax to differentiate the legal syntax for ANALYZE/RMS_FILE, ANALYZE/SYSTEM, ANALYZE/DISK_STRUCTURE, ANALYZE/ERROR_LOG, etc. - IDENT and MODULE are used to provide identification information and a module name when an object module is created from a Command Definition File. _____ ___ _______ __________ _______ _______ USING THE COMMAND DEFINITION UTILITY (cont) An example Command Definition File Going back to the example I mentioned earlier, here is a Command Definition File for my COLOR utility: - Within verb and type clauses, there are parameter, qualifier, value, image and keyword clauses. - Image clause: defines the image to be invoked. - Parameter clause (one per parameter) specify: - Name of parameter. Parameter names must numbered consecutively from P1 through P8. "P1" is how this application must refer to the parameter when using the CLI routines to retrieve information. An alternate, more mneumonic, name can be defined by using the LABEL= statement; looks just like the PROMPT= statement. - If there parameter is present on the command line by default. - The prompt to be given if a required parameter is missing from the command line. - A value clause which indicates: - The default value for the parameter, in the absence of an explicit parameter value (i.e. PURGE). - Whether the parameter is required. - If parameter can be specified as a list. - Type of the parameter -- a pre-define type (file, acl, time, etc) or a the name of a DEFINE TYPE statement. _____ ___ _______ __________ _______ _______ USING THE COMMAND DEFINITION UTILITY (cont) An example Command Definition File - Qualifier clause (one per qualifier) specifying: - The name of the qualifier (i.e. "/red"). - If the qualifier is present on the command line by default. - Whether the qualifier is negatable is negatable or not. - Where the qualifier may appear on the command line: - Command or GLOBAL qualifiers (default) -- applies to the entire command line; may appear anywhere. - LOCAL -- can appear only after a parameter and applies only to that paramter. - POSITIONAL -- can appear anywhere on the comman line, but its meaning depends on the position it is in. - A value clause which indicates: - The default qualifier value, in absence of an explicit qualifier value being given on the command line. - Whether the qualifier value is required. - If parameter can be specified as a list. - The qualifier value's type -- a pre-define type (file, acl, time, etc) or a the name of a DEFINE TYPE statement. - Disallow clause: Disallows a command string if the results of the given expression are true. _____ ___ _______ __________ _______ _______ USING THE COMMAND DEFINITION UTILITY (cont) An example Command Definition File - Valid commands: $ COLOR /RED /BLUE SHOOTING_STAR $ COLOR /GREEN=ALL LAWN - Invalid commands: $ COLOR /RED /GREEN=HALF CIRCLE $ COLOR /BLUE /GREEN=ALL OCEAN __________ ___ ___ ___ _______ ___ ________ QUALIFIERS FOR THE DCL COMMAND SET COMMAND Now that the Command Definition File has been created, the process or system command tables can be modified, so that the new command can be used. - System command table is in SYS$LIBRARY:DCLTABLES.EXE. - By default, when logging in this command table is copied to your process. - Changes to your process command table will not effect the system wide table. - No special privileges are needed to modify your own process's command table. SYSPRV is required to modify the system command table. - /REPLACE = file_spec -- add or replace verbs in the command table. - /TABLE = file_spec -- specifies the command table to be modified. Default is the current process's command table. - /DELETE = verb -- removes a verb from the command table. - /OBJECT -- creates an object module. This object module can be linked into an image and used as a private command table for parsing strings and executing routines. - /[NO]LISTING -- controls whether a listing is produces - /[NO]OUTPUT -- controls where the modified command tables should be placed. Defaults is the process's command table. /NOOUTPUT indicates that no output should be generated. ___ _______ ________ _________ _____ _________ THE COMMAND LANGUAGE INTERFACE (CLI) ROUTINES Now that the command syntax has been defined, what has to be done inside the utility to retrieve command line information? - CLI$PRESENT (entity_desc) - Determines whether parameter, qualifier, or keyword is present on the command line. - entity_desc -- Character string descriptor for the label of the entity. - Returns separate values indicating if the entity was present, absent, locally present, negated, locally negated or defaulted on the command line. - CLI$_PRESENT, CLI$_NEGATED, CLI$_LOCPRES, CLI$_LOCNEG, CLI$_DEFAULTED, CLI$_ABSENT - CLI$GET_VALUE (entity_desc, ret_desc [,ret_length]) - Retrieves the value associated with a specified qualifier, parameter or keyword. - entity_desc -- A character string containing the label of the entity. - retdesc -- A character string containing the value retrieved by CLI$GET_VALUE. - ret_length -- The number of characters DCL returned in ret_desc. - $VERB and $LINE are predifined entities. - $VERB is used to retrieve the verb from the command line. Useful if an image contains more than one command (COPY/APPEND and PURGE/DELETE are really the same image, they use $VERB to determine which operation should be done.) - $LINE returns the whole command line with all characters converted to uppercase, defaults filled in, integers converted to decimal, etc. - Returns separate values to indicate whether the value is followed by others (i.e. it is in a list), if the value is to be concatenated, if it is absent or if it is the last or only value in a list. - CLI$_COMMA, CLI$_CONCAT, CLI$_ABSENT, SS$_NORMAL - CLI$DCL_PARSE (command_str, table [,param_rtn] [,prompt_rtn] [,prompt_str]) - Parses a command string using the command definition supplied by the specified command table. - command_str -- Descriptor for for a string containing the command line parsed. - table -- Name of module containing the command language description. This module was created by SET COMMAND/OBJECT and linked into the image. - param_rtn -- name of a routine to obtain a required parameter that was not supplied in the command string. LIB$GET_INPUT can be used or a routine that you have written, with the same calling interface as LIB$GET_INPUT. - prompt_rtn -- name of routine to call to obtain all or part of a command. (like "MAIL>") Again, LIB$GET_INPUT or a user written routine with the same calling interface. - prompt_str -- Descriptor for for a string containing a prompt, used as an argument for the prompt_rtn. - Returns: CLI$_NOCOMD, RMS$_EOF. - CLI$DISPATCH ([userarg]) - Invokes the subroutine associates with the verb most recently parsed by a CLI$DCL_PARSE routine call. - userarg -- Data passed to the action routine. There is a good example of how to use CLI$DCL_PARSE and CLI$DISPATCH in the VAX/VMS Utility Commands Reference Manual. __________ __ _________ _____ ___ _________ DEFINITION OF CONDITION CODES AND MESSAGES Creating user defined messages: - Construct messages by writing a message source file, compiling it w/ the message utility and linking the resultant object module with your utility. - The message source file contains: - Facility directive -- Specifies the facility to which the messages apply, including a facilty name, and facility number. - Severity directive -- Specifies the severity level to be associated with the messages that follow. SUCCESS, WARNING, INFORMATIONAL, ERROR, SEVERE/FATAL - Message definition -- Defines the message symbol, the message text and the number of FAO arguments that can be included in the message. - End directive -- Terminates the list of messages for the facility. - Other directives: .BASE (defines a base offset for the message values), .LITERAL (defines global symbols), .IDENT, .TITLE, .PAGE - Messages for more than one facility may defined in a single message file. _________ _________ COMPILING MESSAGES - The Message utility creates the 32-bit message code and the message ID -- consisting of the faciity prefix, the message name and severity level. - By default an object module is created with text and symbols. - In some cases, it is desirable to change the text of messages often. There is a way of doing that which does not require the utility to be relinked each time. Two object files must be created from the message source file. The first would have the message text, but no symbols. The second object file would have symbols, no text; It also would have an indirect pointer to the first object module (created with /FILE_NAME). This is very useful for applications which are targeted for several foreign countries. (April Fools day, too) - After message file has been compiled, the message object module must be linked into the utility so that the system can reference the newly defined messages. __________ ____ _______ _________ SIGNALLING USER DEFINED MESSAGES - This FORTRAN code segment demonstrates how to declare and signal user defined messages. - Use the symbol formed by the facility prefix and the condition name. - If the message text contains FAO arguments, you must specify paramters for those arguments when you signal the condition. ______ __ _ ____ _____ FORMAT OF A HELP FILE - Help libraries contain modules of help text that provide user information about a utility. A help module is the lines of help text that relate to the same topic. - Each module is numbered as key-1 through key-9. Key-1 identifies the main topic of information. - The key-1 name becomes the module name in the library. - The template shown on this slide would contain two help modules, one for key-1 and another for 2nd-key-1. - Formatting help files: - Help text can be any length. - The only restriction is that it cannot contain a number or a slash (/) in the first column. A number in the first column indicates that the line is a key. A slash indicates a qualifier line. In addition, characters such as question mark, asterisk and percent sign in key names may make retrieval of information very difficult. Therefore, it is advised to avoid special characters. - A qualifier line, which starts with a slash in the first column, is similar to a key line, except that the librarian returns a list of all the qualifier lines when you request help on key containing the qualifiers. _______ ____ _____ EXAMPLE HELP FILE 1 COLOR The COLOR utility is used to paint pictures. 2 Parameters There is only one parameter for the COLOR utility. 3 OBJECT This parameter specifies which object should be colored. 2 Command_qualifiers /RED /RED indiacates that the color red should be used. /BLUE /BLUE indicates that the color blue should be used. /GREEN [=green_amount] /GREEN indicates that the color green should be used. The optional argument, green_amount, specifies the amount of green to use. _________ ____ ___ ___ _____ PROVIDING HELP FOR THE USER - Once the help source file has been created, the LIBRARY command is used, with the /CREATE and /HELP qualifiers, to turn it into a help library. - To provide the user with help, from within the utility: LBR$OUTPUT_HELP (output_rtn [,output_width] [,line_desc] [,library_name] [,flags] [,input_routine]) - Outputs help text to a user-supplied output routine. - Output_rtn -- Name of routine the writes the help text one line at a time. You may specify LIB$PUTOUTPUT or another routine which has the same calling format. - Output_width -- The width of a text line. Default is 80. - Line_desc -- Descriptor for the help request line, a string containing one or more help keys define the requested help. - Library_name -- Descriptor for a string containing the file specification for the main library. If this is unspecified, the defautl help libraries are used. (SYS$HELP:.HLB is the default name string.) - Flags -- Specify help output options, such as which logical name table should be searched for default help libraries and whether interactive help prompting is in effect or not. - Input_rtn -- Routine used for prompting. May be specified as LIB$GET_INPUT or another routine with the same calling interface. Used only when the prompt flag is set in the FLAGS argument. ________ __________ CALLABLE UTILITIES (or Modular Programming) - Invocation, form and function are separated within the utility - Invocation -- The part of the utility that establishes the context in which it will run: the input and output files, the initialization files, the terminal type, etc. - Form -- That portion of the utility that communticates with the enviroment. "Form" is used by the invocation procedures to ask the user for parameters, report errors and present information. - An application is usually designed to run in a particular enviroment or set of enviroments. Within each enviroment assumptions are made about the devices, formats, conventions and language that must be used to interact with the user. "Form" refers to those portions of the program that are specifically designed for interaction with the enviroment. - Separation of form and function can be thought of as separating out the likely to change enviroment-dependant portions from the pure functions. - Such as making DCL command work in a graphical enviroment along with the current, hardcopy design center. - Function -- the actual tasks that a application is supposed to provide. ________ __________ CALLABLE UTILITIES (or Modular Programming) - By making utilities modularized and standardizing portions, such as calling interfaces, data types and error handling: - The functions of one utility are made available to other utilities and applications, which can lessen the duplication of programming effort. - DCL no longer is the only mechanism for invoking the utility's capabilities. A utility could be written that has no command line interface at all. - Modifying utility for use in varied enviroments is simplified. - There are issues that have to be considered: - Errors -- Is signalling the user appropriate? Should an error be returned to the caller and let it handle the problem? How long can error reporting be dealdelayed after the actual conditin occurred. - How flexible of an interface is necessary? Should any language be able to call this utility? How many data types are going to be supported? - How does callability effect documentation? _____ __ ____ ______________ WHERE TO FIND DOCUMENTATION - Command Language Interface (CLI): - Guide to Programming on VAX/VMS, Chapter 7 - VAX/VMS Utility Routines Reference Manual, Section 2 - Command Definition Utility (CDU): - VAX/VMS Command Definition Utility Reference Manual - Guide to Programming on VAX/VMS, Chapter 7 - VAX/VMS Utility Routines Reference Manual, Section 2 - SET COMMAND: - VAX/VMS Command Definition Utility Reference Manual - VAX/VMS DCL Dictionary - MESSAGE Utility: - Guide to Programming on VAX/VMS, Chapter 10 - VAX/VMS Message Utility Reference Manual - HELP Libraries: - Guide to Programming on VAX/VMS, Chapter 9 - VAX/VMS Utility Routines Reference Manual, Section 7