.PAPER SIZE 54,60 .RIGHT MARGIN 60 .NO NUMBER .TITLE RSX "@" for VMS Users # .BLANK 10 .CENTER;RSX "@" for VMS Users .BLANK 7 .CENTER;- DA020 - .BLANK 5 .CENTER;Thomas R. Wyant, III .CENTER;E. I. DuPont de Nemours .CENTER;Richmond, Virginia .BLANK 5 .CENTER;May 6, 1992 .AUTOPARAGRAPH .PAGE .CENTER;Abstract .BLANK .LEFT MARGIN +10;.RIGHT MARGIN -10 The RSX Indirect Command Processor (ICP) is in general (and with specific exceptions) equivalent in functionality to VMS DCL. However, the implementation philosophy of the two is totally different, and specific experience with VAX DCL command procedures generally does NOT transfer to RSX in the manner that VAX DCL experience transfers to RSX DCL. The purpose of this talk is to try to match RSX ICP concepts to VAX DCL concepts to give the new RSX programmer or system manager a jump start. .LEFT MARGIN -10;.RIGHT MARGIN +10 .AUTOPARAGRAPH .HL1 Introduction Any operating system worthy of the name (and a few that aren't) has a facility for "canning" system commands in a file, and executing them from the file in sequence. Generally, some sort of logic is included, and the indirect command facility of many operating systems is equivalent in functionality to a general purpose programming language. The RSX Indirect Command Processor (ICP) is no exception to the above remarks, but its implementation provides a unique "feel" versus the equivalent facility in other operating systems. Generally, indirect commands are implemented as part of the Command Line Interpreter (CLI - eg: VAX DCL, RT-11 KMON, Unix sh, csh, and so on). This frequently results in certain "batch-like" features, such as input redirection to the command procedure itself. RSX, on the other hand, implements the ICP as a separate executable which passes commands to the CLI one at a time, and (usually) waits for their completion. There is no input redirection, and no implicit status checking (the ICP predates the concept of an exit status in RSX). There is also a dichotomy between ICP directives (the symbol and logic statements, which ALWAYS start with a period) and CLI commands; they simply LOOK different. In fact, the first impressions of a VMS person looking at the RSX command processor would probably be all negative: .LIST "*" .LE;No inline data. .LE;Symbol substitution doesn't work. .LE;Arithmetic works funny. .LE;No foreign commands. .LE;No lexical functions. .END LIST Generally, the above are "paper" problems: the functionality is there, but different; sometimes more convenient, sometimes less. My personal opinion is that user interaction, debugging, and task (= sub- or detached process) synchronization are better (or at least easier) under RSX, but that system interaction and arithmetic are better under VMS. .HL1 General considerations There are several things needful to know, but which do not really fit in any of the specific topics. Because some of them are rather important, they are covered here, rather than in a "Miscellany" section at the end. .LIST "*" .LE;The default file type is _.CMD, not _.COM. DEC seems to have established the convention that _.COM is the default when the indirect command facility is embedded in the CLI, and _.CMD otherwise. .LE;The maximum line length is 132 characters. .LE;The maximum nesting depth is four, not eight. This is partially compensated for by the _.CHAIN directive, which transfers control to another command file at the same nesting level. .LE;The ICP tends to die on syntax errors, as opposed to the VMS DCL, which typically makes an assumption and trucks on. .LE;An attempt to substitute an undefined symbol is also fatal. .LE;There is no "-" operation for strings. .LE;The comment operator is ";" or ".;", not "!". The difference between the two is that comments preceded by ";" are normally displayed, but comments preceded by ".;" are normally not. .LE;Symbol substitution takes place before any other processing. One way to conditionally bypass a command is to comment it out using symbol substitution: .BLANK;.INDENT 5 'FOO'DELETE *.*;* .BLANK where FOO is "" if you want the command to execute, and ".;" if you don't. This also means that .BLANK;.INDENT 5 _.IFDF FOO 'FOO' .BLANK won't work, as the symbol substitution occurs before the ICP parses the directive. .LE;The ICP generally does not like extraneous blanks or tabs in ICP directives - except before the directive name itself. A single blank or tab should separate the directive name from its first argument, and the arguments themselves from each other. Embedded blanks in arithmetic expressions, for example, are not tolerated. .LE;Commands that do NOT represent ICP directives are displayed by default. You can cause them not to be displayed using _.ENABLE QUIET. _.DISABLE QUIET reverses this effect. The _.IFENABLED QUIET conditional is _ if _.ENABLE QUIET is in effect and _ otherwise; _.IFDISABLED QUIET is just the opposite. .LE;The left side of a relational test (".IF") MUST be a symbol. The right side may be a symbol, literal, substring, or expression of the appropriate type. .END LIST .HL1 Symbols ICP symbols are the same in spirit as VMS DCL symbols, but somewhat different in implementation. RSX ICP symbols come in three types (logical, numeric, and string), rather than VMS' two. The types of the ICP's symbols are rigidly defined; once a string symbol (for example), always a string symbol. Symbols take their type from the directive that creates them: _.SETL or _.ASK create logical symbols, _.SETN or _.ASKN create numeric symbols, and _.SETS, _.ASKS, and _.READ create string symbols. The _.ERASE directive destroys symbols, or they die a natural death when control transfers out of their scope. .HL2 Symbol Names Symbol names are limited to six alphanumerics, plus the dollar sign. Symbol names may officially begin with numeric characters, but there have been some bugs in this area. .HL2 Symbol Values Logical symbols, of course, are simply _ or _. "_" and "_", by the way, are predefined symbols that have those values. Numeric symbols take the values 0 to 65535 unless the _.ENABLE OVERFLOW directive has been issued. This directive changes the range to -32768 to 32767. Numeric symbols and expressions will be discussed at greater length under "Arithmetic". String symbols take strings from zero to 132 bytes in length. .HL2 Symbol Assignment RSX does not recognize VMS' "symbol = expression" syntax for assigning symbol values. Instead, it employs a set of directives that specify the type of symbol being created, as well as computing and assigning its value: .LIST "*" .LE;_.SETT symbol Creates a logical symbol and sets it _. .LE;_.SETF symbol Creates a logical symbol and sets it _. .LE;_.SETL symbol expression Creates a logical symbol and sets its value equal to the logical expression. The logical operators _& (and), _! (or), and _# (not) are recognized, but _& and _! have the same precedence. However, expressions in parentheses are evaluated before expressions outside parentheses. .LE;_.SETN symbol expression Creates a numeric symbol and sets its value equal to the arithmetic expression. The logical operators mentioned above are recognized, and perform bitwise operations. In addition, the normal arithmetic operators (_+, _-, _*, and _/) are recognized, though again without precedence. The section on "Arithmetic" gives more detail. .LE;_.SETS symbol expression Creates a string symbol and sets its value equal to the string expression. The only string operator is _+, which does concatenation. String literals can be quoted with either the '"' or '_#' character, which is a good thing as there is no convention for embedding the quoting character within a literal. .LE;Bit strings RSX lacks the VMS bit string operator represented by the example .BLANK;.INDENT +5 _$ ESC[0,8] = 27 .BLANK to create a symbol whose value is an escape character. However, an effect equivalent to the above (though NOT to the general case) can be had by using the %V symbol substitution operator, as follows: .BLANK;.LEFT MARGIN +5;.NOFILL _.SETN N_$JUNK 27. _.SETS ESC "'N_$JUNK%V'" .BLANK;.LEFT MARGIN -5;.FILL .END LIST .HL2 Standard Symbols On entry to any command procedure, the string symbols P1 through P9 are defined in exactly the same way that VMS defines P1 through P8. In addition, P0 represents the command file name as specified in the command (ie - it's NOT the same as F_$ENVIRONMENT ("PROCEDURE") -- more on that later). Also, COMMAN contains the entire command line; that is, it is equivalent to the concatenation of P0 through P9, separated by spaces. In addition, there is a plethora of predefined symbols enclosed in angle brackets. These will be discussed where appropriate (generally under lexical functions). .HL2 Symbol Scope Symbol scoping in the ICP is similar but not identical to VMS DCL. Both local and global symbols exist, but global symbols are not recognized unless the "_.ENABLE GLOBAL" directive has been issued. If this directive is in effect, any symbol whose name begins with a dollar sign is a global symbol. By default, the scope of local symbols is the command procedure in which they are defined. Unlike VMS DCL, they are not visible in procedures invoked by the procedure that defines them. The default scope of local symbols can be changed in two ways: .LIST "*" .LE;The _.BEGIN directive creates a local symbol block. Symbols defined outside this block are still visible. The _.END directive terminates the block. .LE;The "/LC" switch, when applied to a nested command procedure, prevents a local symbol block from being created for that command procedure. Instead, the invoked and invoking command procedures share the same local symbol block, and have access to each others' symbols. .END LIST .HL2 Symbol Substitution The ICP has symbol substitution, but the rules are slightly different from VMS: .LIST "*" .LE;You must issue the ".ENABLE SUBSTITUTION" ICP directive before symbol substitution occurs. The ICP predates symbol substitution, and the RSX group has never, to my knowledge, changed the default behavior of any RSX component. Typically, 99_% plus of all RSX _.CMD files begin with ".ENABLE SUBSTITUTION" .LE;There is no "_&" substitution operator. .LE;The VMS "Foreign Command" facility (implicit substitution on the first token on the line) is not implemented. This is NOT to say custom commands are unavailable; more on this under "Foreign Commands". .LE;The symbol name MUST be enclosed in "'" characters; the VMS practice of making (in most cases) the trailing "'" optional is not supported. .LE;The rules for symbol substitution DO NOT CHANGE inside string literals; it is not necessary to double up the "'" characters. Instead, "''" inserts a literal "'" in the string. Note, however, that "''" is interpreted as a double "'" only in a context where a leading "'" is expected. The string "'P1''P2'" is interpreted as equivalent to the VMS DCL string "''P1'''P2'" .END LIST .HL1 Arithmetic Arithmetic in the RSX ICP is done to 16 bit (integer) precision. By default, it is unsigned, though signed arithmetic can be had by use of the "_.ENABLE OVERFLOW" directive. Numeric constants are octal by default, though you can specify a decimal number by appending a decimal point. You can make the default radix decimal (with no way of specifying octal numbers) by using the "_.ENABLE DECIMAL" directive. Numeric symbols have a default display radix associated with them. This display radix is inherited from the expression that was used to compute the value of the symbol: decimal if ANY decimal constant or symbol appears in the expression, and octal otherwise. You can also use the "_.SETO" or "_.SETD" directives to explicitly set the display radix of the symbol, and you can override the default by substitution control, which will be discussed under the lexical function F_$FAO. There are six binary operators recognized: + (addition), - (subtraction), * (multiplication), / (division), _& (bitwise and), and ! (bitwise or). In addition, there are two unary operators, - (unary minus), and _# (bitwise not). If you intend to do arithmetic with the ICP, you need to be aware that the ICP does NOT obey the (almost) universal rules for the precedence of operators; instead, all operators have the same precedence. The expression 3.+4.*5., for example, evaluates to 35., not 23. as you would expect. You can, however, group operations with parentheses: 3.+(4.*5.) in fact evaluates to 23., as does 4.*5.+3. .HL1 Logic The ICP directive corresponding most nearly to the VMS "IF" is the _.IF directive. The general syntax is .BLANK;.INDENT 5 _.IF symbol relation expression command .BLANK where the command is issued only if the value of the symbol on the left has the specified relation to the expression on the right. NOTE THAT ONLY A SYMBOL IS ACCEPTABLE ON THE LEFT SIDE OF THE RELATION (no literals or expressions!), and that the expression must be the same type as the symbol. The following relations are recognized: .BLANK;.LEFT MARGIN +5;.NOFILL Relation Satisfied if symbol is -------- ---------------------- _= or EQ Equal to expression _<_> or NE Not equal to expression _> or GT Greater than expression _< or LT Less than expression _>_= or GT Equal to or greater than _<_= or LT Less than or equal to .BLANK;.LEFT MARGIN -5;.FILL Note the absence of dots around the alphabetic forms of the relationals; given that the left side is a single symbol, spaces are sufficient punctuation. Also, there is no distinction between string and numeric relations; the type of the symbol makes this unambiguous. In addition to the "plain vanilla _.IF", there are special-purpose directives: .BLANK;.LEFT MARGIN +5;.NOFILL Test True if: -------------- ---------------------- _.IFT symbol Logical symbol true. _.IFF symbol Logical symbol false. _.IFDF symbol Symbol defined. _.IFNDF symbol Symbol not defined. _.IFLOA driver Driver loaded. _.IFNLOA driver Driver not loaded. _.IFINS task Task is installed. _.IFNINS task Task is not installed. _.IFACT task Task is active. _.IFNACT task Task is not active. .LEFT MARGIN -5;.FILL Any two or more of the _.IF directives can be connected with _.AND or _.OR directives, which function as the expected logical connectives. One inobvious thing about these connectives is the need to specify _.IF again after _.AND or _.OR; this convention allows _.AND and _.OR to be used in conjunction with the special purpose _.IF directives; for example, .BLANK;.INDENT 5 _.IFINS FOO _.OR _.IFINS BAR .BLANK Parentheses can be used to group conditionals on the right side of an _.AND or _.OR: .BLANK;.INDENT 5 _.IFINS FOO _.AND (_.IFINS BAR _.OR _.IFINS BAT) .HL1 Inline Data Inline data is one of those things that is simply not supported under RSX. However, almost all RSX utilities (including COPY, LINK, FORTRAN, and so on) can be instructed to read their input from a file rather than the terminal. The syntax for this is (not surprisingly) "@filename", with "_.CMD" being the default file type. Files fed to utilities in this way are NOT processed by the ICP. The net effect resembles feeding an option file to the linker. Unfortunately, the GCML_$ facility which supports this behavior does not have a supported interface to high-level languages. .HL1 Subroutines. The ICP has a _.GOSUB directive, which is about midway in functionality between the VMS GOSUB and CALL verbs. It is a VMS GOSUB as far as symbol scope is concerned; the subroutine and the caller are in the same local symbol block (though you can create your own local symbol block using the _.BEGIN and _.END directives). But unlike the VMS GOSUB, it takes command arguments; anything on the command line after the name of the called routine is passed in reserved symbol COMMAN. You return from a subroutine using the _.RETURN directive. One thing to be cautious about is the fact that, unlike a VMS subroutine, if control flow reaches an RSX subroutine by "fall through", the subroutine WILL be executed. You will get an error when the ICP attempts to execute the _.RETURN. .HL1 File I/O Corresponding to the OPEN, READ, WRITE, and CLOSE verbs in VMS are the _.OPEN, _.READ, _.DATA, and _.CLOSE directives. The ICP is limited (rather severely) to only four files open simultaneously. In addition, it can only read and write sequential files. The functionality corresponding to the VMS "READ/PROMPT/TIMEOUT" exists, but does NOT reside in these directives, and discussion of it is deferred to the section on user I/O. All ICP file I/O directives have generally the same syntax; the directive name, an optional channel number (preceded by a pound sign, and in the range 0 to 3), and directive-specific data if any. The channel number is a numeric literal (eg: #3) or a SUBSTITUTED symbol (eg: #'FOO'). Any non-fatal error causes the FCS error code to be returned in _. The specifics are: .LIST "*" .LE;_.OPEN [_#n] filename Opens a file for output. It is a sequential file with variable length records and "List" carriage control. The square brackets are NOT part of the syntax; they merely denote an optional syntax element. .LE;_.OPENA [_#n] filename Opens an existing sequential file for appending. .LE;_.OPENR [_#n] filename Opens an existing sequential file for input. .LE;_.DATA [_#n] stuff ... Writes the stuff to the designated open file. The "stuff" is not quoted in any way. A SINGLE space or tab precedes "stuff"; if more than one is there, the subsequent ones are taken as part of the data. .LE;_.ENABLE DATA [_#n] Causes the contents of the command procedure to be copied to the output file until a "_.DISABLE DATA" directive is encountered. In at least some incarnations of the ICP, the _.DISABLE DATA must start in column 1. Symbol substitution DOES take place while you _.ENABLE DATA. If you are using the _.ENABLE DATA block to build another command procedure, be aware that labels in the _.ENABLE DATA block WILL be recognized while executing a GOTO. .LE;_.READ [_#n] symbol Causes the next record in the file to be read into the symbol. If end of file is encountered, the symbol _ (the enclosing angle brackets ARE part of the symbol name) will be set to _. .LE;_.CLOSE [_#n] Closes the open file. .END LIST .HL1 User Interaction The ICP directives corresponding most nearly to INQUIRE (or READ/PROMPT) are the _.ASK directives. These come in three flavors, one for each type of symbol, and provide a considerable amount of validation, with hooks for you to easily do more. The general syntax is .BLANK;.INDENT +5 _.ASKx [low:high:default:timeout] symbol prompt .BLANK with the "x" being nothing at all for a logical query, "N" for a numeric, and "S" for a string. The prompt is not enclosed in quotes. The stuff in square brackets is optional, but if supplied the square brackets are part of the syntax. The meanings of the optional items are: .LIST "*" .LE;low:high These items are not valid for the _.ASK (logical) form of the directive; the colons that delimit them are also omitted in this case. For _.ASKN, they represent the lowest and highest valid inputs, and they must both be specified or both omitted; the ICP will issue a warning and repeat the prompt if the input is out of range. For _.ASKS, they represent the minimum and maximum length of the input string. .LE;default This is the value returned if a carriage return is entered. It must be of the same type as the directive (_ and _ are handy here in _.ASK). If not specified, the default is _ for _.ASK, zero for _.ASKN, and "" for _.ASKS. If the user in fact takes the default, the special symbol _ is set _; otherwise it is set _. .LE;timeout The timeout is specified as an integer followed by "S" (for seconds), "M" (for minutes), or "H" (for hours). If a timeout occurs, the special symbol _ is _, but in general you should NOT assume that the default value has been returned. You cannot specify more than 32767 seconds, 1440 minutes, or 24 hours. .END LIST Any validation parameters specifies will appear in the prompt. .HL2 More on Validation In addition to the validation provided by the _.ASKx directive itself, there is supplemental information made available after the _.ASKS directive in various special symbols: .LIST "*" .LE;_ contains the length of the string. .LE;_ is _ if the string contains only RAD50 characters. .LE;_ is _ if the string contains only alphanumeric characters. .LE;_ is _ if the string contains only numeric characters. .LE;_ is _ if the string contains only octal characters. .END LIST .HL2 Captive Command Procedures The normal action of a _.ASKx directive on encountering end-of-file (control/z) is to terminate the ICP on the spot. However, if you _.DISABLE CONTROL-Z, the control/z character causes the _.ASKx directive to be satisfied, and special symbol _ is _. If, in addition, you issue the MCR command SET /SLAVE=TI: (or the equivalent DCL SET TERMINAL/SLAVE), there will be no way to exit the command procedure (barring errors) except under your control. The SET /SLAVE command has no exact equivalent in VMS, but in the present case has the effect of SET NOCONTROL_=Y. You can have the equivalent of a captive account if you specify that the account itself be logged in slaved, and you _.DISABLE CONTROL-Z in the account's LOGIN.CMD before issuing any _.ASKx directives. .HL2 The Great Escape Under RSX, the escape character normally acts as a terminator. However, you can if you choose field it in a couple of ways. If you _.ENABLE ESCAPE, then special symbol _ is _ if the user responds to the query with an escape character. This trick is used extensively in SYSGEN. In addition, entire escape sequences can be fielded if you _.ENABLE ESCSEQ and issue the MCR command SET /ESCSEQ=TI:. For this to work smoothly, you will probably also need to _.ENABLE ATTACH and _.DISABLE DETACH .HL1 Foreign Commands Although RSX does not support anything like the VMS foreign command facility (much less anything like "SET COMMAND"), it is possible to define your own commands. The ease or difficulty of this depends on which CLI you are using, as follows: .LIST "*" .LE;MCR Foreign commands under MCR are a piece of cake. Just install your task with name "...xxx" (where the x's are a three character name of your choosing), and MCR will recognize it as a command. You get the command text using GETMCR (the RSX facility corresponding to LIB_$GET__FOREIGN). GETMCR works regardless of which CLI you're using. A foreign command created in this way is system-wide. If you are running under RSX-11M+ you can create a command valid only on terminal tTnn by installing your task as xxxtnn. The "t" is the first character of your terminal's device name (either "T", "R", "H", or "V"), and the "nn" is its unit number (octal). For unit numbers above 77, use the letters of the alphabet in order for the first "n"; for example, FOOTB6 for command "FOO" on terminal TT116:. Be aware that the system will NOT clean up tasks installed in this way when you log out. .LE;DCL Adding commands to DCL requires modifying DCL's command table. This is charitably considered a pain in the neck. However, DCL can be configured (and is configured by default under modern M+ systems) to pass any command it doesn't recognize to MCR, reducing the problem to the previous case. .LE;CCL CCL is a user-written CLI available from DECUS. It is a file-driven command parser, able to supply defaults, prompt, and generally handle a wide variety of command parsing tasks. Unlike MCR and DCL, CCL supports command definition on a per-user basis as well as system-wide. .END LIST As an aside, all user-written CLIs under RSX except (of course) MCR simply take their input, reformat it into a MCR command, and let MCR do the dirty work. This does involve several task activations before you're done, but an RSX task activation is not the big deal a VMS image activation is; you should be able to get an installed task under way in under 100 milliseconds. .HL1 Debugging The RSX equivalent of SET VERIFY is to apply the /TR qualifier to the command that invokes the command procedure. Within the command procedure, you can _.ENABLE TRACE and _.DISABLE TRACE to turn verification on and off. The directive _.IFENABLED TRACE will tell you whether verification is currently on or off. In addition, the RSX ICP has a feature which causes CLI commands not to be execute. The effect is more or less as though VMS could be made to ignore all commands that execute images (such as DELETE ...), while executing commands that don't (such as GOTO, IF, ...). This is a boon to those who want to be sure what commands their procedure issues before turning it loose on their systems. In order to run a command procedure without issuing CLI commands, invoke it with the /-CLI (or /-MCR) qualifier. In order to enable or disable the issuing of CLI commands from within a command procedure, use the _.ENABLE CLI or _.DISABLE CLI directive. RSX lacks a SHOW SYMBOL command. This is no hardship in the case of single symbols, as the command .INDENT 5 _; FOO = 'FOO' .BREAK has the same effect as the VMS DCL command SHOW SYMBOL FOO. However, this technique is useless if you wanted to SHOW SYMBOL/ALL. Instead, the command .INDENT 5 @LB:[1,2]INDSYS/LB:INDDMP/LC .BREAK will do the trick. .HL1 Synchronization and Status When the ICP runs a task, it usually but not always waits for it to complete before continuing. The rules for whether or not a wait occurs are: .LIST "*" .LE;CLI commands are synchronous. That is, the ICP will wait for it to exit (or emit status) before continuing. .LE;The RUN command is synchronous provided the task being run is NOT installed. .LE;The RUN command is asynchronous if the task being run is installed; RSX treats this case more or less like the VMS RUN/DETACH command. .END LIST In addition, any synchronous command can be made asynchronous by using the _.XQT directive, which corresponds in effect (though not in mechanism!) to SPAWN/NOWAIT. Unlike VMS, RSX also provides the ability to resynchronize with asynchronous tasks. The _.WAIT directive waits for an task in the system to complete. Upon completion of this task, numeric symbol _ contains the exit status of the task, or 17 (octal) if the status was not available. Status would not be available if the task was not active when you issued the _.WAIT, unless you ran the task with a _.XQT; in this case, the ICP can buffer a limited number of completion statuses for you. Timed delays (corresponding to VMS DCL WAIT) can be had with the _.DELAY directive. The time is specified as an integer in the range 1-32767, followed by one of the letters "T" (Ticks), "S" (Seconds), "M" (Minutes), or "H" (Hours). The interval specified may not exceed 24 hours. .HL1 Error Control The RSX ICP is normally insensitive to statuses returned by executables. If you care what's going on here, you'll need to manually check the exit status, which becomes available in numeric symbol _ upon task exit for synchronous operation, or the completion of the _.WAIT directive otherwise. Unlike VMS, RSX exit statuses are almost completely ad-hoc. The only order imposed is as follows: .LIST "*" .LE;The low 4 bits are BY CONVENTION the severity code. .LE;If the application exits normally without specifying an exit status, 1 (_) is returned. .LE;If the application dies horribly, 4 (_) is returned. .END LIST On the other hand, trapping of internal error is somewhat similar to VMS. You specify .BLANK;.INDENT 5 _.ONERR label .BLANK to get the ICP to transfer control to the label of your choice for error handling. Unfortunately, the only indication of what error you encountered is an error class number, returned in _; since there are only two classes, you're pretty much on your own. What class each error belongs to is covererd in the ICP manual. Be aware that by default only class 1 errors are trapped by the _.ONERR directive; class 2 errors abort the ICP anyway. You can modify this behaviour by setting bits in _ corresponding to the error classes you want; .BLANK;.INDENT 5 _.SETN _ 3 .BLANK will cause both class 1 and class 2 errors to be trapped. Class 2 errors are generally more severe than class 1 errors, and the manual contains some dire words about continuing from a class 2 error. Experience has shown, however, that things aren't necessarily as bad as they are presented. One can generally continue from class 2 errors, provided one does not rely on any particular behaviour from the operation that caused the error. .HL1 Equivalents of Lexicals RSX does not have any feature corresponding to VAX DCL lexical functions. In general, things that are implemented as lexicals under VMS are either special symbols or directives under the ICP. This section is basically a conversion table, listing VMS lexicals and their nearest RSX equivalents. Lexicals whose function depends on an "item" argument will in general NOT be covered exhaustively; silence on a particular item will usually mean that RSX won't do the function, as RSX functionality is generally not as rich as VMS functionality in this area. .HL2 F_$CONTEXT RSX has neither processes, process IDs, nor contexts in which to search them. .HL2 F_$CSID This is irrelevant, as clustering in the DEC sense is not supported under RSX. .HL2 F_$CVSI, F_$CVUI The ICP is capable of extracting the first byte of a string symbol and converting it to numeric by using %V substitution control. For example, after .BLANK;.LEFT MARGIN +5;.NOFILL _.SETS FOO "BAR" _.SETN ASCI 'FOO%V' .BLANK;.LEFT MARGIN -5;.FILL symbol ASCI has value 66. .HL2 F_$CVTIME RSX has no such "built-in" capacity. It has the capability to perform all the functions of this lexical procedurally, provided the user is sufficiently determined. For instance, a date (passed in COMMAN) can be converted to relative format by the following code fragment, which is called by a _.GOSUB: .BLANK;.LEFT MARGIN +5;.NOFILL ####_.GOSUB CVTCMP '_' ####_; '_' ####_.EXIT _.CVTCMP: ####_.PARSE COMMAN "-" S$D S$M S$Y ####_.TEST "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" S$M ####_.SETN N$M (+2)/3 ####_.SETN N$Y 'S$Y'_. ####_.SETN N$D 'S$D'_. ####_.SETS "'N$Y%DR2Z'-'N$M%DR2Z'-'N$D%DR2Z'" ####_.RETURN .LEFT MARGIN -5;.FILL .HL2 F_$DEVICE RSX has, unfortunately, no corresponding functionality. One can "make do" by iterating over a list of device names and issuing a _.TESTDEVICE for each unit that exists: .BLANK;.LEFT MARGIN +5;.NOFILL ####_.SETS S_$DL "DR,DU,DP,DL,DK" _.DEVLP: ####_.IF S_$DL = "" .GOTO DEVND ####_.PARSE S_$DL "," S_$DN S_$DL ####_.SETN N_$DU 0 _.UNTLP: ####_.TESTDEVICE 'S_$DN''N_$DU': ####_.IF _ = "NSD," .GOTO DEVLP ####_ ####_.INC N_$DU ####_.GOTO UNTLP _.DEVND: .LEFT MARGIN -5;.FILL;.BLANK Note that the above code can be fooled by logical names that look like device names. To be on the safe side, look at the physical device name you get from _ to be sure it's what you expected. .HL2 F_$DIRECTORY This lexical corresponds pretty exactly to the special symbol _. However, this symbol is set to "[]" when you are in NONAMED mode; you'll need to check for this case and use the value of _ instead. There is an example under F_$ENVIRONMENT ("DEFAULT"). .HL2 F_$EDIT This is one of those "item"-dependent lexicals mentioned above. What follows is a list of items the ICP handles, followed by the RSX command equivalent to FOO = F_$EDIT (BAR, item): .NOFILL .LIST "*" .LE;"COMPRESS" _.SETS BAR "'FOO%C'" .LE;"UNCOMMENT" _.PARSE FOO "!" BAR JUNK .LE;"UPCASE" _.DISABLE LOWERCASE _.SETS BAR "'FOO'" _.ENABLE LOWERCASE .END LIST;.FILL .HL2 F_$ELEMENT After the ICP directive .BLANK;.INDENT 5 _.PARSE FOO SEP E0 E1 E2 E3 ... .BLANK the string symbols E0, E1, ... will contain elements 0, 1, _... as they would be returned by F_$ELEMENT (0, SEP, FOO) _..., with the following differences: .LIST "*" .LE;SEP can be more than one character; in this case, E0 will contain everything up to the first character in SEP, E1 everything from there to the second character in SEP, and so on. The last character in SEP will be reused as often as necessary. .LE;If there are not as many elements in FOO as anticipated, the remaining E's will be null strings, not SEP. .LE;If there are more elements in FOO than anticipated, the last symbol in the _.PARSE will contain the entire remaining portion of FOO. .END LIST .HL2 F_$_ENVIRONMENT This is another of those "item"-dependent lexicals. Again, a list of items the ICP handles is given, followed by the RSX construct equivalent to FOO = F_$ENVIRONMENT (item): .LIST "*" .LE;"CAPTIVE" RSX does not have captive accounts as such; however, you can find out whether you are running on a slaved terminal as follows: .BLANK;.NOFILL _.TESTDEVICE TI: _.PARSE _ "," JUNK JUNK S_$UCW2 JUNK _.SETN N_$UCW2 'S_$UCW2' _.SETN N_$ZERO 0 _.IF N_$ZERO _= 'S_$UCW2'_&200 _. .FILL .LE;"DEFAULT" .NOFILL _.TRANSLATE SY: _.SETS FOO _ _.IF _ _<_> "[]" .SETS FOO FOO+_ _.IF _ _= "[]" .SETS FOO FOO+_ .FILL .LE;"PROCEDURE" _.SETS FOO _, provided this is done before any other file manipulation directives (such as _.TESTFILE or _.OPEN) are issued. .LE;"VERIFY__IMAGE", "VERIFY__PROCEDURE" VERIFY__IMAGE has no real equivalent in RSX, since it does not do inline data. VERIFY__PROCEDURE equates to the following pair of RSX ICP directives: _.IFENABLED QUIET evaluates _ if commands that run tasks are not displayed, and _ of not. The RSX ICP has QUIET disabled by default. _.IFENABLED TRACE evaluates _ if commands that do not run tasks are displayed, and _ if not. The RSX ICP has TRACE disabled by default. Both the above tests have corresponding _.IFDISABLED tests, which evaluate oppositely. .END LIST .HL2 F_$EXTRACT The exact equivalent of F_$EXTRACT (s, n, FOO) is FOO[s:s+n-1] -- or at least it would be if RSX tolerated expressions in the substring specification. As it is, only constants or symbols work. The frequently-encountered case .BLANK;.INDENT 5 BAT = F_$EXTRACT (0, F_$LOCATE (BAR, FOO), FOO) .BLANK is better handled by .BLANK;.INDENT 5 _.PARSE FOO BAR BAT .BLANK provided BAR is a single character. For the general case, you are forced to .BLANK;.LEFT MARGIN +5;.NOFILL _.TEST FOO BAR _.SETS BAT FOO[1:_] .LEFT MARGIN -5;.FILL .HL2 F_$FAO The RSX feature corresponding to the SYS_$FAO service is the _$EDMSG subroutine. The ICP does not provide an interface to this routine, but it does provide some of the same functionality. Byte, longword, and hexadecimal operations are not supported, but most of the rest can be obtained by using substitution control. Substitution control has already been encountered; it is specified by following the variable being substituted with a percent sign and the substitution control characters desired. These are: .LIST "*" .LE;C Blank compression (covered under F_$EDIT). .LE;D Decimal (numerics only). .LE;Ln Left justify in an "n" byte field. .LE;O Octal (numerics only). .LE;Rn Right justify in an "n" byte field. .LE;S Signed value (numerics only). .LE;V Convert first byte of string to numeric, or low byte of number to character. See F_$CVSI and "Bit strings" (under "Symbol Assignment") for more details. .LE;X Convert number to RAD-50 string. .LE;Z Zero-fill the field. .END LIST .HL2 F_$FILE__ATTR The RSX functionality in this area is pretty rudamentary. If the information you want is available at all, you may have to dig it out. Specifically, the _.TESTFILE directive returns a number of special symbols. These include .LIST "*" .LE;_ will be 1 if the file exists. .LE;_ contains the fully-qualified file specification. .END LIST In addition, certain information is returned to you in _ when you open a file. This information corresponds to the first seven words of the FCS File Descriptor Block, documented in the back of the "Guide to I/O Operations". You'll need to parse _, then (possibly) extract the information you want with bitwise operations. _ contains (in order, and separated by commas): .LIST "*" .LE;Record type. The values represent: .BLANK;.LEFT MARGIN +5;.NOFILL Value Meaning if set. ----- -------------------------------- 1 Fixed-length records. 2 Variable-length records. 3 Variable woth fixed control. .BLANK;.LEFT MARGIN -5;.FILL .LE;Record attribute. The individual bits represent: .BLANK;.LEFT MARGIN +5;.NOFILL Mask Meaning if set. ------ -------------------------------- 000001 FORTRAN carriage control. 000002 List carriage control. 000004 Print (_=COBOL) carraige control. 000010 Records don't span blocks. .BLANK;.LEFT MARGIN -5;.FILL .LE;Record size (decimal). .LE;Highest virtual block number (decimal longword). .LE;End-of-file block number (decimal longword). .LE;First free byte in the end-of-file block (octal word). .LE;Record access control. The individual bits represent: .BLANK;.LEFT MARGIN +5;.NOFILL Mask Meaning if set. ------ -------------------------------- 000001 Open in read/write mode. 000002 Open in random access mode. 000004 Open in locate mode. 000010 Sequential put doesn't truncate. .BLANK;.LEFT MARGIN -5;.FILL These will probably all be zero, and at any event do not represent actual file attributes, but rather the way the ICP opens the file. .LE;Device attributes (octal). This is just the device-independent word returned by _.TESTDEVICE. See below under F_$GETDVI for the meanings of the individual bits. .END LIST You can not determine whether a file is installed as a task or resident library or common without writing some pretty serious (kernel-mode!) code. Discovering whether a task is installed, on the other hand, is pretty simple; _.IFINS task is true if the named task is installed, and false if not; _.IFNINS is just the opposite. Checking for a resident library or common can be done with the _.TESTPARTITION directive, which returns its information in _. .HL2 F_$GETDVI The functionality here is slightly better than for file attributes, but not much. The implementation is similar: issue the _.TESTDEVICE directive, and parse _. This variable contains "NSD," if the device does not exist, or "name,ucb1,ucb2,ucb3,ucb4,flags..." if it does. "Name" is the physical device name. UCB1 through UCB4 are the device attributes returned by GETLUN, and you extract the information in the same way: UCB1 is device-independent characteristics (eg: "Mass storage", "sequential", ...), UCB4 contains the buffer size, and UCB2 and 3 are device-dependent. The flags are a comma-separated list of three-character mnemonics indicating such things as whether and how the device is mounted. The contents of the four UCB words are documented various places. The contents of the first word are documented in the I/O drivers manual for each driver, and in the crash dump analyzer manual, which also has the second (device-specific) word for the TT: driver. But the only guaranteed way to get the meaning of the contents of the second and third words is to read the driver involved. For disks, the low byte of the second word plus both bytes of the third is the device size in blocks. The device-independent bits in word one are: .BLANK;.LEFT MARGIN +5;.NOFILL Symbol Mask Meaning if set. ------ ------ -------------------------------- DV.REC 000001 Record oriented device DV.CCL 000002 Carriage control device DV.TTY 000004 Terminal device DV.DIR 000010 File structured device DV.SDI 000020 Single directory device DV.SQD 000040 Sequential device DV.MSD 000100 Mass storage device DV.UMD 000200 User mode diagnostics supported DV.EXT 000400 Device on extended address ctrlr DV.SWL 001000 Device is software write locked DV.ISP 002000 Input spooled device DV.OSP 004000 Output spooled device DV.PSE 010000 Pseudodevice DV.COM 020000 Mountable as comm channel DV.F11 040000 Mountable as Files-11 device. DV.MNT 100000 Mountable .BLANK;.LEFT MARGIN -5;.FILL For the TT: and related drivers, the bits in word 2 are: .BLANK;.LEFT MARGIN +5;.NOFILL Symbol Mask Meaning if set. ------ ------ -------------------------------- U2.LWC 000001 Convert input to uppercase. U2.VT5 000002 VT05 terminal. U2.L3S 000004 LA30S terminal. U2.PRV 000010 Privileged. U2.AT. 000020 Command procedure is active. U2.HLD 000040 Hold screen. U2.DZ1 000100 Terminal is on DZ-11. U2.SLV 000200 Slaved. U2.LOG 000400 Not logged on. U2.ESC 001000 Escape sequences recognized. U2.CRT 002000 CRT device. U2.NEC 004000 Do not echo solicited input. U2.HFF 010000 Handles hardware form feeds. U2.RMT 020000 Terminal is remote. U2.DJ1 040000 Terminal is on DJ-11 U2.DH1 100000 Terminal is on multiplexer .BLANK;.LEFT MARGIN -5;.FILL The symbols in the first column are the symbolic names of the bit masks as defined in the UCBDF_$ macro. The flags are three letter device status indications, separated by commas. they fall into a number of groups, reporting different characteristics of the device. One flag from each group will be returned: .LIST "*" .LE;Driver status: .LIST " " .LE;LOD, driver is loaded. .LE;UNL, driver is not loaded. .END LIST .LE;Device status: .LIST " " .LE;ONL, device is online. .LE;OFL, device is offline. .END LIST .LE;Mount status: .LIST " " .LE;MTD, device is mounted. .LE;NMT, device is not mounted. .END LIST .LE;Mount type: .LIST " " .LE;FOR, device is mounted foreign. .LE;NFO, device is not mounted foreign. .END LIST .LE;"Publicity": .LIST " " .LE;PUB, device is set public. .LE;NPU, device is not set public. .END LIST .LE;Allocation: .LIST " " .LE;NAL, not allocated. .LE;ALU, allocated to this terminal. .LE;ALO, allocated to another terminal. .END LIST Be warned that some versions of the ICP get confused whether to return ALO or ALU. .LE;Attachment: .LIST " " .LE;NAT, not attached. .LE;ATU, attached by this copy of the ICP. .LE;ATT, attached by another task. .END LIST .END LIST .HL2 F_$GETJPI RSX functionality here is non-existent, for the simple reason that jobs and processes don't exist. .HL2 F_$GETQUI Though RSX in fact has queues, the functionality here is pretty much non-existent, also. .HL2 F_$GETSYI This functionality is also pretty much non-existent, since RSX does not have anything corresponding to a VMS "SYSGEN". The major exception is special symbol _, which returns the DECnet node name if DECnet has been running, or the system name specified at the SYSGEN if not. There is also a string symbol _ which encodes the availability of certain RSX sysgen options. It is recommended that you use INDSYS module INDSFN to test these options; it is invoked using: .BLANK;.INDENT 5 _@LB:[1,2]INDSYS/LB:INDSFN opt .BLANK and returns "_" or "_" in _, depending on whether the specified sysgen option was chosen. The option codes include: .LIST "*" .LE;EXT - 22 bit memory support. .LE;MUO - Multiuser protection. .LE;EXV - 20K Executive. .LE;DRV - Loadable driver support. .LE;OFF - Parent/Offspring support. .LE;DAS - Kernel mode data space support. .LE;LIB - Supervisor mode library support. .LE;MP -- Multiprocessor support. .LE;WND - Secondary pool window blocks. .LE;EIS - Extended instruction set support. .LE;XHR - External header support. .LE;11S - RSX-11S system. .LE;CLI - Alternate CLI support. .LE;SHF - Shuffler support. .LE;LOG - Error logging support. .LE;DSP - Executive level dispatching. .END LIST Actually, there are a bunch more than this, but I have been unable to run all of them to earth. Beware of the fact that INDSFN dies horribly if you give it an option it does not know about. .HL2 F_$IDENTIFIER Not having identifiers in the first place, RSX dispenses with this lexical. .HL2 F_$INTEGER The VMS expression FOO _= F_$INTEGER (BAR) is equivalent to the RSX .BLANK;.INDENT 5 _.SETN FOO 'BAR' .BLANK provided BAR is a string symbol containing a valid numeric literal or expression. Remember that RSX errors out rather than just terminating processing of the line if an illegal character is encountered. You can trap illegal characters beforehand by .BLANK;.INDENT 5 _.TEST BAR .BLANK and checking _ (or _) to see if the string contains only numeric (or only octal) characters. Alternatively, you can use the ICP's error trapping. .HL2 F_$LENGTH The ICP equivalent to BAR = F_$LENGTH (FOO) is .BLANK;.LEFT MARGIN +5;.NOFILL _.TEST FOO _.SETN BAR _ .LEFT MARGIN -5;.FILL The _ symbol is implicitly set by the _.ASKS and _.READ directives. .HL2 F_$LOCATE The ICP equivalent to BAT = F_$LOCATE (BAR, FOO) is .BLANK;.LEFT MARGIN +5;.NOFILL _.TEST FOO BAR _.SETN BAT _ .LEFT MARGIN -5;.FILL .HL2 F_$MESSAGE Lacking a message facility, RSX also lacks this lexical. .HL2 F_$MODE RSX does not distinguish as VMS does between process modes. You can infer similar (but NOT equivalent) information from the device name of your TI: device, as follows: .LIST "*" .LE;TTnn: Direct-connect (possibly with modem) or LAT; such a user would probably be interactive, but see the discussion under CO0:. .LE;HTnn: RMT session, using the RSX native DECnet terminal protocol. Probably interactive. .LE;RTnn: SET HOST session, using the CTERM protocol. Probably interactive. .LE;VTnn: Virtual terminal session. Probably batch, but the RSX VT: driver corresponds more nearly to the VMS pseudoterminal driver, and can be used in the same ways. For example, a logging task similar to the one that came out on the VMS tape for Fall 1990 was distributed with RSX-11M+ V1.0. A command procedure being run by such a logging task would also be active on VTnn:. .LE;CO0: Tasks run via DECnet or out of the clock queue. There is no good way do distinguish between the two cases; use whatever heuristic is appropriate to your environment. In addition, _.TESTDEVICE will return CO0: as the equivalent of TI: only of the console logger is running; otherwise, CO: is redirected to a real terminal (normally TT0:), and _.TESTDEVICE will report the name of that terminal. .END LIST .HL2 F_$PARSE Not implemented under RSX, though the PRMS_$ service under M+ gives a basis for it. There is a module in INDSYS that will at least take a filespec and pull it apart into its components. If you .BLANK;.INDENT 5 _@LB:[1,2]INDSYS/LB:INDPRF filspc .BLANK _ will come back containing .BLANK;.INDENT 5 node_\dev_\direct_\name_\type_\version_\quals .BLANK with missing fields null. Unlike VMS, punctuation is NOT included in the output. .HL2 F_$PID RSX has neither processes nor process IDs. .HL2 F_$PRIVILEGE Privilege under RSX is attached to your terminal device. The privilege bit can be extracted from the second word of your unit control block by: .BLANK;.LEFT MARGIN +5;.NOFILL _.TESTDEVICE TI: _.PARSE _ "," JUNK JUNK S_$UCW2 JUNK _.SETN N_$UCW2 'S_$UCW2' _.SETN N_$ZERO 0 _.IF N_$ZERO _<_> 'S_$UCW2'_&10 _. .LEFT MARGIN -5;.FILL .HL2 F_$SEARCH This case is not covered by the ICP, though it would be nice. You can look for a specific file using the _.TESTFILE directive. If you're doing a wildcard search, the best way is to get SRD off the symposium tapes, use it to build a scratch file containing the names of the files you want, and _.READ the file. You can also read directory files directly, but this is both slower and more complex than the SRD approach. .HL2 F_$SETPRV Not implemented. You could, of course, SET _/NOPRIV=TI: to lose privilege, but there's no way to undo it. The GIN_$ directive toggles task privilege, not terminal privilege, and the M+ ICP is unprivileged anyway. .HL2 F_$STRING This function is accomplished in a manner analogous to F_$INTEGER. The VMS expression _$ FOO = F_$STRING (BAR) is equivalent to the RSX ICP directive .BLANK;.INDENT 5 _.SETS FOO "'BAR'" .BLANK Unlike the F_$INTEGER case, there isn't much that can go wrong here. .HL2 F_$TIME This lexical corresponds to the two ICP special symbols _ (which returns the current date), and _ (which returns the current time). .HL2 F_$TRNLNM The RSX equivalent of BAR = F_$TRNLNM (FOO) is .BLANK;.LEFT MARGIN +5;.NOFILL _.TRANSLATE 'FOO' _.SETS BAR _ .LEFT MARGIN -5;.FILL .HL2 F_$TYPE This functionality is implemented as part of the single-argument _.TEST directive. The directive .BLANK;.INDENT +5 _.TEST FOO .BLANK sets numeric symbol _ to zero if FOO is a logical symbol, two if it is a numeric symbol, and four if it is a string symbol. It will fail if the symbol does not exist at all; use .BLANK;.INDENT +5 _.IFDF FOO .BLANK to test whether FOO is a defined symbol; .BLANK;.INDENT +5 _.IFNDF FOO .BLANK is the test for nonexistence. .HL2 F_$USER The special symbol _ contains the user's current UIC. .HL2 F_$VERIFY You can use the .BLANK;.INDENT +5 _.ENABLE TRACE .BLANK directive to turn on a full trace, and the corresponding _.DISABLE directive to turn it off. The .BLANK;.INDENT +5 _.ENABLE QUIET .BLANK turns off the display of commands other than ICP directives, and the corresponding _.DISABLE directive turns it back on. The testing of the state of these features is discussed above under the F_$ENVIRONMENT directive. .HL1 Things VMS Never Told You About The architecture of RSX has given rise to some features that have no counterpart in VMS. These are discussed below. .HL2 Multiple CLIs In VMS, a process is created with a CLI, which is with it unto death. The major CLI available under VMS is DCL; MCR runs a very poor second. Under RSX, on the other hand, you can switch CLIs at will, and though MCR is the primary CLI from the point of view of the operating system (and the only one guaranteed to be present!), DCL is quite common. The author of an RSX command procedure can thus be faced with the problem of writing command procedures that will run under multiple CLIs. The ICP has a special symbol, _, that contains the name of the current CLI. This information can be made use of in a number of ways: .LIST "*" .LE;Save the name of the CLI, switch to the CLI of your choice for the duration of the command file, and switch back on exit. This requires you to be careful about possible routes out of the command procedure, or the user will be stranded in the wrong CLI. .LE;Have CLI commands for each anticipated CLI, and execute the appropriate ones based on the value of _. This has the advantage tat the user sees commands appropriate to the CLI currently in use, but the disadvantage that multiple versions of each command must be maintained. .LE;Prefix each CLI command with a string symbol, which is set to null if the CLI is the one desired, and some non-null value to force the correct CLI if not. For example: .BLANK;.LEFT MARGIN +5;.NOFILL _.SETS S_$MCR "MCR " _.IF _ _= "MCR" _.SETS S_$MCR "" _'S_$MCR'MOU XX:/OVR/VI .BLANK;.LEFT MARGIN -5;.FILL This is a fairly general approach (since most alternate CLIs understand "MCR" as a request to pass the request through to MCR), and my personnal favorite. But you do have to remember to put the 'S_$MCR' in front of all your MCR commands. .LE;Limit yourself to commands whose syntax is common to all CLIs expected. This can work, but is too restrictive for most applications. .LE;Modify the ICP so that it sets the CLI override bit on entry, then just write everything in MCR. You will have to have to remember to clear the override bit on exit, or make another ICP mod. to handle this. This is the simplest in some respects, but has the drawback of requiring you to modify the ICP, plus making DCL command procedures difficult. .END LIST The CLI override bit probably requires a few words of explanation. It is DEC's solution to the multiple CLI problem, allowing SYSLOGIN.CMD to be written in MCR no matter what the user's CLI is set to. _...HEL (RSX's 'login' portion of LOGINOUT) sets this bit when it first logs the terminal in, and then sets the user's CLI to whatever is contained in the profile entry. SYSLOGIN.CMD must clear the bit using the .BLANK;.INDENT +5 CLI /UNOVER .BLANK command as one of its last acts. The _ symbol does not reflect the setting of the override bit, so you'll need to be careful about using it in circumstances when the that bit might be set. .HL2 _ This special symbol is the basis of the INDSYS module INDDMP. Basically, every reference to it after it is initialized returns the name of the next symbol in the symbol table. Some care is needed (don't create new symbols in the loop), but this can be used in a number of creative ways to search the symbol table. .HL2 Command procedure libraries The ICP is capable of executing a command procedure contained in a universal library. The syntax for this is .BLANK;.INDENT +5 @library/LB:module .BLANK The default file type for a library is _.CLB. Module names are up to six RAD-50 characters. If the module name is omitted, module _.MAIN. is executed. If the /LB qualifier is omitted, the ICP will determine whether the file it is being fed is a library, and react appropriately. A module in a command procedure can invoke another module in the same library by .BLANK;.INDENT +5 @/LB:module .BLANK If this command is used outside a command procedure, it is equivalent to .BLANK;.INDENT +5 @module .BLANK This greatly simplifies troubleshooting, as the library can be taken apart into its constituent command procedures and executed without modification. Command procedure libraries are useful for organizing complex sets of command procedures; the RSX-11M+ SYSGEN, for example, is implemented as a command procedure library. .HL1 Bibliography .NOAUTOPARAGRAPH;.NOFILL .BLANK 2 "Indirect Command Files for New RSX Users" Allen A. Watson RSX/IAS SIG Symposium Handout Spring 1983 DECUS US Symposium .BLANK 2 RSX LB:[1,2]ICP.HLP On-line help file for ICP. Contains some information that is not in the manual. .BLANK 2 RSX-11 I/O Operations Guide Documentation for the contents of . .BLANK 2 RSX-11M/M-PLUS Indirect Command Processor Manual The primary reference for the ICP under RSX. .FILL