home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
vxtech07.zip
/
RXAWAR
/
VARPOOL
/
C
/
VARPOOL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-05
|
12KB
|
421 lines
/*
* varpool.c -- Routines to fetch, set and drop REXX variables. You can
* call these routines whenever the REXX interpreter calls
* your program (in an external function, a subcommand
* handler, or a system exit).
*
* Notes on accessing the variable pool:
* -------------------------------------
*
* All accesses to the variable pool are done by filling in one or
* more (you can link them together into a list) SHVBLOCK structures
* (defined in rexxsaa.h) and then passing the block(s) to the
* interpreter by calling the RexxVariablePool function. The interpreter
* will then scan each SHVBLOCK, fulfill the request if it can, and
* then store the result back into the structure.
*
* There is NO function you can call to get a list of all variables,
* or all variables that start with a certain stem, etc. You CAN traverse
* the variable pool one item at a time, which is the only way to get
* all the variables.
*
* The functions below all work on a single variable at a time, but you
* can easily expand them to work with multiple variables. You might
* want to get a complete stem array (foo.0, foo.1, foo.2, ...) in a
* single pass.
*
* WATCH OUT FOR MEMORY LEAKS! If you let the variable pool allocate
* buffers for you, be sure to free them...
*/
#define INCL_REXXSAA
#include <os2.h>
#include <rexxsaa.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include "varpool.h"
/*
* VarFetchValue -- Fetch a single value from the variable pool. You can
* pass the name of a simple symbol, or a complex
* one. The return code indicates whether the function
* was successful: RXSHV_OK indicates total success,
* RXSHV_TRUNC indicates partial success (the value
* of the variable was too long to fit in the given
* space and was truncated), anything else is an error.
*
* If the RXSTRING you pass in has its strptr field set
* to NULL, the variable pool will allocate memory
* for you using DosAllocMem. Otherwise it will use
* the memory you provide, so set the strlength field
* accordingly.
*
* Sample usage:
*
* RXSTRING value;
* char buf[256];
*
* value.strlength = 256;
* value.strptr = buf;
*
* if( VarFetchValue( "A.B.C", &value ) == RXSHV_OK ){
* ........
* }
*
*
* value.strlength = 0
* value.strptr = NULL;
*
* if( VarFetchValue( "FOO", &value ) == RXSHV_OK ){
* ........
*
* if( value.strptr )
* DosFreeMem( value.strptr );
* }
*
*/
LONG VarFetchValue( PSZ name, PRXSTRING value )
{
SHVBLOCK shv;
PSZ varname;
ULONG len;
if( !name ) goto leave;
/* Copy name and uppercase it... */
len = strlen( name );
varname = alloca( len + 1 );
if( varname == NULL ) goto leave;
strcpy( varname, name );
strupr( varname );
/* Fill in a FETCH request.... */
shv.shvnext = NULL;
shv.shvname.strptr = varname;
shv.shvname.strlength = len;
shv.shvvalue.strptr = value->strptr;
shv.shvvalue.strlength = value->strlength;
shv.shvvaluelen = value->strlength;
shv.shvcode = RXSHV_FETCH;
/* Fetch it and set the return values accordingly... */
RexxVariablePool( &shv );
if( shv.shvret == RXSHV_OK || shv.shvret == RXSHV_TRUNC ){
value->strptr = shv.shvvalue.strptr;
value->strlength = shv.shvvaluelen;
}
return( shv.shvret );
leave:
return( -1 );
}
/*
* VarFetchStemValue -- This function is similar to VarFetchValue, except
* that it is useful in fetching a stem array
* (i.e., foo.0, foo.1, foo.2, etc.). You could
* actually do it by calling VarFetchValue for
* "foo.0", "foo.1", etc., but this function makes
* it easier.
*
* Sample usage (no error checking):
*
* RXSTRING value;
* char buf[256];
* ULONG count, i;
*
* value.strlength = 256;
* value.strptr = buf;
*
* VarFetchStemValue( "foo", 0, &value );
*
* count = strtoul( buf, NULL, 10 );
*
* for( i = 1; i <= count; ++i ){
* value.strlength = 256;
* value.strptr = buf;
*
* VarFetchStemValue( "foo", i, &value );
*
* .....
* }
*
*/
LONG VarFetchStemValue( PSZ stem, USHORT count, PRXSTRING value )
{
SHVBLOCK shv;
PSZ varbuf;
USHORT varlen;
if( !stem ) goto leave;
/* Convert to uppercase, make sure there's enough room for a ULONG
value, and add a '.' if necessary */
varlen = strlen( stem );
varbuf = alloca( varlen + 12 );
if( varbuf == NULL ) goto leave;
strcpy( varbuf, stem );
strupr( varbuf );
if( varbuf[ varlen - 1 ] != '.' ){
varbuf[ varlen ] = '.';
varlen++;
}
/* Convert the index */
sprintf( &varbuf[ varlen ], "%d", count );
/* Request the value... */
shv.shvnext = NULL;
shv.shvname.strptr = varbuf;
shv.shvname.strlength = strlen( varbuf );
shv.shvvalue.strptr = value->strptr;
shv.shvvalue.strlength = value->strlength;
shv.shvvaluelen = value->strlength;
shv.shvcode = RXSHV_FETCH;
RexxVariablePool( &shv );
if( shv.shvret == RXSHV_OK || shv.shvret == RXSHV_TRUNC ){
value->strptr = shv.shvvalue.strptr;
value->strlength = shv.shvvaluelen;
}
return( shv.shvret );
leave:
return( -1 );
}
/*
* VarSetValue -- Sets the value of a variable. Just pass it the name
* of the variable (i.e., "FOO", "A.B") and a value and
* it will set it. Returns RXSHV_OK or RXSHV_NEWV if
* successful.
*
* Sample usage:
*
* RXSTRING value;
*
* value.strptr = "This is a test"
* value.strlength = strlen( value.strptr );
*
* VarSetValue( "FOO", &value );
*/
LONG VarSetValue( PSZ name, PRXSTRING value )
{
SHVBLOCK shv;
PSZ varname;
ULONG len;
if( !name ) goto leave;
len = strlen( name );
varname = alloca( len + 1 );
if( varname == NULL ) goto leave;
strcpy( varname, name );
strupr( varname );
shv.shvnext = NULL;
shv.shvname.strptr = varname;
shv.shvname.strlength = len;
shv.shvvalue.strptr = value->strptr;
shv.shvvalue.strlength = value->strlength;
shv.shvvaluelen = value->strlength;
shv.shvcode = RXSHV_SET;
RexxVariablePool( &shv );
return( shv.shvret );
leave:
return( -1 );
}
/*
* VarSetStemValue -- Like VarSetValue, but lets you set the values
* of a stem array.
*
* Sample usage:
*
* RXSTRING value;
* char buf[256];
* ULONG count, i;
*
* count = ........
*
* value.strlength = sprintf( buf, "%d", count );
* value.strptr = buf;
*
* VarSetStemValue( "FOO", 0, &value );
*
* for( i = 1; i <= count; ++i ){
* value.strlength = ......
* value.strptr = ......
*
* VarSetStemValue( "FOO", i, &value );
* }
*
*/
LONG VarSetStemValue( PSZ name, USHORT count, PRXSTRING value )
{
SHVBLOCK shv;
PSZ varname;
ULONG len;
if( !name ) goto leave;
len = strlen( name );
varname = alloca( len + 12 );
if( varname == NULL ) goto leave;
strcpy( varname, name );
strupr( varname );
if( varname[ len - 1 ] != '.' ){
varname[ len ] = '.';
len++;
}
sprintf( &varname[ len ], "%d", count );
shv.shvnext = NULL;
shv.shvname.strptr = varname;
shv.shvname.strlength = strlen( varname );
shv.shvvalue.strptr = value->strptr;
shv.shvvalue.strlength = value->strlength;
shv.shvvaluelen = value->strlength;
shv.shvcode = RXSHV_SET;
RexxVariablePool( &shv );
return( shv.shvret );
leave:
return( -1 );
}
/*
* VarDropValue -- Drop a REXX variable, just as if the program
* had executed the "drop" instruction.
*/
LONG VarDropValue( PSZ name )
{
SHVBLOCK shv;
ULONG len;
PSZ varname;
len = strlen( name );
varname = alloca( len + 1 );
if( varname == NULL ) goto leave;
strcpy( varname, name );
strupr( varname );
shv.shvnext = NULL;
shv.shvcode = RXSHV_DROPV;
shv.shvname.strptr = varname;
shv.shvname.strlength = len;
shv.shvvalue.strptr = NULL;
shv.shvvalue.strlength = 0;
shv.shvvaluelen = 0;
RexxVariablePool( &shv );
return( shv.shvret );
leave:
return( -1 );
}
/*
* VarGetNextValue -- Use this function to traverse the variable pool.
* Gets the name of the next REXX variable in the
* pool. Starts over whenever you fetch, set or
* drop a variable.
*
* The first parm will hold the name of the variable,
* the second will hold the value of the variable.
*
* If the buffers you pass in aren't big enough,
* new ones will be allocated.
*/
LONG VarGetNextValue( PRXSTRING name, PRXSTRING value )
{
SHVBLOCK shv;
if( !name || !value ) goto leave;
shv.shvnext = NULL;
shv.shvcode = RXSHV_NEXTV;
shv.shvname.strptr = NULL;
shv.shvname.strlength = 0;
shv.shvvalue.strptr = NULL;
shv.shvvalue.strlength = 0;
shv.shvvaluelen = 0;
RexxVariablePool( &shv );
if( shv.shvret == RXSHV_OK && shv.shvname.strptr ){
if( !name->strptr || name->strlength < shv.shvname.strlength + 1 ){
name->strptr = shv.shvname.strptr;
name->strlength = shv.shvname.strlength;
} else {
memcpy( name->strptr, shv.shvname.strptr, shv.shvname.strlength );
name->strptr[ shv.shvname.strlength ] = '\0';
name->strlength = shv.shvname.strlength;
DosFreeMem( shv.shvname.strptr );
}
if( !shv.shvvalue.strptr ){
value->strlength = 0;
value->strptr = NULL;
} else if( !value->strptr || value->strlength < shv.shvvaluelen + 1 ){
value->strlength = shv.shvvaluelen;
value->strptr = shv.shvvalue.strptr;
} else {
memcpy( value->strptr, shv.shvvalue.strptr, shv.shvvaluelen );
value->strptr[ shv.shvvaluelen ] = '\0';
value->strlength = shv.shvvaluelen;
DosFreeMem( shv.shvvalue.strptr );
}
} else {
name->strlength = value->strlength = 0;
name->strptr = value->strptr = NULL;
}
return( shv.shvret );
leave:
return( -1 );
}