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