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 >
C/C++ Source or Header  |  1994-08-05  |  12KB  |  421 lines

  1. /*
  2.  * varpool.c -- Routines to fetch, set and drop REXX variables.  You can
  3.  *              call these routines whenever the REXX interpreter calls
  4.  *              your program (in an external function, a subcommand
  5.  *              handler, or a system exit).
  6.  *
  7.  *  Notes on accessing the variable pool:
  8.  *  -------------------------------------
  9.  *
  10.  *  All accesses to the variable pool are done by filling in one or
  11.  *  more (you can link them together into a list) SHVBLOCK structures
  12.  *  (defined in rexxsaa.h) and then passing the block(s) to the
  13.  *  interpreter by calling the RexxVariablePool function.  The interpreter
  14.  *  will then scan each SHVBLOCK, fulfill the request if it can, and
  15.  *  then store the result back into the structure.
  16.  *
  17.  *  There is NO function you can call to get a list of all variables,
  18.  *  or all variables that start with a certain stem, etc.  You CAN traverse
  19.  *  the variable pool one item at a time, which is the only way to get
  20.  *  all the variables.
  21.  *
  22.  *  The functions below all work on a single variable at a time, but you
  23.  *  can easily expand them to work with multiple variables.  You might
  24.  *  want to get a complete stem array (foo.0, foo.1, foo.2, ...) in a
  25.  *  single pass.
  26.  *
  27.  *  WATCH OUT FOR MEMORY LEAKS!  If you let the variable pool allocate
  28.  *  buffers for you, be sure to free them...
  29.  */
  30.  
  31. #define INCL_REXXSAA
  32.  
  33. #include <os2.h>
  34. #include <rexxsaa.h>
  35.  
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include <malloc.h>
  40.  
  41. #include "varpool.h"
  42.  
  43. /*
  44.  * VarFetchValue -- Fetch a single value from the variable pool.  You can
  45.  *                  pass the name of a simple symbol, or a complex
  46.  *                  one.  The return code indicates whether the function
  47.  *                  was successful: RXSHV_OK indicates total success,
  48.  *                  RXSHV_TRUNC indicates partial success (the value
  49.  *                  of the variable was too long to fit in the given
  50.  *                  space and was truncated), anything else is an error.
  51.  *
  52.  *                  If the RXSTRING you pass in has its strptr field set
  53.  *                  to NULL, the variable pool will allocate memory
  54.  *                  for you using DosAllocMem.  Otherwise it will use
  55.  *                  the memory you provide, so set the strlength field
  56.  *                  accordingly.
  57.  *
  58.  *    Sample usage:
  59.  *
  60.  *        RXSTRING value;
  61.  *        char     buf[256];
  62.  *
  63.  *        value.strlength = 256;
  64.  *        value.strptr    = buf;
  65.  *
  66.  *        if( VarFetchValue( "A.B.C", &value ) == RXSHV_OK ){
  67.  *            ........
  68.  *        }
  69.  *
  70.  *
  71.  *        value.strlength = 0
  72.  *        value.strptr    = NULL;
  73.  *
  74.  *        if( VarFetchValue( "FOO", &value ) == RXSHV_OK ){
  75.  *            ........
  76.  *
  77.  *            if( value.strptr )
  78.  *                DosFreeMem( value.strptr );
  79.  *        }
  80.  *
  81.  */
  82.  
  83. LONG VarFetchValue( PSZ name, PRXSTRING value )
  84.   {
  85.     SHVBLOCK shv;
  86.     PSZ      varname;
  87.     ULONG    len;
  88.  
  89.     if( !name ) goto leave;
  90.  
  91.     /* Copy name and uppercase it... */
  92.  
  93.     len     = strlen( name );
  94.     varname = alloca( len + 1 );
  95.  
  96.     if( varname == NULL ) goto leave;
  97.  
  98.     strcpy( varname, name );
  99.     strupr( varname );
  100.  
  101.     /* Fill in a FETCH request.... */
  102.  
  103.     shv.shvnext            = NULL;
  104.     shv.shvname.strptr     = varname;
  105.     shv.shvname.strlength  = len;
  106.     shv.shvvalue.strptr    = value->strptr;
  107.     shv.shvvalue.strlength = value->strlength;
  108.     shv.shvvaluelen        = value->strlength;
  109.     shv.shvcode            = RXSHV_FETCH;
  110.  
  111.     /* Fetch it and set the return values accordingly... */
  112.  
  113.     RexxVariablePool( &shv );
  114.  
  115.     if( shv.shvret == RXSHV_OK || shv.shvret == RXSHV_TRUNC ){
  116.         value->strptr    = shv.shvvalue.strptr;
  117.         value->strlength = shv.shvvaluelen;
  118.     }
  119.  
  120.     return( shv.shvret );
  121.  
  122.   leave:
  123.     return( -1 );
  124. }
  125.  
  126. /*
  127.  * VarFetchStemValue -- This function is similar to VarFetchValue, except
  128.  *                      that it is useful in fetching a stem array
  129.  *                      (i.e., foo.0, foo.1, foo.2, etc.).  You could
  130.  *                      actually do it by calling VarFetchValue for
  131.  *                      "foo.0", "foo.1", etc., but this function makes
  132.  *                      it easier.
  133.  *
  134.  *    Sample usage (no error checking):
  135.  *
  136.  *        RXSTRING value;
  137.  *        char     buf[256];
  138.  *        ULONG    count, i;
  139.  *
  140.  *        value.strlength = 256;
  141.  *        value.strptr    = buf;
  142.  *
  143.  *        VarFetchStemValue( "foo", 0, &value );
  144.  *
  145.  *        count = strtoul( buf, NULL, 10 );
  146.  *
  147.  *        for( i = 1; i <= count; ++i ){
  148.  *            value.strlength = 256;
  149.  *            value.strptr    = buf;
  150.  *
  151.  *            VarFetchStemValue( "foo", i, &value );
  152.  *
  153.  *            .....
  154.  *        }
  155.  *
  156.  */
  157.  
  158. LONG VarFetchStemValue( PSZ stem, USHORT count, PRXSTRING value )
  159.   {
  160.     SHVBLOCK    shv;
  161.     PSZ         varbuf;
  162.     USHORT      varlen;
  163.  
  164.     if( !stem ) goto leave;
  165.  
  166.     /* Convert to uppercase, make sure there's enough room for a ULONG
  167.        value, and add a '.' if necessary */
  168.  
  169.     varlen = strlen( stem );
  170.     varbuf = alloca( varlen + 12 );
  171.  
  172.     if( varbuf == NULL ) goto leave;
  173.  
  174.     strcpy( varbuf, stem );
  175.     strupr( varbuf );
  176.  
  177.     if( varbuf[ varlen - 1 ] != '.' ){
  178.         varbuf[ varlen ] = '.';
  179.         varlen++;
  180.     }
  181.  
  182.     /* Convert the index */
  183.  
  184.     sprintf( &varbuf[ varlen ], "%d", count );
  185.  
  186.     /* Request the value... */
  187.  
  188.     shv.shvnext            = NULL;
  189.     shv.shvname.strptr     = varbuf;
  190.     shv.shvname.strlength  = strlen( varbuf );
  191.     shv.shvvalue.strptr    = value->strptr;
  192.     shv.shvvalue.strlength = value->strlength;
  193.     shv.shvvaluelen        = value->strlength;
  194.     shv.shvcode            = RXSHV_FETCH;
  195.  
  196.     RexxVariablePool( &shv );
  197.  
  198.     if( shv.shvret == RXSHV_OK || shv.shvret == RXSHV_TRUNC ){
  199.         value->strptr    = shv.shvvalue.strptr;
  200.         value->strlength = shv.shvvaluelen;
  201.     }
  202.  
  203.     return( shv.shvret );
  204.  
  205. leave:
  206.     return( -1 );
  207.   }
  208.  
  209.  
  210. /*
  211.  * VarSetValue -- Sets the value of a variable.  Just pass it the name
  212.  *                of the variable (i.e., "FOO", "A.B") and a value and
  213.  *                it will set it.  Returns RXSHV_OK or RXSHV_NEWV if
  214.  *                successful.
  215.  *
  216.  *    Sample usage:
  217.  *
  218.  *        RXSTRING value;
  219.  *
  220.  *        value.strptr    = "This is a test"
  221.  *        value.strlength = strlen( value.strptr );
  222.  *
  223.  *        VarSetValue( "FOO", &value );
  224.  */
  225.  
  226. LONG VarSetValue( PSZ name, PRXSTRING value )
  227.   {
  228.     SHVBLOCK shv;
  229.     PSZ      varname;
  230.     ULONG    len;
  231.  
  232.     if( !name ) goto leave;
  233.  
  234.     len     = strlen( name );
  235.     varname = alloca( len + 1 );
  236.  
  237.     if( varname == NULL ) goto leave;
  238.  
  239.     strcpy( varname, name );
  240.     strupr( varname );
  241.  
  242.     shv.shvnext            = NULL;
  243.     shv.shvname.strptr     = varname;
  244.     shv.shvname.strlength  = len;
  245.     shv.shvvalue.strptr    = value->strptr;
  246.     shv.shvvalue.strlength = value->strlength;
  247.     shv.shvvaluelen        = value->strlength;
  248.     shv.shvcode            = RXSHV_SET;
  249.  
  250.     RexxVariablePool( &shv );
  251.  
  252.     return( shv.shvret );
  253.  
  254. leave:
  255.     return( -1 );
  256.   }
  257.  
  258. /*
  259.  * VarSetStemValue -- Like VarSetValue, but lets you set the values
  260.  *                    of a stem array.
  261.  *
  262.  *    Sample usage:
  263.  *
  264.  *        RXSTRING value;
  265.  *        char     buf[256];
  266.  *        ULONG    count, i;
  267.  *
  268.  *        count = ........
  269.  *
  270.  *        value.strlength = sprintf( buf, "%d", count );
  271.  *        value.strptr    = buf;
  272.  *
  273.  *        VarSetStemValue( "FOO", 0, &value );
  274.  *
  275.  *        for( i = 1; i <= count; ++i ){
  276.  *            value.strlength = ......
  277.  *            value.strptr    = ......
  278.  *
  279.  *            VarSetStemValue( "FOO", i, &value );
  280.  *        }
  281.  *
  282.  */
  283.  
  284. LONG VarSetStemValue( PSZ name, USHORT count, PRXSTRING value )
  285.   {
  286.     SHVBLOCK shv;
  287.     PSZ      varname;
  288.     ULONG    len;
  289.  
  290.     if( !name ) goto leave;
  291.  
  292.     len     = strlen( name );
  293.     varname = alloca( len + 12 );
  294.  
  295.     if( varname == NULL ) goto leave;
  296.  
  297.     strcpy( varname, name );
  298.     strupr( varname );
  299.  
  300.     if( varname[ len - 1 ] != '.' ){
  301.         varname[ len ] = '.';
  302.         len++;
  303.     }
  304.  
  305.     sprintf( &varname[ len ], "%d", count );
  306.  
  307.     shv.shvnext            = NULL;
  308.     shv.shvname.strptr     = varname;
  309.     shv.shvname.strlength  = strlen( varname );
  310.     shv.shvvalue.strptr    = value->strptr;
  311.     shv.shvvalue.strlength = value->strlength;
  312.     shv.shvvaluelen        = value->strlength;
  313.     shv.shvcode            = RXSHV_SET;
  314.  
  315.     RexxVariablePool( &shv );
  316.  
  317.     return( shv.shvret );
  318.  
  319. leave:
  320.     return( -1 );
  321. }
  322.  
  323. /*
  324.  *  VarDropValue -- Drop a REXX variable, just as if the program
  325.  *                  had executed the "drop" instruction.
  326.  */
  327.  
  328. LONG VarDropValue( PSZ name )
  329.   {
  330.     SHVBLOCK shv;
  331.     ULONG    len;
  332.     PSZ      varname;
  333.  
  334.     len     = strlen( name );
  335.     varname = alloca( len + 1 );
  336.     if( varname == NULL ) goto leave;
  337.  
  338.     strcpy( varname, name );
  339.     strupr( varname );
  340.  
  341.     shv.shvnext            = NULL;
  342.     shv.shvcode            = RXSHV_DROPV;
  343.     shv.shvname.strptr     = varname;
  344.     shv.shvname.strlength  = len;
  345.     shv.shvvalue.strptr    = NULL;
  346.     shv.shvvalue.strlength = 0;
  347.     shv.shvvaluelen        = 0;
  348.  
  349.     RexxVariablePool( &shv );
  350.  
  351.     return( shv.shvret );
  352.  
  353.   leave:
  354.     return( -1 );
  355.   }
  356.  
  357. /*
  358.  * VarGetNextValue -- Use this function to traverse the variable pool.
  359.  *                    Gets the name of the next REXX variable in the
  360.  *                    pool.  Starts over whenever you fetch, set or
  361.  *                    drop a variable.
  362.  *
  363.  *                    The first parm will hold the name of the variable,
  364.  *                    the second will hold the value of the variable.
  365.  *
  366.  *                    If the buffers you pass in aren't big enough,
  367.  *                    new ones will be allocated.
  368.  */
  369.  
  370. LONG VarGetNextValue( PRXSTRING name, PRXSTRING value )
  371.   {
  372.     SHVBLOCK shv;
  373.  
  374.     if( !name || !value ) goto leave;
  375.  
  376.     shv.shvnext            = NULL;
  377.     shv.shvcode            = RXSHV_NEXTV;
  378.     shv.shvname.strptr     = NULL;
  379.     shv.shvname.strlength  = 0;
  380.     shv.shvvalue.strptr    = NULL;
  381.     shv.shvvalue.strlength = 0;
  382.     shv.shvvaluelen        = 0;
  383.  
  384.     RexxVariablePool( &shv );
  385.  
  386.     if( shv.shvret == RXSHV_OK && shv.shvname.strptr ){
  387.         if( !name->strptr || name->strlength < shv.shvname.strlength + 1 ){
  388.             name->strptr    = shv.shvname.strptr;
  389.             name->strlength = shv.shvname.strlength;
  390.         } else {
  391.             memcpy( name->strptr, shv.shvname.strptr, shv.shvname.strlength );
  392.             name->strptr[ shv.shvname.strlength ] = '\0';
  393.             name->strlength = shv.shvname.strlength;
  394.  
  395.             DosFreeMem( shv.shvname.strptr );
  396.         }
  397.  
  398.         if( !shv.shvvalue.strptr ){
  399.             value->strlength = 0;
  400.             value->strptr    = NULL;
  401.         } else if( !value->strptr || value->strlength < shv.shvvaluelen + 1 ){
  402.             value->strlength = shv.shvvaluelen;
  403.             value->strptr    = shv.shvvalue.strptr;
  404.         } else {
  405.             memcpy( value->strptr, shv.shvvalue.strptr, shv.shvvaluelen );
  406.             value->strptr[ shv.shvvaluelen ] = '\0';
  407.             value->strlength = shv.shvvaluelen;
  408.  
  409.             DosFreeMem( shv.shvvalue.strptr );
  410.         }
  411.     } else {
  412.         name->strlength = value->strlength = 0;
  413.         name->strptr    = value->strptr    = NULL;
  414.     }
  415.  
  416.     return( shv.shvret );
  417.  
  418.   leave:
  419.     return( -1 );
  420.