The New MPE XL User Interface [ COMMUNICATOR 3000/XL ] MPE/iX Communicators
COMMUNICATOR 3000/XL
The New MPE XL User Interface
by Jeff Vance and John Korondy--Information Technology Group
The MPE XL User Interface, consisting of commands, expressions, variable
and intrinsics, encapsulates the majority of communication between the
end-user and the HP 3000. This new User Interface is designed to satisfy
several important goals. First, it is to be compatible with MPE V/E.
Second, it furnishes the foundation technology for localizing the User
Interface. Third, it provides a powerful, flexible, and productive
environment for the general user, as well as the experienced user.
Fourth, it is desirable to expose some of the architectural advantages of
the HP Precision Architecture.
This article describes the new MPE XL User Interface, focusing on the
extensions beyond MPE V/E. The command language aspect of the User
Interface is emphasized and examples are provided. Knowledge of the MPE
V/E User Interface and the basic use of the new MPE XL commands is
assumed.
MPE V/E COMPATIBILITY
Most of the MPE V/E commands (e.g. file, listeq, fcopy, showjob) have
been "ported" to MPE XL without modification. These commands typically:
execute in Compatibility Mode (CM); retain their original syntax
(parsing); and retain their original error/warning conditions. Some MPE
V/E commands parse in CM and then switch to Native Mode (NM) to complete
execution. The listf, listacct, and report commands have been
implemented this way so that the external interface is unchanged, despite
the fact that internal interfaces are considerably different. And,
finally, some MPE V/E commands, and all new MPE XL commands, execute in
NM. Examples include: redo, setcatalog copy, chgroup, and print. All
MPE V/E commands which have been enhanced (e.g.redo) will continue to
function as in MPE V/E. The new features can only be invoked by supplying
additional parameters.
CONSISTENCY AND LOCALIZATION
All Native Mode (NM) commands are parsed by a centralized parser, which
enforces a consistent syntax and provides the ability to localize command
input. Localization of command output can be done via the message
catalogs.
Each NM command has a parse template, called a "prompt string" , which is
used by the parser to recognize the entire syntax for the command. This
includes the spelling and position of every required and optional command
parameter. Prompt strings can be generated in many languages, thus the
command could be parsed and executed regardless of the input language.
Localization is not available on first release because many MPE XL
commands are still parsed and executed in Compatibility Mode; and also
many commands still produce hard-coded output. However, the foundation
is in place for the entire User Interface to be localized.
EVOLUTION OF THE COMMAND INTERPRETER (CI)
The majority of MPE XL User Interface enhancements make the Command
Interpreter (CI) more powerful, more flexible, and easier to use than its
predecessor. This can be viewed as the evolution of the CI from a
command interpreter to an interpretive command language. This evolution
is necessary to support the diverse and complex requirements of the
nonprogrammer end-user, as well as addressing the needs of the
experienced user and programmer. Like most programming languages, the CI
supports variables, expression evaluation, and logic flow control via
recursion, iteration (while), and conditional constructs (if, else,
endif).
This section contains five parts. First, command files are discussed and
compared to UDCs. Next, the CI's search path for command files and
program files is described. The third part explains CI variables as a
powerful extension of JCWs. Next, expression evaluation is described,
and lastly, several command file examples are provided that tie together
variables and expressions.
Command Files
Command files are simply files that contain one or more commands. The
command lines are referred to as the "body" of the command file. A
command within a command file may be an MPE XL command, a UDC command, or
another file name. A command file can contain a header, which defines
parameters and options (same as UDC options). As with UDCs, command
files cannot contain data following the command line. If a command file
accepts parameters the first record must begin with "PARM" followed by
the parameter list. For example: PARM p1, p2=10, p3="". This parameter
line indicates that there are at most three parameters: the first
parameter is required; the second parameter is optional, with a default
value of 10; and the last parameter is also optional, with a default
value of "" (nil).
UDCs versus Command Files
Command files are very similar to UDCs in that they create customizable
commands. Three major differences exist between command files and UDCs:
* First, since UDCs are searched before MPE XL commands, they can
effectively override or redefine an existing MPE XL command. Command
files are looked for after MPE XL commands, and thus cannot be used
for this purpose.
* Second, UDCs are cataloged and command files do not have this
requirement. This situation has three implications: a) new UDCs
cannot be created and old UDCs cannot be modified without first
uncataloging the UDC file and then recataloging it; whereas, command
files do not have this constraint; b) a UDC file is only opened once,
at logon, but a command file must be opened and closed for each
invocation; c) UDCs provide more efficient organization for command
scripts and use less disc space than if each UDC command were kept as
a separate command file.
* Third, UDCs can control whether or not recursion is permitted via
OPTION RECURSION. Command files do not support the control of
recursion (although recursion is legal).
In summary, UDCs should be chosen for frequently used, stable commands,
and for command name aliasing. For performance reasons, recursion should
be confined to UDCs. Command files are best suited for scripts that can
be enhanced often for testing of potential UDCs, and for environments
where dynamic search paths are exploited. HELP is available for UDCs,
command files, and program files.
Search Path and Implied Run
The CI follows a user-defined search path when looking for
command/program files. This path is only examined if the user's command
is not a UDC and is not a built-in (known) MPE XL command. The HPPATH
predefined variable contains the current search path. If HPPATH is null
(:setvar hppath "") then no command files will ever be found. The
default value for HPPATH is "!HPGROUP,pub,pub.sys". If the command
entered is X (assume X is not a UDC) then the file X.logon group
(!HPGROUP) will be searched for. If it is not found then X.pub is looked
for. If, again, it is not located then X.pub.sys is examined. If, after
this final attempt, the file cannot be found then the command X is
assumed to be an unknown command name and CIERR 975 is reported.
On the other hand, if a file named X is located in one of the groups
specified by HPPATH then its file code is read to determine if the file
is a program file (file code of 1029 or 1030), a command file (file code
within zero through 1023), or neither. The search path can be altered
via the setvar command. To illustrate, if most of your command files
reside in a group named "scripts" , in your logon account, then changing
HPPATH can speed up command file searching. For example, SETVAR HPPATH
'scripts, '+ HPPATH would add the group "scripts" to the current search
path. The SETVAR command, variables, and "!" dereferencing are discussed
below.
Implied Run
Program files use the same search path as command files. Using the
default path, SPOOK.PUB.SYS can be invoked simply by issuing "spook" .
This is referred to as "implied run" . Implied run commands have two
optional parameters. The first parameter is assumed to be an info
string, and the second parameter is interpreted as the parm= RUN
command parameter. Other options and keywords on the RUN command
(debug,lmap,unsat=,stdlist=, etc.) are not supported by the implied run
facility.
Variables
Commands: setvar, showvar, deletevar, setjcw, showjcw.
Intrinsics: hpciputvar, hpcigetvar, hpcideletevar, setjcw, getjcw,
putjcw, findjcw.
An MPE XL variable is similar to an MPE V/E JCW. However variables can
contain 32 bit integers, string values, Boolean TRUE or FALSE, or the
name of other variables (also a string value). Like JCWs, variables are
job/session global, meaning that any process within a given job or
session can read (and possibly modify) a variable. There are two major
classes of variables: user-defined, via the new SETVAR command or the
HPCIPUTVAR intrinsic, and HP-predefined variables such as HPACCOUNT,
HPDATEF, etc. The new MPE XL Commands Manual (P/N 32650-60002) contains
a list of all predefined variables. All user-defined variables can be
read, modified, and deleted. Most HP-predefined variables are read-only,
however, several important variables can also be modified (for example:
HPPROMPT, HPPATH, HPCMDTRACE, HPAUTOCONT, HPMSGFENCE, HPREDOSIZE,
HPRESULT, HPTIMEOUT). None of the predefined variables can be deleted.
Four variable types are supported: integer, string, Boolean, and JCW. If
a variable is created via the setjcw command then it becomes a JCW-type
variable and a warning is issued if it is changed to a value not
supported by MPE V/E JCWs.
The value of a variable is retrieved by placing an exclamation point (!)
before the variable name, e.g. !MY_VAR. This is called dereferencing the
variable: the name "MY_VAR" is replaced by its value. For example, if
MY_VAR contains the string 'hi there' (e.g. setvar my_var 'hi there')
then every occurrence of !MY_VAR is substituted by the string "hi there".
T This is the same substitution that is done for UDC parameters. A
variable's value can also be retrieved when its name is used within an
expression (this is implicit dereferencing, whereas !varname is explicit
dereferencing). Two examples of implicit dereferencing follow:
:while i < len(Var_x) do
:setvar my_calc hpresult+10
As mentioned above, a variable may contain the name of another variable.
This is essential for read/write variables whose values are dynamic. For
example, if you want to personalize the CI's prompt to contain your
username followed by "(current command number):" , e.g. JEFF(10):, then,
since the command number is always changing, a dynamic variable is
required. This prompt can be obtained by the following command:
:setvar hpprompt '!hpuser(!!hpcmdnum):'
The quotes cause the variable type to be a string type. The first "!"
dereferences the value of the HPUSER predefined variable (i.e. "JEFF").
The next two exclamation points ("!!") fold to a single exclamation point
followed by the string "hpcmdnum" (also a predefined variable). Thus, a
showvar of HPPROMPT would reveal "JEFF(!HPCMDNUM):" as its value. To see
how this translates " JEFF(10):" recursive dereferencing needs to be
explained. Whenever a variable is explicitly dereferenced (!varname)
substitution is done until all dereferences within varname's value have
been attempted. The following simple example will illustrate this:
:setvar a "!!b" {!b is stored as the value of a}
:setvar b 10 {10 is stored as the value of b}
:echo Here is A: !a {"Here is A: 10" will be echoed}
!a is dereferenced as !b, which in turn is dereferenced as 10. SHOWVAR
retrieves the immediate value of a variable. This is also true for
implicit dereferencing. However, explicit dereferencing always fully
substitutes the variable. So, in the HPPROMPT example above, since the
prompt contains an exclamation point indicating another variable needs to
be retrieved, HPPROMPT will be fully dereferenced before it is displayed.
Thus, the final prompt would be "JEFF(10):" when the current command
number is 10, and will always track the command number.
QUESTION: - What would the prompt be if a single explanation point used
rather than the two, e.g. setvar hpprompt '!hpuser (!hpcmdnum):'?
ANSWER: - The prompt would contain the current command number as a static
variable. For example if the command number was 12, the prom would
always show 12, regardless of the increasing command number.
Expressions
Commands: calc, setvar, if, while.
Intrinsics: fdhpcicommand, command.
Implicit expressions are permitted in five commands: calc, setvar, if,
while, and setjcw. The following discussion does not pertain to setjcw,
which retains MPE V/E expressions. The expression evaluator supports a
rich set of functions. The entire list is available in the MPE XL
Commands Manual. All arithmetic operations are allowed, including:
absolute value (ABS), modulo (MOD), and exponentiation (^). Many string
functions (an argument is a string) are defined, such as: concatenation
(+), length (LEN), ordinal (ORD), extraction (LFT, RHT, POS, STR), and
case shifting (DWNS, UPS). Special variable functions include: existence
(BOUND) and type (TYPEOF). The bit operations supported include: bitwise
and (BAND), bitwise or (BOR), bitwise not (BNOT), bitwise exclusive or
(BXOR), shift left (LSL), and shift right (LSR). Numeric conversion
functions are: convert to octal (OCTAL) and convert to hexadecimal
(HEX). Finally, some special file functions are provided via FINFO and
include: file existence (FINFO(0)), file creation date (FINFO(6)), file
modification date (FINFO(8)), file code (FINFO(9)), foptions (FINFO(13)),
and others.
It is also possible to use expressions in any MPE XL command by
explicitly dereferencing the expression, referred to as "expression
substitution" . To do this, enclose the expression within square
brackets and precede it with an exclamation mark: ![ expression ]. For
example, :print ![prefix+'01'+suffix] where the suffix and prefix
user-defined variables contain string values.
Mixed expressions are not allowed, for example, calc "a"+1 would result
in an error. Standard precedence rules apply, with variable
dereferencing superseding all other operations.
Below are some examples using variables and expression evaluation:
:setvar a 'aa' {a = aa}
:setvar b 'BB'+a {b = BBaa}
:setvar c (len(b)+pos("a",b)) lsl 1 {c = (4+3) lsl 1=14}
:if bound(a) and ord(ups(a))=65 then {T AND T = TRUE}
{ assume file "BBAA" exists }
:calc finfo(b,0) {TRUE}
{ assume eof on "SL" is 5540 }
:file x;disc=![100+finfo('sl',19)/2] {:file x;disc=2820}
{ assume HEAPSIZE=500 }
:run pgm;nmheap=![heapsize*4] {:run pgm;nmheap=2000}
Command File Examples
The first command file is more fully commented than the others and should
read thoroughly.
1. "CIERR" - prints the error message text associated with either the
current value of the CIERROR JCW, or a passed cierror value.
PARM cierr=0
OPTION nolist
COMMENT Parameter cierr is not required. Its default value is 0.
COMMENT The "parm" and "option" lines comprise the header.
COMMENT
COMMENT If cierr is not zero then save the current cierror JCW
COMMENT and set the cierror JCW to cierr. Note that parameters
COMMENT must always be explicitly dereferenced. Implicit
COMMENT dereferencing is only available to global variables.
if !cierr <> 0 then
comment Since we're dealing with global variables,
COMMENT use an unlikely name.
setvar _cierr cierror
setjcw cierror !cierr
endif
COMMENT Retrieve the error text associated to the value of CIERROR.
setvar _text hpcierrmsg
if len(_text) = 0 then
COMMENT No error message corresponding to CIERROR.
setvar _text 'INVALID CI ERROR NUMBER (!cierror).'
endif
COMMENT Display the final message to $stdlist.
echo !_text
COMMENT Cleanup by deleting global variables used here
COMMENT and resetting CIERROR if necessary.
deletevar _text
if !cierr <> 0 then
setjcw cierror !_cierr
deletevar _cierr
endif
COMMENT End of command file.
Usage:
:setjcw cierror 9072
:cierr 9103
THIS COMMAND IS NO LONGER SUPPORTED IN MPE XL. (CIERR 9103)
:cierr 2
INVALID CI ERROR NUMBER (2).
:cierr
THERE ARE NO COMMANDS AVAILABLE TO REDO. (CIERR 9072)
This command file can be improved by adding parameter verification
code, i.e., test if the parameter is fully numeric. For example:
if typeof(!cierr) <> 1 then
comment 0=bad expression, 1=numeric, 2=string, 3=Boolean.
echo Expected optional parameter to be numeric.
else ...
2. "TAIL" - this command file prints the last n records from a given
file.
PARM file, last=10
COMMENT Print the last "last" records from "file".
print !file;start=-!last
COMMENT End of command file.
Usage:
:tail catalog.pub.sys
:tail myletter 40
3. "PRT" - this command file prints to EPOC up to six files.
PARM f1,f2=",f3=",f4=",f5=",f6=";env=elite
COMMENT Prints f1-f6 to EPOC. User may specify environment.
setvar i 1
while '!"f!i"' <> " do
if finfo('!"f!i"',0) then
file !"f!i";dev=epoc;env=!env.hpenv.sys
echo (PRT): Printing of ![finfo('!"f!i"',1)] in progress...
print !"f!i",*!"f!i"
reset !"f!i"
else
echo (PRT): ![ups('!"f!i"')] not found... printing skipped.
endif
setvar i i+1
endwhile
deletevar i
COMMENT End of command file.
Usage: (assume logon group=LEI, logon account=UI and file MEMO does not exist)
:prt letter,memo,paper.doc
(PRT): Printing of LETTER.LEI.UI in progress...
(PRT): MEMO not found... printing skipped.
(PRT): Printing of PAPER.DOC.UI in progress...
4. "ME" - this command file provides a convenient :showme format.
PARM flag="
COMMENT Shows user environment info similar to :showme. If "flag" is non
COMMENT null then the user's capabilities are also displayed.
if hpinbreak then
echo (#!hpjobtype!hpjobnum)!hpuser.!hpaccount,!hpgroup&
Ldev=!hpldevin CI=hpcidepth "!hpsysname"&
!hptimef <In Break>
else
echo (#!hpjobtype!hpjobnum)!hpuser.!hpaccount,!hpgroup&
Ldev=!hpldevin CI=hpcidepth "!hpsysname"&
!hptimef
endif
if "!flag" <> "" then
echo !hpusercapf
endif
COMMENT End of command file.
Usage:
:me
(#S97)JEFF.UI,CI Ldev=210 CI=1 "JOY" 5:17 PM
:me x
(#S6)MANAGER.SYS,SCRIPTS Ldev=20 CI=1 "JOY" 10:30 AM <In Break>
AM,AL,GL,DI,CV,UV,LG,CS,ND,SF,IA,BA,PH,DS,MR,PM
5. "ADDCAP" - this command file adds a capability to the logon user's
current capabilities.
PARM cap
COMMENT Syntax: addcap <capability>
COMMENT Adds "cap" to the current user's existing capabilities. 'AM' is
COMMENT required to execute the :altuser command. The new capability
COMMENT takes effect only after the user logs on again.
COMMENT: make sure that the user doesn't already have "cap"
if pos(ups('!cap'),hpusercapf) > 0 then
echo (ADDCAP): You already have ![ups('!cap')].
else
setvar cierror 0
continue
altuser !hpuser;cap=![hpusercapf+',!cap']
if cierror <> 0 then
echo (ADDCAP): Your capabilities remain: !hpusercapf.
else
echo (ADDCAP): Your new capabilities are: &
![hpusercapf+','+ups('!cap')]
setvar addcap_temp 'N'
continue
input addcap_temp,'(ADDCAP): Log off/on now (Y/N)> ',10
if cierror = 9003 then
echo (ADDCAP): Timed 10-second read expired. Logon canceled.
else
if ups(lft(addcap_temp,1)) <> 'Y' then
echo (ADDCAP): New capabilities take effect at next logon.
else
hello !hpjobname,!hpuser.!hpaccount,!hpgroup
endif
deletevar addcap_temp
endif
endif
endif
Usage:
:listuser foo
********************
USER: FOO.UI
HOME GROUP: CI PASSWORD: **
MAX PRI : 150 LOC ATTR: $00000000
LOGON CNT : 1
CAP: AM,ND,SF,BA,IA,PM,MR,PH
:addcap pm
(ADDCAP): You already have PM.
:addcap al
(ADDCAP): Your new capabilities are: AM,ND,SF,BA,IA,PM,MR,PH,AL
(ADDCAP): Log off/on now (Y/N)> no
(ADDCAP): New capabilities take effect at next logon.
:addcap al
(ADDCAP): Your new capabilities are: AM,ND,SF,BA,IA,PM,MR,PH,AL
(ADDCAP): Log off/on now (Y/N)> yes
CPU=10. CONNECT=71. WED, MAY 6, 1987, 12:44 PM.
HP3000 / MPE XL 9.20.22. WED, MAY 6, 1987, 12:45 PM.
============================================================
6. "LOGPUR" - this command file purges all log#### log files in
pub.sys. For better performance the user can specify the starting
log file number. The purged log file name will be echoed if the
second parameter is not "QUIET" .
PARM lognum=0,mode='QUIET'
COMMENT Purge all log####.pub.sys starting at "lognum". Echo purged
COMMENT file if not "quiet".
setvar _logcnt 0
setvar _logx !lognum
setvar _quiet ups(lft(!mode,1)) = 'Q'
setvar _cont hpautocont
setvar _msg hpmsgfence
setvar hpautocont true
setvar hpmsgfence 2
setvar cierror 0
COMMENT Find first log file to purge.
setvar _logname "LOG"+str('0000',1,4-len('!_logx'))+"!_logx"
purge !_logname
while cierror = 383 or cierror = 0 do
if cierror = 0 then
setvar _logcnt _logcnt+1
if not (_quiet) then
echo (LOGPUR): !_logname.PUB.SYS has been purged.
endif
endif
setvar _logx _logx+1
setvar _logname "LOG"+str('0000',1,4-len('!_logx'))+"!_logx"
setvar cierror 0
purge !_logname
endwhile
setvar hpautocont_cont
setvar hpmsgfence_msg
echo (LOGPUR): !_logcnt log files were purged.
deletevar _logcnt, _logname, _logx, _quiet, _cont, _msg
COMMENT End of command file.
Usage: (assume LOG0030, LOG0031, LOG0032, LOG0033, LOG0034*)
:logpur
(LOGPUR): 4 log files were purged.
:logpur 30
(LOGPUR): 4 log files were purged.
:logpur 32,loud
(LOGPUR): LOG0032.PUB.SYS has been purged.
(LOGPUR): LOG0033.PUB.SYS has been purged.
(LOGPUR): 2 log files were purged.
7. "FINFO" - displays file label information for a given filename.
PARM file
COMMENT Use finfo to show file label info.
if not finfo('!file',0) then
comment File does not exist.
if lft('!file',1) <> '*' and lft('!file',1) <> '$' then
comment Qualify file before reporting non-existence.
if pos('.','!file') > 0 then
if pos('.',rht('!file',len('!file')-pos('.','!file'))) > 0 then
echo ![ups('!file')] does not exist.
else
echo ![ups('!file')].!hpaccount does not exist.
endif
else
echo ![ups('!file')].!hpgroup.!hpaccount does not exist.
endif
else
echo !file does not exist.
endif
else
comment ** formal file designator **
echo (FINFO): Full file description for ![finfo('!file',1)] follows:
comment ** creator and create/modify dates **
echo Created by ![finfo('!file',4)] on ![finfo('!file',6)].
echo Modified on ![finfo('!file',8)] at ![finfo('!file',24)].
comment ** file code **
if finfo('!file',9) = " then
echo Fcode: ![finfo('!file',-9)].
else
echo Fcode: ![finfo('!file',9)] (![finfo('!file',-9)]).
endif
comment ** rec size, eof, flimit **
echo Recsize: ![finfo('!file',14)], Eof: ![finfo('!file',19)], &
Flimit:![finfo('!file',12)].
comment ** foptions **
setvar _fopt finfo('!file',-13)
echo Foptions: ![finfo('!file',13)] (#!_fopt, ![octal(_fopt)],&
![hex(_fopt)]).
deletevar _fopt
endif
COMMENT End of command file.
Usage: (assume logged into PUB.SYS)
:finfo sl
(FINFO): Full file description for SL.PUB.SYS follows:
Created by MANAGER on TUE, DEC 9, 1986.
Modified on TUE, DEC 9, 1986 at 7:00 PM.
Fcode: SL (1031).
Recsize: -256, Eof: 103927, Flimit: 108320.
Foptions: BINARY, FIXED, NOCCTL, STD (#1, %1, $1).
:build a;msg;rec=-80,,f,ascii;cctl
:finfo a
(FINFO): Full file description for A.PUB.SYS follows:
Created by JEFF on WED, OCT 22, 1986.
Modified on FRI, OCT 24, 1986 at 6:45 AM.
Fcode: 0.
Recsize: -81, Eof=0, Flimit=1029.
Foptions: ASCII, VARIABLE, CCTL, MSG (#12613, %30505, $3145)
:build temp;temp;rec=40,,f,ascii;disc=100
:file t=temp
:finfo *t
(FINFO): Full file description for TEMP.PUB.SYS follows:
Created by MGR on FRI, OCT 24, 1986.
Modified on WED, DEC 10, 1986 at 2:26 PM.
Fcode: 0.
Recsize: -80, Eof: 0, Flimit: 100.
Foptions: ASCII, FIXED, NOCCTL, STD (#1030, %2006, $406).
:build $newpass
:finfo $oldpass
(FINFO): Full file description for $OLDPASS.PUB.SYS follows:
Created by JEFF on SAT, OCT 25, 1986.
Modified on SAT, OCT 25, 1986 at 11:30 AM.
Fcode: 0, Recsize: -256, Eof: 0, Flimit: 1023.
Foptions: BINARY, FIXED, NOCCTL, STD (#1050, %2032, $41A).
MPE/iX Communicators