HP3000-L Archives

November 1996, Week 4

HP3000-L@RAVEN.UTC.EDU

Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Jeff Vance <[log in to unmask]>
Reply To:
Jeff Vance <[log in to unmask]>
Date:
Mon, 25 Nov 1996 17:29:36 -0800
Content-Type:
text/plain
Parts/Attachments:
text/plain (1161 lines)
Hi all,

Here is the semi-formal document that describes the enhancements that CSY
is planning on providing in the area of CI variables.  This should mostly
satisfy the customer requirements for globl or system-wide variables, and
for local variables.

If you want to be able to influence the outcome of this effort please
read this document!  I know that it is long, but this is what will be
implemented and you now have a chance to make sure this new feature will
be usful and useable in your company.  Also I have several unresolved
issues where I am seeking your advice.

I would like to publicly thank the small team of customers who
showed tremendous dedication by helping us with the external features
and the basic implementation.  These folks went way beyond "the call
of duty" in assisting us:
  Jerry Fotchmann
  Donna Gaverick
  Paul Taffel
  Stan Sieler

Also, a special thanks to the rest of this mini design team who gave me great
and timely suggestions via many e-mail correspondences:
  Jon Diercks
  John Korb
  Lars Appel

I got email from many of you and I thank you for helping me improve the
design where needed, and letting me know when I was violating the KISS
principle!  Noteworthy in providing ample freedback were:
  Glen Cole
  John Dunlop
  Alfredo Rego
  Ken Sletten

I guarantee we would have a different (and inferior) design if I did it alone.


Many thanks to all,
Jeff Vance, CSY


-------------------------------------------------------------------------------
Here is the offical External Specifications for global, account and private
CI variables.

I have sprinkled a few questions in this document.  The questions are
enclosed in a banner like:
"======================== QUESTION ======================="

I also have repeated all of the questions in Appendix G.


Motivation:
-----------
Today all vars live in one scope -- the job/session scope.  This means
that all jobs and sessions on the system have their own variables that
cannot be seen or shared across different jobs.  This makes it very
difficult for a user or process, external to the job, to control or
influence the job via CI variables.  It is also wasteful, both in terms
of memory and in logon time, for every job and session on the system to
create many of the same predefined HP variables.  For example: HPCONSOLE,
HPSUSAN, HPUSERLIMIT, HPJOBCOUNT, HPSESLIMIT, etc. are variables that
are unique to the system, yet are duplicated for every job and session
logged on.  Another consequence of today's single scope for all variables
is that all processes and scripts within a given job share the same
variables.  This results in scripts that, without care, can inadvertently
overwrite a job variable, or scripts that exit without properly deleting all
the CI variables they created.

Solution:
---------
This enhancement introduces 3 new scopes for CI vars: the most global
scope is named "global".  Vars created in this scope are potentially
accessible to all processes on the system.  The next narrower scope is
named "acct" or "account".  Vars living in this scope are potentially
accessible to all processes that are members of the same account.  The
next narrower scope is named "jobses" or "job"*.  This is the scope where
all CI vars live today.  Vars at this scope are accessible by all processes
running in the same job/session.  The next narrower scope, which is the
most local scope, is named "private".  Vars in this scope are accessible
only by the script that created them.  "Potentially accessible" is accurate
since an ACD will be created for vars in global and acct scope, and these
ACDs can be altered to provide a wide range of access rules.

The phrase "more local", when applied to a CI var, means the var is defined
in a scope with narrower or potentially more restrictions than the scope of
the compared-to var.  If scopes were numbers ranging from 0=global to
3=private, then private (3) is more local than job (2).

Examples of this enhancement can be seen in Appendix D.

=================== QUESTION =======================
* Possibly a more intuitive name for the scope of these vars is "user"
  since the user (and all processes run by the user) has full access to
  all of these vars.
====================================================


GLOBAL VARIABLES:

There are two types of global variables: 1) "global" vars where the
default access is that all users have read access, and 2) "acct"
vars where, by default, only account members have read access.

Since global vars are implemented as files (see Appendix B), the sharing
and modification rules can be easily changed by altering the associated
ACD.  Also, all global and acct vars survive reboot, since they are
permanent files, but may easily be deleted from the sysstart file
via the PURGEDIR command (see appendix E).

Motivate by global vars there is a new property for all variables. If
a variable is created as "unique" then another var of the same name
cannot be created.  This is useful for vars with important roles where
you cannot afford to have a parameter or more locally scoped var hide
or mask the important, more globally scoped var.  See appendix C for more
details on UNIQUE.

Since all global vars are really files, security is controlled via the
existing ACD mechanism.  However, users of global and acct vars need not
be aware of this implementation, since the standard CI variable features
transparently work with these files.  You will be able to use SETVAR to
create or modify global and vars.  !varname will locate global and acct
vars.  The INPUT command can set a global or acct var, etc.  Appendix
B describes the default ACDs that will be applied by the CI; however,
the SM can alter these ACDs or pre-create the special directory structure
to best suit their company's needs.

To create a global var you need to be able to write to the special directory
where all global vars reside.  This directory is in the POSIX name space
and is required to have an ACD.  See Appendix B for a complete description
of the directory sructure and the default ACDs used by the CI when it
creates a global or account variable.  To modify a global var you need write
permission to the actual file that holds the variable's value .

Creating and modifying account vars are similar to the requirements for global
vars.  You need write access to the special directory that the account vars
reside in, and you need write permission to the individual files that hold
the acct var's value.  Appendix B has the details.


PRIVATE VARIABLES:

Private scoped vars cannot alter job/session vars, nor can they be seen
in any context other than the script they were defined in (ignoring a
private var passed as a parm to another script).  Only the script
creating the private var may alter it or delete it.  Once the script
terminates all surviving private vars are automatically deleted.
At a later date we may also provide local vars that are inherited
by nested scripts.  However due to the greater implementation cost this
feature is being excluded for now.

Private vars can mask or hide many of predefined HP variables.  Thus you
can create a private CIERROR or HPMSGFENCE and use it throughout your script.
All CI references to these predefined vars refer to the local instance, and
when your script exits the original predefined vars remain unchanged.

For simplicity sake, private vars are implemented as script parameters.
This has the benefit of permitting script parms to be used exactly like
ordinary CI variables.  A script parm can be modified and can be implicitly
referenced (ie. !parm is no longer required).

NOTE: this represents a backwards incompatibility since today if I have
a parm named P1 and I do   :setvar p1,0   I create a jobses P1 (which
can survive the life of the script).  Tomorrow, the same command will
modify parm P1.
================= QUESTION ===================
Is it acceptable to treat all parms like private vars?  Specifically,
is it ok to refer to a parm as:
   if parm = "abc" then ...  ?
Is it ok to modify a parm, like:
   setvar parm1, value
Noting that this can break scripts that rely on creating a JOB
var with the same name as a parm.
==============================================


VARIABLE NAME RESOLUTION:

The same method is used to resolve a variable name for all var references,
whether via commands, CI functions or intrinsics..  This means that the rule
for finding a var on the right-hand side (RHS) or left-hand side (LHS) when
assigning a value to a var is similar.  Variables retrieved on the RHS of an
assignment can be viewed as reading or loading the var, whereas variables
retrieved on the LHS are being written to or stored.  The description below
assumes that the scope has not been explicitly stated for the var in
question, in other words, we are trying to resolve an unscoped (or
"unqualified") var.

In referencing a var name the CI uses the most local scope first, the
the next most local scope next, etc. until the most global scope is searched.
If the CI is executing a script the first scope searched is PRIVATE, and if
the var is not found in the private scope the JOB scope is searched next.
If the CI is not executing a script the most local scope is JOB.  If a var
is not found here the ACCT scope is searched next.  If the var is still
not located the GLOBAL scope is searched last.  If still the var is not
found then the var does not exist.

The ACCT and GLOBAL scopes are not searched for automatically on the LHS
of a var assignment.  This is to prevent unintentional modification of
new global or acct vars.  Consider a system manager creates a global var
V1 and an old production script happens to create V1 too (expected to be in
the JOB scope).  We don't want the
       setvar v1, init_value
in the script to try to modify the global V1 -- just because global V1
exists!  If the setvar in the script did try to modify the global V1
most likely the user would lack permission and an error would be reported.

It is possible to defeat this "natural" order for var referencing by
explicitly stating the scope within the varname.  For example,
   global:foo    -- indicates look for FOO only in the GLOBAL scope
   private:bar   -- look for BAR only in the PRIVATE scope.
See Appendex A for a complete list of explicit var scopes.

A short-cut to the above explicit scoping is available.  The OPTION
command has a new parameter: VARSCOPE=xxx, where xxx can be JOB or PRIVATE.
This command lets you establish the scope to use for all unscoped var
creations (LHS).

Explict name resolution (eg. !varname) follows the same RHS rules, such
that all possible scopes can be searched.  When a var is referenced whose
value is an explicit var reference (eg. var1's value is "!var2") this is
called "recursive dereferencing".  A scope cannot be specified for any
explicit var dereferencing (!varname) including all levels of recursive var
dereferencing.  Appendix A motivates this rule and has more details.
In other words, you cannot create var1 with a value of "!acct:var2" and
expect an ACCT scoped var2 to be retrieved.  In recursive dereferencing the
scope for all nested !varnames starts a fresh name resolution, meaning that
the nested varname will be searched for beginning in the most local scope
until it is found.


CREATING A VARIABLE:

Unless the command or intrinsic states the scope explicitly, a variable
is created in the JOB scope, as occurs today.  There are two ways to state
the scope to create a var in:
  1) the scope can be embedded in the var name,
  2) the scope can be implied by a previous OPTION VARSCOPE= command.

The only way to create global or account vars is choice one, that is you
cannot imply the GLOBAL or ACCT scopes via the enhanced OPTION command.
This was done to make global and account vars usage explicit.  Because
var name resolution on the LHS of an assignment stops at the JOB scope we
also have greater consistency.

Appendix F describes the full syntax for variable names, including
some future ideas that are not part of this enhancement.  Appendix A
details embedding the scope in a variable's name.


MODIFYING A VARIABLE:

Unscoped vars are modified using the above var name reolution scheme:
we search the different scopes* looking for the var, and the scope the
var is located in is the scope used for the modification.  This means
that once a PRIVATE var is created all modifications to the same var
name apply to this private var.

If there is a private var FOO and a job/session var FOO and you need to
modify the job/session FOO, you will need to state the scope explicitly.
This can be done as:
       setvar JOB:FOO, mod_value

If you need to modify an account var BAR (regardless of whether or not
there are private or job BAR's present) you always need to state the scope:
       setvar ACCT:BAR, mod_value


* Remember that automatic scope lookup is limited to PRIVATE and JOB
scopes.



COMMANDS, FUNCTIONS and INTRINSICS:
(look for more examples in Appendix D)

I.  OPTION Command:

Syntax: OPTION [list|nolist] [recursion|norecursion]
               [VARSCOPE=scope]

where "scope" can be one of the following:
   default          - defeat a previous VARSCOPE=
   private
   job  | jobses

This command can be used anywhere: in a script header, a script body, as
a regular CI command, interactively or in a job to create private CI
vars not associated with a script.

This command only affects the scope for var creation (not modification)
and only applies to varnames that do not have a scope embedded in the
name.  This command affects all unscoped var creations until another
OPTION VARSCOPE= is executed or the script terminates.  OPTION VARSCOPE
scopes are overridden by a scope embedded in the varname.  Use of OPTION
VARSCOPE=xx is equivalent to specifying xx:varname on every LHS variable
assignment.

Global and account scopes are not supported by this command.  To create
vars in these scopes the scope must be prefixed to the varname.  See
Appendix A.

Like the other OPTION arguments, the VARSCOPE= scope is not inherited by
nested scripts.


II.  SETVAR Command:

Syntax:
     SETVAR varname value [;UNIQUE]

Creates or modifies "varname".  Appendix A contains the description
of all possible scope values that may be embedded in "varname".

The default scope for creating new vars is JOBSES (as it is today) unless
a scope is specified.  The default scope when modifying an existing var is
the most local scope that the var is found at, unless a scope is specified.
GLOBAL and ACCT scopes always require explicit scoping for creation and
modification.

IF UNIQUE is specified then varname will not be created if a var of more
local scope already exists.  Once a var is created as UNIQUE, vars of the
same name in a more local scope cannot be created.  UNIQUE only applies at
var creation time -- it is ignored when SETVAR is modifying "varname".
UNIQUE is unnecessary if the scope is PRIVATE since there is not a scope
more local than PRIVATE.

Algorithm:

o  parse varname, note scope if part of name -- see appendix A.

o  if (scope specified in varname) or
      (we're in a script and option varscope set) then
      if varname already exist at this scope then
         modify var at this scope    # applies to parms too!
      else
   PUTVAR:
         # want to create a var at this scope
         # check for higher scoped unique vars
         for scope=specified scope+1 to global scope do
            if varname exists at scope and unique_bit=true then
               error: can't create var due to UNIQUE rule; return
            endif
         endfor
         if unique specified for varname then
            # make sure var not found in more local scope
            if in script then most_local=private
            else most_local = jobses
            for scope=specified scope-1 downto most_local do
               if varname exists at scope then
                  error: can't make unique; return
               endif
            endfor
         create var at this scope
      endif

o  else  # scope not known.
      # find scope for varname if it exists.  Note acct and global
      # intentionally skipped since these scopes must be explicit
      if in a script then start_scope is private
      else start_scope is jobses
      for scope = start_scope to jobses do
         if varname exists at scope then  # setvar is modify, not create
            scope is defined; goto PUTVAR
         endif
      endfor
      # var doesn't exist at the above tested scopes so create jobses var
      scope=jobses
      goto PUTVAR
   endif


The above logic applies to :INPUT, setvar() function and HPCIPUTVAR.

=====================================
Note: the SETJCW command is not being enhanced to support embedded
scoping as part of the JCW name.  To create a private JCW the OPTION
VARSCOPE= command must be used.
=====================================


III.  INPUT Command:

Syntax (unchanged):
     INPUT varname [;prompt=string] [;wait=seconds] [;readcnt=num_bytes]

The INPUT command optionally prompts to $stdlist and reads $stdin input
into varname.  Varname can have the scope embedded, see Appendix A, or
the scope can be inferred from a previous OPTION VARSCOPE= command.
Lacking any stated scope, varname is created in the JOB scope, or modified
(if it already exists) in the PRIVATE or JOB scope, based on the rules
already stated.

Here is a way to get the value from INPUT into an acct var:
   input acct:foo, "Please reply Y or N"; readcnt=1

Note what follows will *not* cause INPUT to modify an acct var:
   setvar acct:foo, "abc"
   input foo,"prompt>"    # created job/session FOO
   # ABOVE DID *NOT* MODIFY THE ACCT VAR FOO!

INPUT in this case did not modify the existing account scoped foo since
the scope for foo was not embedded in the varname and the varname
resolution rules prohibit searching the acct and global scopes for LHS
assignments.


IV.  SHOWVAR Command:

Syntax:
     SHOWVAR vars [FORMAT=DETAIL | BASIC]

where "vars" can be one or more variable names or wildcarded patterns.

The scope of the var to display may be part of the var name (see
Appendix A).  If the scope is specified and "vars" exists in that scope,
it will be shown and no further scopes will be searched.  If the scope is
specified and the var does not exist in that scope a "variable not found
in scope" error is reported.

If the scope is not specified then all scopes will be searched, starting
at the most local, until the first var matching variable is found.  If
"@" is used as the scope then the matching var will be shown in all scopes
it occupies; in other words, we don't stop at the first match.

================= QUESTION ===================
What does SHOWVAR <no argument> mean? (today we show all non-predefined vars).
- Should it mean the same with scoping?  If so, how do we distinguish var FOO
which may be listed 4 times (once per possible scope).
- Another interpretation is "show all vars I created", which again could
span many scopes.  However, this interpretation would less likely show
many acct or global vars (unless the user created them??).
- A third possibility is "show job/session vars I created" (which is literally
what is done today), meaning an implied jobses: scope.

Follow on questions: does this behavior ("show vars I created") need a way to
be explicitly specified, like a ;USER | PREDEFINE option?  This would allow
you to use pattern matching separately from controlling the above behavior.
==============================================

================= QUESTION ===================
What does SHOWVAR @  mean? (today we show all vars).
- Should it mean the same with scoping and display all vars at all scopes?
- Should it just show all vars that it would "naturally" discover using the
scoping hierarcy rules.  This means that if we show a private var FOO then
we don't display a JOB, ACCT or GLOBAL foo.  We still need to search all
vars in all scopes.
- Should the jobses scope be inferred in SHOWVAR @?
==============================================

The default format is BASIC, which just shows a list of varnames
followed by their value (today's format).

The new DETAIL format shows the following information about each var:
- name,
- value,
- type (eg. integer, boolean , string & len, jcw)
- properties (predefined, unique, programmatically avail, refparm...)
For acct and global vars:
- owner,
- access restrictions,
- locked state,
- last date/time accessed??
- what else in important??  what above is not needed??

ALL SUGGESTIONS FOR EASY-TO-READ OUTPUT FORMATS ARE GLADLY ACCEPTED !!

Algorithm:

o  parse var names(s), allow for wildcards, note scope in name

o  for each varname[i] in command line do

o     if scope specified in varname and scope <> @ then
         if varname[i] wildcarded then
            find all matches in var tbl at this scope
         endif
         if vm_bound(varname[i], scope) then
            display_var(varname[i], scope, format)
         else
            if varname wildcarded then
               warn: "var not found"
            else
               error: "var not found"
            endif
         endif

o     else  # scope is not stated or is @
         if varname[i] wildcarded then
            find all matches in var tbl at this scope
         endif
         if in script then start_scope=private
         else start_scope=job
         for scope in start_scope to global do
            if vm_bound(varname[i], scope) then
               display_var(varname[i], scope, format)
               if specified_scope <> @ then return
               endif
            endif
         endfor
         if no var displayed then
            if varname wildcarded then
               warn: "var not found"
            else
               error: "var not found"
            endif
         endif
      endif


V.   DELETEVAR Command:

Syntax (unchanged):
     DELETEVAR vars

where "vars" can be one or more variable names or wildcarded patterns.

The scope of the var being deleted may be part of the var name (see
Appendix A).  If the scope is specified and "vars" exists in that scope,
it will be deleted and no further scopes will be searched.  If the scope
is specified and the var does not exist in that scope a "variable not found
in scope" warning is reported.

If the scope is not specified then DELETEVAR works similarly to SETVAR in
that only the PRIVATE and JOB scopes are searched for the var to be deleted.
To delete account and global vars their scope needs to be part of the
var name.  Remember that OPTION VARSCOPE applies only to var creation
scopes, not retrieval nor deletion.

================= QUESTION ===================
What does DELETEVAR @  mean? (today we delete all deleteable vars).
- Should it mean the same with scoping and delete all "deleteable" vars at
all scopes?  This means if there was a private, job and global FOO var, all
three FOOs would be deleted.
- Should it just delete all vars that it would "naturally" discover using the
scoping hierarcy rules.  This means that if we delete a private var FOO then
we don't try to delete a JOB, ACCT or GLOBAL foo.  We still need to search
all vars in all scopes.
- Should the jobses scope be inferred in DELETEVAR @?
==============================================

To delete all occurences of the var FOO you can:
  a)  Brute force technique:

     deletevar foo    # del private foo
     deletevar foo    # del jobses foo
     continue
     deletevar acct:foo
     continue
     deletevar g:foo

  b)  Finesse technique:

     setvar p:hpmsgfence,2         # create private hpmsgfence to stop noise
     while bound(foo,p:scope) do   # while FOO exists somewhere...
        continue
        deletevar !scope:foo
     endwhile


Algorithm:

o  parse var names(s), allow for wildcards, note scope in name

o  for each varname[i] in command line do

o     if scope specified in varname then
         if varname[i] wildcarded then
            find all matches in var tbl at this scope
         endif
         if not vm_bound(varname[i], specified_scope {don't rtn foundscope})
            error: var not found; return
         endif
         delete_var(varname[i], specified_scope)

o     else  # scope is not stated
         if not vm_bound(varname[i],{no_scope}, found_scope) then
            error: var not found in any scope; return
         endif
         # "found_scope" is the scope var was 1st found in
         delete_var(varname[i], found_scope)
      endif
   endfor  # each var in command line



VII.  bound() Function:

Syntax:
     bound(varname [,rtn_scope])

where the scope can be embedded in "varname".  If "rtn_scope" is
passed the scope that varname was found in is returned in the var named
by "rtn_scope".  This var will be a string var with a values shown in
Appendix A.

bound() is a boolean function, returns true if varname exists.  A single,
specific scope is searched if the scope prefix is used in "varname".
If the scope is not supplied then varname is searched in each scope:
private, job, acct and lastly global.  The first scope that varname
lives in stops the search, causes TRUE to be functionally returned, and
sets the "rtn_scope" argument -- if it is passed.

If varname cannot be found, either in a specified scope, or in any
scope then FALSE is returned.

Algorithm:

o  parse varname, note scope if part of name.  See appendix A.

o  if scope specified then
      if varname exists at scope then
         set rtn_scope to specified scope; return TRUE
      else
         return FALSE
      endif

o  else  # scope is not stated
      if in a script then start_scope = private
      else start_scope = jobses
      for scope in start_scope to global
         if varname exists at scope then
            set rtn_scope to scope; return TRUE
         endif
       endfor
      # varname not found in any scopes
      return FALSE
   endif


VIII. HPCIPUTVAR Intrinsic:

Syntax:
                    CA    I32      U32V   *
      HPCIPUTVAR(varname,status[,itemnum,item] [...])

Programmatically creates or modifies a CI variable.

"varname" follows the rules for a CI variable name.  A scope may be
embedded in varname.  If no scope is stated varname is searched for
starting in the most local scope until it is found.  If it is not
located a job/session var is created.  If it is found that var is modified.

If varname contains an embedded scope and item 20 is passed the embedded
scope takes precedence and a warning is returned.

Two new item pairs have been added:


  item      description / value
____________________________________________________________________________
    20   |  defines the scope for new varname creation -- ignored if
         |  varname is being modified.
         |
         |   0    - default scoping (same as not passing item 20)
         |   10   - private scope
         |   20   - job scope
         |   30   - account scope   - ACD access control in affect
         |   40   - global scope    - ACD access control in affect
_________|__________________________________________________________________
    25   |  defines the UNIQUE property for varname.
         |
         |  If set to 1 then varname is created as a unique var, thus a
         |  more locally scoped var of the same name cannot exist, and
         |  subsequent var creations cannot be more local.
         |
         |  If set to 0 (default) then varname is not unique, and therefore
         |  can be masked or overridden by a more local var.
____________________________________________________________________________



IV.  HPCIGETVAR Intrinsic:

Syntax:
                    CA     I32    U32V    *
      HPCIGETVAR(varname,status[,itemnum,item] [...])

Programmatically retrieve a CI variable.

"varname" follows the rules for a CI variable name.  A scope may be
embedded in varname.  If no scope is stated varname is searched for
starting in the most local scope until it is found.

If varname contains an embedded scope and item 20 is passed the embedded
scope takes precedence and a warning is returned.

One new item pair has been added:


  item      description / value
____________________________________________________________________________
    20   |  defines the scope for varname retrieval
         |
         |   0    - default scoping (same as not passing item 20)
         |   10   - private scope
         |   20   - job scope
         |   30   - account scope   - ACD access control in affect
         |   40   - global scope    - ACD access control in affect
_________|__________________________________________________________________


X.   HPCIDELETEVAR Intrinsic:

Syntax:
                       CA     I32     I32
      HPCIDELETEVAR(varname,status [,scope]);

Programmatically deletes a CI variable.

"varname" follows the rules for a CI variable name.  A scope may be
embedded in varname.  If no scope is stated varname is searched for
starting in the most local scope until it is found.

If varname contains an embedded scope and the scope parms is passed,
the embedded scope takes precedence and a warning is returned.

The new "scope" parm has been added to this intrinsic.  If the scope parm
is omitted (as it is on all existing calls) or set to DEFAULT_SCOPE then
varname is resolved as described many times above, and if found, is
deleted.

Valid scope values are:
     0    - default scoping (same as not passing the scope parm)
     10   - private scope
     20   - job scope
     30   - account scope
     40   - global scope


VIII. "REFPARM" or "VARPARM":     ********* OPPERTUNISTIC !! ************

The idea here is to define a new parm type whose actual argument is
the name of an unscoped var.  The formal REFPARM name can be assigned
to normally throught the script, and the REFPARM name can be passed to
nested scripts.  This is the "pass-by-reference" method of Pascal and
other languages.  The main benefit is that the called script can set
the caller's private vars, rather than setting job/session vars.  This
allows private vars to be modified by nested scripts, which is the only
way a private var can be altered outside of the creating script.

Note: assigning values to the REFPARM is done like any other var, eg.
           setvar refparm_a, value      # sets private var in caller
      It defeats the purpose if the called script assigns values to an
      explicitly dereferenced refparm, eg.
           setvar !refparm_a, value     # creates JOB var - can do this today

Example:

Consider the script named XYZ:
   PARM p1
   REFPARM r1, r2=""    # the default is the name of the callers var to set,
                          "" means "parm not passed"
   setvar p1,0          # set parameter P1 to 0
   setvar r1,1          # set var that R1 "points to" to 1
   setvar !r1,2         # error if R1 not a valid varname, else sets passed
                        #  varname in JOB scope - as today.

Now call xyz:
   :xyz 100 abc         # caller's PRIVATE abc var set to 1 by xyz
   :xyz 10              # no REFPARM passed - xyz can't affect caller

********* THE ABOVE REFPARM FEATURE IS OPPERTUNISTIC ************


----------------------------------------------------------------------------
Appendix A.
----------------------------------------------------------------------------

A variable name may contain the scope used to reference the var.  This
applies to LHS and RHS vars in any expression or var assignment.

Syntax (see Appendix F for possible expansion to the varname syntax):
   [scope:]varname

where scope is:
   global  | g,
   account | acct | a,
   jobses  | job | j,
   private | p.
   @

The "@" scope is for commands that support retrieving a var from all
scopes.  "@" is not real wildcarding -- it in a symbol used to indicate
"all".  Currently, SHOWVAR is the only command supporting "@" scoping.


================ QUESTION =================
 Should the JOB scope be named USER instead, with "u:" as the
 abbreviation?
============================================

For commands that support wildcarding, like SHOWVAR and DELETEVAR the
embedded scope applies to all vars that match the pattern.  Eg.
    showvar acct:a_@
displays all acct vars beginning with "A_".

For commands that support a list of vars, like SHOWVAR and DELETEVAR, the
embedded scope pertains only to the var immediately right of the scope. Eg.
    deletevar acct:a1, a2, a3
deletes the account var A1, but the "acct" scope does not transfer to A2 or
A3.

This "qualified" var name can be used everywhere a var is used today
EXCEPT in explicit dereferencing (!varname).  This exception is
necessary for backwards compatibility.  Consider:
   setvar acct "SYS"
   echo !acct:foo

In a script today you would see:
   SYS:foo

If we were to allow the scope in an explicit reference then
   echo !acct:foo
would return an error since FOO does not exist in the ACCT scope.

To substitute the contents of an explictly scoped var you need to enclose
the var name in square brackets:
  setvar acct:foo, 0
  echo ![acct:foo]
  0

Remember, the var name resolution rules will resolve the ACCT scoped
FOO if there is not a more locally scoped FOO, so you can still do
  echo !foo
and see the account FOO value as long as a more local FOO doesn't exist.


----------------------------------------------------------------------------
Appendix B.
----------------------------------------------------------------------------

PROPOSED IMPLEMENTATION:

              / (root)
              |\____________________________________________________ ...
              |                                     \               \
           hpvars (directory)                       ACCT1          ACCT2
           ------                                   /               |
      ____/    \ \_____________                  hpvars           hpvars
     /          \__            \                  / |              / |
  ACCT1          ACCT2        global             I  J             I  J
(symlink to      (symlink     |  | \
/ACCT1/hpbvars)    to         G1 I HPSUSAN ...
                /ACCT2/hpvars)


The above diagram shows a new directory directly under root named "hpvars"
(lowercase). Under hpvars are "account" symbolic links and a directory named
"global". The symbolic link has the same name as the account of the user
creating the first account level var for his/here account.  Each "acct"
link points to the hpvars directory under the real account. So if four
accounts are using account vars, there will be 4 symbolic links under
/hpvars and there will be 4 additional hpvars directories -- one directly
under each of the 4 account names in the directory.  The /ACCT/hpvars
directory permits any AM within the account the ability to create account
level vars.  It also places all of the disk space used by acct vars
under the account using them.  The value of the symbolic link under
/hpdirs is that the SM can manage all global vars in one location --
under the /hpvars directory.

Under the /hpvars/global, /ACCT1/hpvars and /ACCT2/hpvars are files.
The name of the file is the name of the variable, so we have account
variables named I and J for the account "ACCT1", and I and J for "ACCT2".
We also have global vars G1, I and HPSUSAN.

DEFAULT ACDs:

[ Note: ACDs are ignored for an SM user, meaning SM has no restrictions.
        ACD subjects are real user.acct names (with wildcarding) but are
        *not* capability based, ie. you cannot say all GL users can do this.
        Also, the CI will create one of the above directories, if it does
        not exist, with the below default ACD.  If the directory exists it
        is used as-is.  Individual "var files" inherit the ACD of their
        parent directory (I hope - depends on effort!!)
]

The default ACD for the hpvars directory is:
   TD:@.@; RD,CD,DD:manager.sys

This means that anyone can "pass thru" or traverse (TD) hpdirs as long as
they know the name below it (ie. a LISTFILE /hpvars/@ would fail for an
ordinary user, but a LISTFILE /hpvars/global/@ would work).  Only MANAGER.SYS
can read the contents of hpvars (RD). And only MANAGER.SYS can create or
delete entries (CD,DD) directly under hpvars. This means that the CI will
need to be privileged when it creates the "ACCTname" symlink under hpdirs.
Also since root (/) allows no one except SM to create an entry in it, the CI
will special case the first-time creation of hpvars.

The default ACD for each /ACCTname/hpvars directory is:
   RD,TD:@.acct; CD,DD:$owner

This technically means that only the user ID who creates the *first* account
level var is permitted to delete any acct var, or to create additional acct
vars.  But since the directory is under an account, AM users have the
ability to also create and delete account vars (files) under this
directory.  Any account member may see the list of vars in their account
(RD).  Any account member may reach a var file below the "account" dir (TD).

The default ACD for the "global" directory is:
   RD,TD:@.@; CD,DD:manager.sys

This means that anyone can read the name of all global vars (RD) and can
traverse through this directory (TD).  Only MANAGER.SYS can create new or
delete old global vars.

The default ACD for an individual var (file) is the parent's ACD:
So, assuming the directory ACDs above, global vars would have this ACD:
   R,RACD:@.@; W:manager.sys

And account vars would have this ACD:
   R,RACD:@.@; W:$owner  (AM has all access to all acct vars in her account)

Under these *default* ACDs, CI var user's access is restricted as follows:
-  SM can create, delete, read, write any global and account var
-  AM can create an account var
-  AM has no acct access outside of his/her account
-  Account members can read all account vars in their account
-  Account members can execute SHOWVAR ;ACCT and see all of their acct vars
-  Ordinary account members cannot create, delete or modify their acct vars
-  Ordinary users can read all global vars
-  Ordinary users can do a SHOWVAR ;GLOBAL and see all global vars
-  Ordinary users cannot create, write or delete global vars.


----------------------------------------------------------------------------
Appendix C.
----------------------------------------------------------------------------

UNIQUE GLOBAL VARS:

Since the "natural" variable dereferencing hierarchy is to look for
private vars before more globally scoped vars, it is possible for a more
local var to mask or hide a more global var.  This is desireable because
you may want the global var to be used as a default value and it is ok
for someone to override this global default.  However there are times
when you want the global var to be referenced, not a more local var of the
same name. This is not for security concerns as much as it helps makes
scripts more predictable.  This "unique" restriction becomes increasingly
important when we start migrating some of the predefined job/sess vars
(like HPSUSAN) to be global vars, and when customers start utilizing
global vars for critical functions.

There are two ways to solve this problem:
1) provide a directive that says "this is the scope to fetch the var at", eg.
     if g:foo = 1 then ...
     echo The global var is ![g.foo]

2) provide a means to prevent a more locally scoped var from being created
   in the first place.

Both 1 and 2 solve the problem, however, users will be able to mask or
hide vars once this functionality is released, and before vendors have been
able to take advantage of a embedding the scope in their varnames.  Thus,
as minimal functionality we need to provide number 2.  The preferred method
is to add ";unique" to the SETVAR command.

When trying to create a ";unique" var, if a var of the same name already
exists at a scope more local than the desired scope then the var is not
created and an error is returned.  Once a ";unique" var is created, no vars
of the same name in a more local scope may be created.

An interesting problem arises when you execute a script with a formal
parameter that has the same name as a ";unique" var.  Assume the formal
parm name is HPSUSAN and we have migrated the real HPSUSAN to be a true
global unique var.  When the script references !hpsusan they will be
referring to the parm, and the caller could pass in any value for the
hpsusan parm.  Of course, ![g:hpsusan] would get the global value.

========================= QUESTION =========================
Is it ok to have a formal parm name the same as any ";unique" var?
Or, if this is attempted should it be an error?
If we disallow this (thus 100% supporting the concept of "unique") we
could make it difficult to use ";unique" vars since there could be
hundreds of scripts using thousands of parms, whose name may collide
with the newly create ";unique" var.
PLEASE CONSIDER THIS QUESION CAREFULLY.
============================================================


----------------------------------------------------------------------------
Appendix D.  Examples:
----------------------------------------------------------------------------

Here are fragments of an sample script showing the scopes used for var
referencing:

  PARM p1=1                      # P1 is parm (treated like private var)
  OPTION VARSCOPE=private        # all non-scoped setvars are private.

  setvar hpmsgfence,2            # create private hpmsgfence (varscope=!)
  setvar p:hpmsgfence,2          # ditto
  setvar global:g0, 0;unique     # create global unique G0 var = 0.
  setvar g:g1 "abc"              # global G1 = "abc"
  setvar g:g2 j1                 # global G2 assigned value of private or
                                   job scoped J1
  setvar g.g3 job:j1             # global G3 assigned jobses J1
  input global:g4                # read $stdin into global G4
  if setvar(global:g0,g0+1)      # reads global G0 (remember ;unique), adds 1
                                   to it and stores result in global G0.
                                   Absence of the global:g0 would cause a
                                   private g0 to be created but this would get
                                   an error due to initial ;unique above
  if setvar(g:g0,g:g0+1)         # ditto - g:g0 on RHS unnecessary
  setvar foo global:g3           # sets private foo to global G3 (remember
                                   option varscope=private)
  setvar job:foo foo             # sets jobses foo to private foo from above
  setvar p:foo global:g0         # the p: and global: both unnecessary since
                                 # g0 is unique and private foo exists
  setvar foo g0                  # same effect as above.
  if setvar(reply,input())       # creates private reply var
  unknown_cmd                    # sets **private** CIERROR to 975
  if cierror <> 0                # tests private CIERROR.
  setvar j:cierror cierror       # sets jobses CIERROR to private cierror
  run pgm                        # 7 yr old pgm does a HPCIPUTVAR("pgmvar")
                                 # Since pgmvar doesn't exist HPCIPUTVAR will
                                 # create it in the JOB scope.
  if pgmvar = 1                  # tests jobses pgmvar set above.
  setvar p:pgmvar,0              # create local pgmvar (JOB pgmvar exists too)
  run pgm                        # re-run program with same result.  The
                                 # private pgmvar does not affect PGM.
  if pgmvar = 2 then             # tests the JOB var
  setvar p1 2                    # modified parm P1 to 2 *** NOTE *** this is
                                   not compatible...is this OK?????????
  calc 1+3                       # sets private HPRESULT



----------------------------------------------------------------------------
Appendix E.
----------------------------------------------------------------------------

Using the SYSSTART File:

PROGEN code will be enhanced to directly support the PURGEDIR command
from within SYSSTART.PUB.SYS.  We will consider direct support of
SETVAR too so that unique global vars can be created.  One possible
problem here is that a full-flege CI expression with possibly an
input() function could be used, and that probably won't work.

To make all of your system's global vars "disappear" after a reboot
you could add this command to sysstart:

      PURGEDIR /hpvars/global/; noconfirm

This will delete the global directory and all files (vars) under it.

To delete all account vars (not global vars) before the system is
up you can add this command to sysstart:

      PURGEDIR /hpvars/[A-Z]@/@/; noconfirm

The above syntax relies on the fact that the name for the links pointing
to all the acct vars are named after the account, and all account names
are uppercase.

To delete all global and acct vars (and use the CI default ACDs when
new global and acct vars are created again):

     PURGEDIR /hpvars/; noconfirm


----------------------------------------------------------------------------
Appendix F.
----------------------------------------------------------------------------

Here is the full syntax for a future CI variable name (note that some
of the features may never be implemented):

     [//nodename/][scope:]VARNAME[[index]][.field]

where nodename is the domain name (or ??) of an established remote
3000 to 3000 connection.

where "scope" is: global  | g
                  account | acct | a
                  jobses  | job  | j
                  private | p
                  file    | f*
                  @

The "@" scope is for commands that support retrieving a var from all
scopes.  "@" is not real wildcarding -- it in a symbol used to indicate
"all".  Currently, SHOWVAR is the only command supporting "@" scoping.

where "index" is an array index into varname.

where "field" is the name of a field (offset) in a varname structure.

* The FILE scope allows the CI to access an arbitrary file (the name of the
var is the name of the file in MPE or POSIX syntax).  When FILE is used
then "index" becomes the record number of the file and "field" is an
offset into that record.


If these ideas are good and important let us know!


----------------------------------------------------------------------------
Appendix F.
----------------------------------------------------------------------------

================= QUESTION ===================
* Possibly a more intuitive name for job/session vars is "user",
  since the user (and all processes run by the user) has full access
  to all of these vars.

================= QUESTION ===================
Is it acceptable to treat all parms like private vars?  Specifically,
is it ok to refer to a parm as:
   if parm = "abc" then ...  ?
Is it ok to modify a parm, like:
   setvar parm1, value
Noting that this can break scripts that rely on creating a JOB
var with the same name as a parm.

================= QUESTION ===================
If a script has a formal parm of the same name as a ";UNIQUE" variable
(could be global, acct or job) is it ok to execute this script?  As
a more extreme example, assume that we have migrated HPSUSAN from today's
JOB scope to be a true global and ;unique var.  Assume a script has a
formal parm named HPSUSAN.  I can pass this script vany value for its
HPSUSAN parm.  Is this ok?

================= QUESTION ===================
What does SHOWVAR <no argument> mean? (today we show all non-predefined vars).
- Should it mean the same with scoping?  If so, how do we distinguish var FOO
which may be listed 4 times (once per possible scope).
- Another interpretation is "show all vars I created", which again could
span many scopes.  However, this interpretation would less likely show
many acct or global vars (unless the user created them??).
- A third possibility is "show job/session vars I created" (which is literally
what is done today), meaning an implied jobses: scope.

Follow on questions: does this behavior ("show vars I created") need a way to
be explicitly specified, like a ;USER | PREDEFINE option?  This would allow
you to use pattern matching separately from controlling the above behavior.

================= QUESTION ===================
What does SHOWVAR @  mean? (today we show all vars).
- Should it mean the same with scoping and display all vars at all scopes?
- Should it just show all vars that it would "naturally" discover using the
scoping hierarcy rules.  This means that if we show a private var FOO then
we don't display a JOB, ACCT or GLOBAL foo.
- Should the jobses scope be inferred in SHOWVAR @?

================= QUESTION ===================
What does DELETEVAR @  mean? (today we delete all deleteable vars).
- Should it mean the same with scoping and delete all "deleteable" vars at
all scopes?  This means if there was a private, job and global FOO var, all
three FOOs would be deleted.
- Should it just delete all vars that it would "naturally" discover using the
scoping hierarcy rules.  This means that if we delete a private var FOO then
we don't try to delete a JOB, ACCT or GLOBAL foo.  We still need to search
all vars in all scopes.
- Should the jobses scope be inferred in DELETEVAR @?

--

ATOM RSS1 RSS2