File RXVARP.TXT                                  Ch. d'H. Sept. 28, 1993
Copyright (C) 1992 Inventec Informatik AG
All rights reserved.



RXVARP  -  Variable Pool Interface for REXX
===========================================

The dynamic link library RXVARP.DLL provides variable pool
functions to an OS/2 REXX program. Variable pools with RPC
(remote procedure call) access can be used for inter-process
communication between REXX programs running on different computers
in a network. Variable pools can also be used to pass values
from a REXX main program to a REXX sub-program, and from the sub-
program back to the main program.



Registering the DLL with REXX
-----------------------------

Before the DLL can be used, it must be registered with the REXX
interpreter. The following REXX statements can be used to register
the DLL:

   if rxfuncquery("RXVARP")<>0 then do
      rc = rxfuncadd("RXVARP","RXVARP","RXVARP")
      if rc <> 0 then call abend "rxfuncadd of RXVARP failed, RC="rc
      end

If the file RXVARP.DLL is not in the current directory or in the
LIBPATH, the complete path name must be included.

Refer to RXDLLOS2.TXT for additional information about using this
DLL with REXX.



The <rxvarp> function
---------------------

The DLL is called through the external REXX routine with the same
name, <rxvarp>.

The <rxvarp> routine can be called as a function or as a routine.
Example to call <rxvarp> as a function:
   result = rxvarp(statement)
Example to call <rxvarp> as a routine:
   call rxvarp statement

The <rxvarp> routine has a single argument <statement> and returns
the value <result>. <result> contains either an empty string (if no
error has occured) or an error code character followed by an error
message.

<result> must be tested after each call to <rxvarp>. If <result> is
not empty and no error processing is done by the REXX program, an
error exit routine (i.e. <abend>) should be called.
Example:
   call rxvarp statement
   if result <> "" then call abend "rxvarp failed," result

The first character of <result> can be used to identify certain
error conditions.
Example:
   call rxvarp "get_var varp_handle=vp1 var_name=var1"
   select
      when result="" then nop /* no error */
      when left(result,1)="N" then
         call abend "variable var1 does not exist in variable pool"
      otherwise call abend "rxvarp failed," result
      end



Statements that can be passed to <rxvarp>
----------------------------------------

The following statements can be passed as parameters to <rxvarp>:

   open         open a variable pool
   close        close a variable pool
   get_var      get a variable
   set_var      set a variable
   delete_var   delete a variable

Before a variable pool can be used, it must be opened though
<open>. <Open> returns a variable pool handle that is used to
identify the variable pool with further statements. The variable
pool handle can be passed to REXX sub-programs that needs to
access the variable pool.

When access to a variable pool is no longer needed, <close>
should be executed to release the internal buffer space allocated
to the variable pool. After <close> has been executed, the
variable pool handle is no longer valid.



Notes to the statement syntax and parameters
--------------------------------------------

- The statements have parameters in the form "keyword=value".
  These keyword parameters can appear in any order.
- Most parameters have default values that will be assumed when
  the parameter is not specified.
- A parameter value must be enclosed in single or double quotes if
  it contains blanks or special characters or if it is an empty
  string.
- Keywords names are case-independent. They can be written in
  uppercase, lowercase or mixed-case characters.
- Boolean output values are returned according to REXX conventions
  as 1 for <true> or 0 for <false>.
  Boolean input parameters can be 1, "TRUE" or "YES" for <true>,
  or 0, "FALSE" or "NO" for <false> (case-independent).

The following sections describe each statement in detail.



Statement:  open  -  open a variable pool
-----------------------------------------

<open> opens a variable pool. It provides a variable pool handle
that can be used to further identify the variable pool. When the
variable pool is no longer needed, <close> should be called.

Syntax:
   open type=id rpc_port_name=id rpc_comp_name=id rpc_method=id
         high_prio=boolean varp_handle_var=rexxx_var_name

Parameters:
   type  -  variable pool type
      <type> can have the following values:
         "local":
            A local variable pool is created that cannot be
            accessed by threads outside the current processes.
         "rpc_server":
            A variable pool is created that can be accessed by
            other processes through RPC (remote procedure calls).
         "rpc_client":
            An existing remote variable pool is accessed through
            RPC calls. The remote variable pool can reside in the
            current process, in another process on the current
            computer, or in a process on another computer in the
            network.
      Default value for <type> is "local".
   rpc_port_name  -  RPC port name
      <rpc_port_name> specifies the RPC port name associated with
      the variable pool. This parameter is only used if <type> is
      "rpc_server" or "rpc_client".
   rpc_comp_name  -  RPC computer name
      <rpc_comp_name> is used if <type> is "rpc_client" to
      specify the name of the computer where the remote variable
      pool resides. An empty string for <rpc_comp_name> can be
      used to designate the current computer.
      The default value for <rpc_comp_name> is the empty string.
      Refer to RXRPCINF.TXT for additional information.
   rpc_method  -  RPC method
      <rpc_method> specifies the RPC method to be used. This
      parameter is only used if <type> is "rpc_server" or
      "rpc_client". The default value for this parameter is
      operating system dependent.
      If <type> is "rpc_server", <rpc_method> can contain a list
      of RPC methods, separated by blanks.
      Refer to RXRPCINF.TXT for additional information.
   high_prio  -  1 for high priority thread
      <high_prio> can be used if <type> is "rpc_server".
      If <high_prio> is 1, the internal thread that processes the
      RPC requests is given a high priority.
      Default value for <high_prio> is 0,
   varp_handle_var  -  name of REXX variable for variable pool handle
      <varp_handle_var> specifies the name of a REXX variable
      where the variable pool handle will be stored. The variable
      pool handle is an integer number that is used to uniquely
      identify the variable pool. It can be used by all threads
      within the current process.

Example:
   call rxvarp "open type=rpc_server rpc_port_name=test_vp",
         "varp_handle_var=vp1"
   if result <> "" then call abend result
   say "the variable pool handle is" vp1



Statement:  close  -  close a variable pool
-------------------------------------------

<close> closes a variable pool. This releases internal memory
blocks that are allocated with the variable pool. After <close>
has been executed, the variable pool handle is no longer valid
and must not be used any more.

Syntax:
   close varp_handle=nr

Parameters:
   varp_handle  -  variable pool handle
      <varp_handle> is the variable pool handle associated with the
      variable pool to be closed.

Example:
   call rxvarp "close varp_handle="vp1
   if result <> "" then call abend result



Statement:  get_var  -  get a variable
--------------------------------------

<get_var> is used to get the value of a variable in the variable
pool. If a variable with the specified name does not exist in the
variable pool, the REXX variable designated by <var_value_var> is
set to the empty string and <result> returns the error code "N"
followed by an error message.

Syntax:
   get_var varp_handle=nr var_name=id var_value_var=rexx_var_name

Parameters:
   varp_handle  -  variable pool handle
      <varp_handle> is the handle associated with the variable pool.
   var_name  -  variable name
      <var_name> specifies the name of a variable in the variable
      pool whose value is requested. Pool variable names are case
      independent.
   var_value_var  -  name of REXX variable for variable value
      <var_value_var> specifies the name of a REXX variable where
      the value of the pool variable is to be stored.
      The default value for <var_value_var> is the variable name
      specified with the <var_name> parameter.

Error codes:
   The following error conditions can be intercepted by testing
   <left(result,1)>:
      "N"  -  variable does not exist
         The variable does not exist in the variable pool.

Example:
   call rxvarp "get_var varp_handle="vp1 "var_name=var1"
   select
      when result = "" then
         say "the value of <var1> is:" var1
      when left(result,1) = "N" then
         say "<var1> does not exist in the variable pool"
      otherwise call abend result
      end



Statement:  set_var  -  set a variable
--------------------------------------

<set_var> is used to set a variable in the variable pool. If the
variable already exists, it's value is replaced.

Syntax:
   set_var varp_handle=nr var_name=id var_value_var=rexx_var_name

Parameters:
   varp_handle  -  variable pool handle
      <varp_handle> is the handle associated with the variable pool.
   var_name  -  variable name
      <var_name> specifies the name of a variable in the variable
      pool whose value is set.
   var_value_var  -  name of REXX variable containing the var value
      <var_value_var> specifies the name of a REXX variable that
      contains the new value for the pool variable.
      The default value for <var_value_var> is the variable name
      specified with the <var_name> parameter.

Example:
   var1 = "Hello"
   call rxvarp "set_var varp_handle="vp1 "var_name=var1"
   if result <> "" then call abend result



Statement:  delete_var  -  delete a variable
--------------------------------------------

<delete_var> deletes a variable in the variable pool.
If the variable does not exist, the statement is ignored (no
error message is returned).

Syntax:
   delete_var varp_handle=nr var_name=id

Parameters:
   varp_handle  -  variable pool handle
      <varp_handle> is the handle associated with the variable pool.
   var_name  -  variable name
      <var_name> specifies the name of a pool variable to be
      deleted.

Example:
   call rxvarp "delete_var varp_handle="vp1 "var_name=var1"
   if result <> "" then call abend result



Sample program SAMPVP1.CMD  -  "rpc_server" variable pool
---------------------------------------------------------

/* SAMPVP1.CMD  -  sample program for RXVARP.DLL                       */

/* This program creates a variable pool of type rpc_server.            */
/* SAMPVP2.CMD can be used to access the variable pool as a client.    */

signal on failure name rexx_exception
signal on novalue name rexx_exception

parse source os . mod_name
select
   when os = "OS/2" then do
      "@echo off"
      parse arg mode main_parms
      if mode <> "INDIRECT" then do
         "cmd /c" mod_name "INDIRECT" arg(1); exit rc; end
      end
   otherwise parse arg main_parms
   end

vp1_rpc_port_name = "SAMPVP1"

call init
call main
return

main:
   call rxvarp "open type=rpc_server rpc_port_name="vp1_rpc_port_name,
         "varp_handle_var=vp1"
   if result <> "" then call abend result
   var1 = "original contents of var1"
   call rxvarp "set_var varp_handle="vp1 "var_name=var1"
   if result <> "" then call abend result
   call charout,"Run SAMPVP2.CMD in another session",
         " and then press ENTER - "
   call linein
   call rxvarp "get_var varp_handle="vp1 "var_name=var1"
   if result <> "" then call abend result
   say "The contents of var1 is:" var1
   call rxvarp "close varp_handle="vp1
   if result <> "" then call abend result
   return

init:
   if rxfuncquery("RXVARP")<>0 then do
      rc = rxfuncadd("RXVARP","RXVARP","RXVARP")
      if rc <> 0 then call abend "rxfuncadd of RXVARP failed, RC="rc
      end
   return

/*--- exit routines ---------------------------------------------------*/

rexx_exception:
   parse source . . mod_name
   call error_exit 'REXX' condition('C') 'exception in module' mod_name,
         'line' sigl', statement = "'sourceline(sigl)'"'

abend:
   parse arg err_msg
   parse source . . mod_name
   s = 'Error in module' mod_name 'line' sigl
   if err_msg <> '' then s = s',' err_msg
   call error_exit s

error_exit:
   parse arg err_msg
   if err_msg <> '' then say err_msg
   exit 99



Sample program SAMPVP2.CMD  -  "rpc_client" variable pool
---------------------------------------------------------

/* SAMPVP2.CMD  -  sample program for RXVARP.DLL                       */

/* This program is used in conjunction with SAMPVP1.CMD to access the  */
/* variable pool that SAMPVP1 has created.                             */

signal on failure name rexx_exception
signal on novalue name rexx_exception

parse source os . mod_name
select
   when os = "OS/2" then do
      "@echo off"
      parse arg mode main_parms
      if mode <> "INDIRECT" then do
         "cmd /c" mod_name "INDIRECT" arg(1); exit rc; end
      end
   otherwise parse arg main_parms
   end

vp1_rpc_port_name = "SAMPVP1"
vp1_rpc_comp_name = ""                /* current computer */

call init
call main
return

main:
   call rxvarp "open type=rpc_client rpc_port_name="vp1_rpc_port_name,
         "rpc_comp_name='"vp1_rpc_comp_name"' varp_handle_var=vp1"
   if result <> "" then call abend result
   call rxvarp "get_var varp_handle="vp1 "var_name=var1"
   if result <> "" then call abend result
   say "The old contents of var1 is:" var1
   var1 = "modified var1 contents"
   call rxvarp "set_var varp_handle="vp1 "var_name=var1"
   if result <> "" then call abend result
   say "var1 modified"
   call rxvarp "close varp_handle="vp1
   if result <> "" then call abend result
   return

init:
   if rxfuncquery("RXVARP")<>0 then do
      rc = rxfuncadd("RXVARP","RXVARP","RXVARP")
      if rc <> 0 then call abend "rxfuncadd of RXVARP failed, RC="rc
      end
   return

/*--- exit routines ---------------------------------------------------*/

rexx_exception:
   parse source . . mod_name
   call error_exit 'REXX' condition('C') 'exception in module' mod_name,
         'line' sigl', statement = "'sourceline(sigl)'"'

abend:
   parse arg err_msg
   parse source . . mod_name
   s = 'Error in module' mod_name 'line' sigl
   if err_msg <> '' then s = s',' err_msg
   call error_exit s

error_exit:
   parse arg err_msg
   if err_msg <> '' then say err_msg
   exit 99
