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]