8.5.2 The SHVBLOCK structure

All requests to manipulate the REXX variable pool are controlled
by a structure which is called SHVBLOCK, having the definition:

     typedef struct shvnode {
           struct shvnode *shvnext ;    /* ptr to next in blk in
     chain */
           RXSTRING shvname ;           /* name of variable */
           RXSTRING shvvalue ;          /* value of variable */
           ULONG shvnamelen ;   /* length of shvname.strptr */
           ULONG shvvaluelen ;  /* length of shvvalue.strptr */
           UCHAR shvcode ;      /* operation code */
           UCHAR shvret ;       /* return code */
     } SHVBLOCK ;

     typedef SHVBLOCK *PSHVBLOCK ;

The fields shvnext and shvcode are purely input, while shvret is
purely output. The rest of the fields might be input or output,
depending on the requested operation, and the value of the fields.
The significance of each field is:

     [shvnext]
          One call to RexxVariablePool() may sequentially process
          many  requests. The shvnext field links one request to
          the next in  line. The last request must have set
          shvnext to NULL. The requests are handled individually
          and thus, calling RexxVariablePool() with several
          requests is equivalent to making one call to
          RexxVariablePool() for each request.
     [shvname]
          Contains the name of the variable to operate on, as a
          RXSTRING. This field is only relevant for some requests,
          and its use may differ.
     [shvvalue]
          Contains the value of the variable to operate on as a
          RXSTRING. Like shvname, this might not be relevant for
          all  types of requests.
     [shvnamelen]
          The length of the array that shvname.strptr points to.
          This  field holds the maximum possible number of
          characters in  shvname.strptr. While shvname.strlength
          holds the number of characters that are actually in use
          (i.e. defined).
     [shvvaluelen]
          The length of the array that shvvalue.strptr points to.
          Relates to shvvalue, like shvnamelen relates to shvname.
     [shvcode]
          The code of operation; decides what type of request to
          perform. A list of all the available requests is given
          below.
     [shvret]
          A return code describing the outcome of the request.
          This code is a  bit special. The lower seven bits are
          flags which are set depending on whether some condition
          is met or not. Values above 127 are not  used in this
          field.

There is a difference between shvnamelen and  shvname.strlength.
The former is the total length of the array of characters pointed
to by shvname.strptr (if set). While the latter is the number of
these characters that are actually in use.  When a SHVBLOCK is
used to return data from RexxVariablePool(), and a pre-allocated
string space has been  supplied, both these will be used;
shvname.strlength will be set to the length of the data returned,
while shvnamelen is never changed, only read to find the maximum
number of characters that shvname can hold.

Even though shvnamelen is not really needed when shvname is used
for input, it is wise to set it to its proper value (or at least
set it to the same as shvname.strlength). The same applies for
shvvalue and shvvaluelen.

The field shvcode can take one of the following symbolic values:

     [RXSHV_DROPV]
          The variable named by the direct variable name shvname
          is dropped (i.e. becomes undefined). The fields shvvalue
          and shvvaluelen do not matter.
     [RXSHV_EXIT]
          This is used to set the return value for an external
          function or exit handler.
     [RXSHV_FETCH]
          The value of the variable named by the direct variable
          name shvname is retrieved and stored in shvvalue. If
          shvvalue.strptr is NULL, the interpreter will allocate
          sufficient space to store the value (but it is the
          responsibility of the application programmer to release
          that space). Else, the  value will be stored in the area
          allocated for shvvalue, and  shvvaluelen is taken to be
          the maximum size of that area.
     [RXSHV_NEXTV]
          This code is used to retrieve the names and values of
          all variables at the current procedure level; i.e.
          excluding variables shadowed by PROCEDURE.  The name and
          value of each variable are retrieved
          simultaneously into shvname and  shvvalue, respectively.
          Successive requests for RXSHV_NEXTV will traverse the
          interpreter's internal data structure for storing
          variables, and return a new pair of variable name and
          value for each request. Each variable that is visible in
          the current scope, is returned once and only once, but
          the order is non-deterministic.
          When all available variables in the REXX interpreter
          have already been retrieved, subsequent RXSHV_NEXTV
          requests will  set the flag RXSHV_LVAR in the shvret
          field.  There are a few restrictions. The traversal will
          be reset whenever the interpreter  resumes execution, so
          an incomplete traversal can not be continued in a later
          external function, exit handler, or subcommand handler.
          Also, any set, fetch or drop operation will reset the
          traversal.  These restrictions have been added to ensure
          that the variable pool  is static throughout one
          traversal.
     [RXSHV_PRIV]
          Retrieves some piece of information from the
          interpreter, other than a variable value, based on the
          value of the shvname field.  The value is stored in
          shvvalue as for a normal fetch. A  list of possible
          names is shown below.
     [RXSHV_SET]
          The variable named by the direct variable name shvname
          is set to the value given by shvvalue.
     [RXSHV_SYFET]
          Like RXSHV_FETCH, except that shvname is a symbolic
          variable name.
     [RXSHV_SYDRO]
          Like RXSHV_DROPV, except that shvname is a symbolic
          variable name.
     [RXSHV_SYSET]
          Like RXSHV_SET, except that  shvname is a symbolic
          variable name.

One type of request that needs some special attention is the
RXSHV_PRIV, which retrieves a kind of meta-variable.  Depending on
the value of  shvname, it returns a value in shvvalue describing
some aspect of the interpreter. For  RXSHV_PRIV the possible
values for  shvname are:

     [PARM]
          Returns the ASCII representation of the number of
          parameters to the currently active REXX procedure. This
          may not be the same value as  the built-in function
          ARG() returns, but is  the number  ArgCount in
          RexxStart().  The two might differ if a routine was
          called with trailing omitted parameters.
     [PARM.n]
          The  n must be a positive integer; and the value
          returned will be the n'th parameter at the current
          procedure level.  This  is not completely equivalent to
          the information that the built-in  function ARG()
          returns.  For parameters where  ARG() would  return the
          state omitted, the returned value is a null string,
          while for parameters where ARG() would return the state
          existing, the return value will be the parameter string
          (which may be a zero length string.
     [QUENAME]
          The name of the currently active external data queue.
          This feature has not yet been implemented in Regina,
          which always return default.
     [SOURCE]
          Returns the same string that is used in the PARSE SOURCE
          clause in REXX, at the current procedure level of
          interpretation.
     [VERSION]
          Returns the same string that is used in the PARSE
          VERSION clause in REXX.

The value returned by a variable pool request is a bit uncommon. A
return value is computed for each request, and stored in the
shvret field.  This is a one-byte field, of which the most
significant bit is never set.  A symbolic value RXSHV_OK is
defined as the value zero, and the shvret field will be equal to
this name if none if  the flags listed below is set.  The symbolic
value for these flags are:

     [RXSHV_BADF]
          The shvcode of this request contained a bad function
          code.
     [RXSHV_BADN]
          The shvname field contained a string that is not valid
          in this context. What exactly is a valid value depends
          on whether the operation is a private, a symbolic
          variable, or direct variable operation.
     [RXSHV_LVAR]
          Set if and only if the request was RXSHV_NETXV, and all
          available variables have already been retrieved by
          earlier requests.
     [RXSHV_MEMFL]
          There was not enough memory to complete this request.
     [RXSHV_NEWV]
          Set if and only if the referenced variable did not
          previously have  a value. It can be returned for any
          set, fetch or drop operation.
     [RXSHV_TRUNC]
          Set if the retrieved value was truncated when it was
          copied into either the shvname or  shvvalue  fields. See
          below.

These flags are directly suitable for logical OR, without
shifting, e.g. to check for truncation and no variables left, you
can do something like:

     if (req->shvret & (RXSHV_TRUNC | RXSHV_LVAR))
           printf("Truncation or no vars left\n") ;

RXSHV_TRUNC can only occur when the interface is storing a
retrieved value in a SHVBLOCK, and the pre-allocated space is
present, but not sufficiently large. As described for RXSHV_FETCH,
the
interpreter will allocate enough space if shvvalue.strptr is NULL,
and then RXSHV_TRUNC will never be set.  Else the space supplied
by  shvvalue.strptr is used, and  shvvaluelen is taken as the
maximum length of shvvalue, and truncation will occur if the
supplied space is too small.

Some implementations will consider SHV_MEMFL to be so severe as to
skip the rest of the operations in a chain of requests. In order
to write compatible software, you should never assume that
requests
following in a chain after a request that returned SHV_MEMFL have
been performed.

RXSHV_BADN is returned if the supplied shvname contains a value
that is not legal in this context. For the symbolic set, fetch and
drop operations, that means a symbol that is a legal variable
name; both upper and lower case letters are allowed.  For the
direct set, fetch and drop operations, that means a variable name
after normalization and tail substitution is not a legal variable
name. For RXSHV_PRIV,  it must be one of the values listed above.

There is a small subtlety in the above description. TRL states
that when a REXX assignment assigns a value to a stem variable,
all possible variables having that stem are assigned a new value
(independent of whether they had an explicit value before). So,
strictly speaking, if a stem is set, then a RXSHV_NETV sequence
should return an (almost) infinite sequence of compound variables
for that stem. Of course, that is completely useless, so you can
assume that only compound variables of that stem given an explicit
value after the stem was assigned a value will be returned by
RXSHV_NEXTV. However, because of that subtlety, the variables
returned by RXSHV_NEXTV for compound variables might not be
representative for the state of the variables.

e.g. what would a sequence of RXSHV_NEXT requests return after the
following REXX code ?:
     foo. = 'bar'
     drop foo.bar

The second statement here, might not change the returned values!
After the first statement, only the stem  foo. would probably have
been returned, and so also if all variables were fetched after the
second statement.



PREV NEXT