Sample for persistent variables

[Autolink] Menu

 
/* sample REXX routines to show how to use the Extended Attributes    */
/* to save persistent variables                                       */
/* The routines use Extended Attributes with the type Binary          */
/* (see also Extended Attribute Data Types and EAs used by the WPS)   */
/*                                                                    */
/* (c) 1998 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */

                    /* load REXXUTIL                                  */
  call rxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs'
  call SysLoadFuncs

                    /* init the stem with the data for the EAs        */
  configData.0 = 4

  configData.1.__key   = 'key1'
  configData.1.__value = 'value1'

  configData.2.__key   = 'key2'
  configData.2.__value = 'value2'

  configData.3.__key   = 'key3'
  configData.3.__value = 'value33'

  configData.4.__key   = 'key4'
  configData.4.__value = 'value44'


/* ------------------------------------------------------------------ */
/* in a real program, this code should be at the end of your program! */

ProgramEnd:

                    /* to write the data use:                         */
  thisRC = WriteDataToEAs()
  say 'The return code of WriteDataToEAs() is ' || thisRC

/* ------------------------------------------------------------------ */
/* in a real program, this code should be at the begin of your        */
/* program!                                                           */

ProgramStart:
                    /* to read the data use:                          */
  thisRC = ReadDataFromEAs()
  say 'The return code of ReadDataFromEAs() is ' || thisRC

exit

/* ------------------------------------------------------------------ */
/* function: Save the Data to the EAs                                 */
/*                                                                    */
/* call:     thisRC = writeDataToEAs( { fileName }, key1 {,..,key#} ) */
/*           thisRC = writeDataToEAs( { fileName }, all )             */
/*                                                                    */
/* where:    fileName                                                 */
/*             - name of the file for the EAs                         */
/*               This parameter is optional, the default is the name  */
/*               of this program.                                     */
/*                                                                    */
/*           key#                                                     */
/*             - key to write                                         */
/*               You can use as many keys as you like                 */
/*               Note that undefined keys are ignored without warning */
/*               if using one or more of this parameters!             */
/*                                                                    */
/*           all                                                      */
/*             - write all keys                                       */
/*                                                                    */
/*           The default if the second parameter is missing is 'ALL'. */
/*                                                                    */
/* returns:   0 - okay                                                */
/*            1 - routine ended with warnings                         */
/*            3 - file not found                                      */
/*           -1 - stem configData. not defined                        */
/*                                                                    */
/* Note:     WriteDataToEAs uses the data from the global stem        */
/*                                                                    */
/*              ConfigData.                                           */
/*                                                                    */
/*           The format of this stem must be:                         */
/*                                                                    */
/*              ConfigData.0 - number of elements                     */
/*                                                                    */
/*              ConfigData.#.__key    - name of the EA                */
/*                                      The key is not case-sensitive */
/*                                      blanks in keys are not        */
/*                                      possible                      */
/*              ConfigData.#.__value  - value for the EA              */
/*                                                                    */
/*                                                                    */
/*                                                                    */
/*           Routines needed:                                         */
/*             CreateBinaryEA                                         */
/*             GetProgramName (only if the first parameter is missing)*/
/*                                                                    */
/*           You must load REXXUTIL.DLL before calling this routine!  */
/*                                                                    */
WriteDataToEAS: PROCEDURE expose configData.
  parse arg thisFileName, firstKey

  thisRC = 0

                    /* check if the stem configData. is defined       */
  if datatype( configData.0 ) <> 'NUM' then
    thisRC = -1

  if thisRC = 0 then
  do
                    /* use the default for thisFileName if the        */
                    /* parameter is missing                           */
    if thisFileName = '' then
      thisFileName = GetProgramName()

                    /* check if the file exists                       */
    thisFileName = stream( thisFileName, 'c', 'QUERY EXISTS' )
    if thisFileName = '' then
      thisRC = 3

                    /* use the default for the second parameter if    */
                    /* the parameter is missing                       */
    if firstKey = '' then
      firstKey = 'ALL'

  end /* if thisRC = 0 then */

  if thisRC = 0 then
  do
     if translate( firstKey ) = 'ALL' then
     do
                    /* process all keys defined in the stem           */
                    /* configData.                                    */
       processALLKeys = 1
     end /* if translate( firstKey ) = 'ALL' then */
     else
     do
                    /* only process the keys found in the parameters  */
       processAllKeys = 0

                    /* create a string with the keys to process       */
       keysToProcess = ''
       do i = 2 to arg()
         curArg = translate( strip( arg(i) ) )

         if pos( ' ', curArg ) <> 0 then
         do
                    /* blanks are not allowed in key names            */
            say 'Warning: The keyname "' || curArg || '" is invalid!'
            thisRC = 1
            iterate
         end /* if */

         keysToProcess = keysToProcess curArg
       end /* do i = 2 to arg() */
     end /* else */

     do i = 1 to configData.0

                    /* get the current key                            */
       curKey = translate( configData.i.__key )
       if pos( ' ', curKey ) <> 0 then
       do
                    /* blanks are not allowed in key names            */
          say 'Warning: The keyname "' || curKey || '" is invalid!'
          thisRC = 1
          iterate
       end /* if */

       if processAllkeys = 0 then
       do
         if wordPos( curKey, keysToProcess ) = 0 then
           iterate
       end /* if processAllkeys = 0 then */

                    /* get the current value                          */
       curVal = configData.i.__value

                    /* convert the value to a binary EA if necessary  */
                    /* (Note: Use an empty string to delete an EA)    */
       if curVal <> '' then
         curVal = CreateBinaryEA( curVal )

                    /* write the EA                                   */
       tRC = SysPutEA( thisFilename, curKey, curVal )
       if tRC <> 0 then
       do
         say 'Warning: Error ' || tRC || ' writing the EA "' || ,
             curKey || '"!'

                    /* set the return code to "Warning"               */
         thisRC = 1
       end /* if tRC <> 0 then */
     end /* do i = 1 to configData.0 */
  end /* if thisRC = 0 then */

return thisRC

/* ------------------------------------------------------------------ */
/* function: Read the data from the EAs                               */
/*                                                                    */
/* call:     thisRC = ReadDataFromEAs( { fileName }, key1 {,..,key#} )*/
/*           thisRC = ReadDataFromEAs( { fileName }, all )            */
/*                                                                    */
/* where:    fileName                                                 */
/*             - name of the file for the EAs                         */
/*               This parameter is optional, the default is the name  */
/*               of this program.                                     */
/*                                                                    */
/*           key#                                                     */
/*             - key to write                                         */
/*               You can use as many keys as you like                 */
/*               Note that undefined keys are ignored without warning */
/*               if using one or more of this parameters!             */
/*                                                                    */
/*           all                                                      */
/*             - write all keys                                       */
/*                                                                    */
/*           The default if the second parameter is missing is 'ALL'. */
/*                                                                    */
/* returns:   0 - okay                                                */
/*            1 - routine ended with warnings                         */
/*            3 - file not found                                      */
/*           -1 - stem configData. not defined                        */
/*                                                                    */
/* Note:     WriteDataToEAs uses the data from the global stem        */
/*                                                                    */
/*              ConfigData.                                           */
/*                                                                    */
/*           The format of this stem must be:                         */
/*                                                                    */
/*              ConfigData.0 - number of elements                     */
/*                                                                    */
/*              ConfigData.#.__key    - name of the EA                */
/*                                      The key is not case-sensitive */
/*                                      blanks in keys are not        */
/*                                      possible                      */
/*              ConfigData.#.__value  - value for the EA              */
/*                                                                    */
/*                                                                    */
/*           Routines needed:                                         */
/*             GetValueFromBinaryEA                                   */
/*             GetProgramName (only if the first parameter is missing)*/
/*                                                                    */
/*           You must load REXXUTIL.DLL before calling this routine!  */
/*                                                                    */
ReadDataFromEAS: PROCEDURE expose configData.
  parse arg thisFileName, firstKey

  thisRC = 0
                    /* check if the stem configData. is defined       */
  if datatype( configData.0 ) <> 'NUM' then
    thisRC = -1

  if thisRC = 0 then
  do
                    /* use the default for thisFileName if the        */
                    /* parameter is missing                           */
    if thisFileName = '' then
      thisFileName = GetProgramName()

                    /* check if the file exists                       */
    thisFileName = stream( thisFileName, 'c', 'QUERY EXISTS' )

    if thisFileName = '' then
      thisRC = 3

                    /* use the default for the second parameter if    */
                    /* the parameter is missing                       */
    if firstKey = '' then
      firstKey = 'ALL'
  end /* if thisRC = 0 then */

  if thisRC = 0 then
  do
     if translate( firstKey ) = 'ALL' then
     do
                    /* process all keys defined in the stem           */
                    /* configData.                                    */
       processALLKeys = 1
     end /* if translate( firstKey ) = 'ALL' then */
     else
     do
                    /* only process the keys found in the parameters  */
       processAllKeys = 0

                    /* create a string with the keys to process       */
       keysToProcess = ''
       do i = 2 to arg()
         curArg = translate( strip( arg(i) ) )

         if pos( ' ', curArg ) <> 0 then
         do
                    /* blanks are not allowed in key names            */
            say 'Warning: The keyname "' || curArg || '" is invalid!'
            thisRC = 1
            iterate
         end /* if */

         keysToProcess = keysToProcess curArg
       end /* do i = 2 to arg() */
     end /* else */

     do i = 1 to configData.0
                    /* get the current key                            */
       curKey = translate( configData.i.__key )
       if pos( ' ', curKey ) <> 0 then
       do
                    /* blanks are not allowed in key names            */
          say 'Warning: The keyname "' || curKey || '" is invalid!'
          thisRC = 1
          iterate
       end /* if */

       if processAllkeys = 0 then
       do
         if wordPos( curKey, keysToProcess ) = 0 then
           iterate
       end /* if processAllkeys = 0 then */

                    /* read the EA                                    */
       tRC = SysGetEA( thisFilename, curKey, 'curVal' )
       if tRC <> 0 then
       do
         say 'Warning: Error ' || tRC || ' reading the EA "' || ,
             curKey || '"!'
                    /* set the return code to "Warning"               */
         thisRC = 1

         curVal = ''
       end /* if tRC <> 0 then */
       else
       do
         if curVal <> '' then
           curVal = GetValueFromBinaryEA( curVal )
       end /* else */

                    /* save the new value                             */
       configData.i.__value = curVal

     end /* do i = 1 to configData.0 */
  end /* if thisRC = 0 then */

return thisRC

/* ------------------------------------------------------------------ */
/* function: Delete all EAs from a file                               */
/*                                                                    */
/* call:     thisRC = DeleteEAs( fileName )                           */
/*                                                                    */
/* where:    fileName                                                 */
/*             - name of the file                                     */
/*                                                                    */
/* returns:  the return code of EAUTIL                                */
/*           (0 = okay, else error)                                   */
/*                                                                    */
/*           External programs needed:                                */
/*             EAUTIL.EXE                                             */
/*                                                                    */
/* note:     Use this routine with caution!                           */
/*                                                                    */
DeleteEAs: PROCEDURE
  parse arg FileName

  thisRC = -1
  if fileName <> '' then
  do
    '@EAUTIL ' fileName ' NUL' '/s ' '2>NUL 1>NUL'
    thisRC = rc
  end /* if */

return thisRC

/* ------------------------------------------------------------------ */
/* function: Create a binary EA                                       */
/*                                                                    */
/* call:     binaryEA = CreateBinaryEA( eaValue )                     */
/*                                                                    */
/* where:    eaValue                                                  */
/*             - value for the EA                                     */
/*                                                                    */
/* returns:  the EA in binary format                                  */
/*                                                                    */
/*           Routines needed:                                         */
/*             SwapWord                                               */
/*                                                                    */
CreateBinaryEA: PROCEDURE
  parse arg eaValue

  EAT_BINARY = SwapWord( 'FFFE'x )
  EAT_LENGTH = SwapWord( right( '00'x || '00'x  || d2c( length( eaValue ) ),2 ) )
  newEA = EAT_BINARY || EAT_LENGTH || eaValue
return newEA

/* ------------------------------------------------------------------ */
/* function: Get the value form a binary EA                           */
/*                                                                    */
/* call:     eaValue = GetValueFromBinaryEA( eaContents )             */
/*                                                                    */
/* where:    eaContents                                               */
/*             - contents of the EA                                   */
/*                                                                    */
/* returns:  the value of the EA or '' if the type of the EA is not   */
/*           binary                                                   */
/*                                                                    */
/*           Routines needed:                                         */
/*             SwapWord                                               */
/*                                                                    */
/* note:     The length saved in the EA is ignored.                   */
/*                                                                    */
GetValueFromBinaryEA: PROCEDURE
  parse arg eaContents

                    /* key for a binary EA                            */
  EAT_BINARY = SwapWord( 'FFFE'x )

                    /* split the EA value into type, length and value */
  parse var eaContents eaType +2 eaLength +2 eaValue

                    /* check the type                                 */
  if eaType <> EAT_BINARY then
    eaValue = ''

return eaValue

/* ------------------------------------------------------------------ */
/* function: Convert a hexadecimal WORD from LSB format to MSB format */
/*           and vice versa                                           */
/*                                                                    */
/* call:     SwapWord hexadecimal_word                                */
/*                                                                    */
/* where:    hexadecimal_word                                         */
/*             - input as hexadecimal word                            */
/*                                                                    */
/* output:   value in MSB format as hexadecimal word                  */
/*                                                                    */
SwapWord: PROCEDURE
 RETURN strip( translate( "12", arg(1), "21" ) )

/* ------------------------------------------------------------------ */
/* function: Get the name of this program                             */
/*                                                                    */
/* call:     progName = GetProgramName()                              */
/*                                                                    */
/* where:    -                                                        */
/*                                                                    */
/* returns:  the fully qualified name of this program                 */
/*                                                                    */
/* Note:     This routine returns '' for REXX programs in the         */
/*           macro space                                              */
/*                                                                    */
GetProgramName: PROCEDURE
   parse source . . progName

   if pos( '\', progName ) = 0 then
      progName = ''
return progName


[Back: Copy the Queue into a compound variable]
[Next: Using REXX queues for global variables]