home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c160 / 1.ddi / DOC / V4FUNCTI.DOC < prev   
Encoding:
Text File  |  1990-02-19  |  9.2 KB  |  249 lines

  1.  
  2. (c)Copyright Sequiter Software Inc., 1987-1990.  All rights reserved.
  3.  
  4.  
  5. Parsing and Evaluating Additional Functions 
  6.  
  7. The expression evaluation module of Code Base parses and evaluate 
  8. dBASE expressions.  It is not difficult to modify the expression 
  9. evaluation module to support user defined functions or 
  10. dBASE/Clipper/FoxPro functions not currently defined.  Alternately, 
  11. you can remove existing ones to make EXE files slightly smaller.  
  12.  
  13. In order to understand the following documentation, you need to understand
  14. dBASE expressions and the Code Base expression evaluation routines.
  15.  
  16. To add a user defined function which is recognized by the Code Base
  17. expression evaluation routines, do the following:
  18.  
  19.    1.  Write the User Defined Function
  20.    2.  Make an entry in the structure array 'v4functions'.  This array
  21.        is located in file 'e4functions.c'.
  22.    3.  Rebuild the Code Base 4 library leaving out file 'e4functions.c'.
  23.        Depending on your compiler, this step may not be necessary.
  24.        For example, when using Turbo C you just need to add 'e4functions.c'
  25.        to your project file.
  26.    4.  Compile and Link your program explicitly compiling and linking
  27.        in Code Base source file 'e4functions.c'.
  28.    5.  Test the user defined function by calling 'e4parse' and 'e4exec.'.
  29.  
  30.    User Defined Functions return a void and have a structure array
  31. of type 'E4PARM' as a parameter.
  32.  
  33. Example
  34.  
  35.    void  e4upper( parms )
  36.    E4PARM  parms[1] ;
  37.    {
  38.       /* Call 'e4return_len' to make sure that there is enough
  39.          space of the 'evaluation' stack to return the result.  */
  40.       if ( e4return_len( parms, parms[0].len+1 ) < 0 )  return ;
  41.  
  42.       parms[0].p.c[parms[0].len] = '\0' ;
  43.       strupr( parms[0].p.c ) ;
  44.    }
  45.  
  46.    The following 'v4functions' entry would be used to tell Code Base 4 
  47. about the above user defined function:
  48.  
  49.    {280, 5,"UPPER",   e4upper,   0,  T_STR, 1, T_STR },
  50.  
  51.    As a result of this entry, the following Code Base 
  52. call works:
  53.  
  54.       i4index( "I_NAME", "UPPER(CHAR_FLD)", 0, 0 ) ;
  55.  
  56.    or
  57.  
  58.       printf( "\n Result: %s", e4eval( "UPPER(CHAR_FLD)" ) ) ;
  59.  
  60.    dBASE Function 'UPPER' converts a character value to upper case.
  61.  
  62.    The purpose of the 'v4functions' entry is to tell routine 'e4parse'
  63. which dBASE function character sequence corresponds with which C function.
  64. Consequently, 'e4exec' calls the correct C routine.  In addition, the entry
  65. specifies the dBASE function parameter and return information.  This allows 
  66. 'e4parse' to do most of the error checking.  Consequently, the User Defined
  67. Functions can make assumptions about its parameters.
  68.  
  69.    dBASE field types are associated with the following integer constants
  70. defined in 'e4parse.h':
  71.  
  72.    dBASE Type        Define Name        Define Integer Value     C Format
  73.  
  74.    CHAR              T_STR           (int) 'C'             Characters
  75.    DATE              T_DATE_DOUB       (int) 'd'             Julian Double
  76.    NUMERIC           T_NUM_DOUB           (int) 'N'             Double
  77.    FLOAT             T_NUM_DOUB           (int) 'N'             Double
  78.    LOGICAL         T_LOG           (int) 'L'             Integer
  79.  
  80.    If you examine 'e4functions.c' or 'e4parse.h' you may notice that
  81. pre-defined Code Base user defined functions sometimes pass Numerics, Dates,
  82. and Floats as strings.  Avoid this as it is slightly more complicated and is
  83. not formally documented.
  84.  
  85. It is easy to add your own functions to be recognized by the expression
  86. evaluation routines.  The source file to modify is 'e4functi.c'.  You
  87. need to make an entry is the static array 'v4functions'.  Each entry
  88. in 'v4functions' is a structure of type 'E4FUNCTIONS':
  89.    
  90.    typedef struct
  91.    {
  92.       int      code ;
  93.       int      name_len ;
  94.       char     name[12] ;
  95.       void     (*function_ptr)( E4PARM *) ;
  96.       int      priority ;
  97.       int      return_type ;
  98.       int      num_parms ;    /* 0 - No Return;  -1 First Parm. Specifies # */
  99.       int      type[MAX_PARMS]; /* type[0] is the return type */
  100.    }  E4FUNCTIONS ;
  101.  
  102.  
  103. Following is a description of each member of structure 'E4FUNCTIONS':
  104.  
  105. code
  106.  
  107.    The is a unique number corresponding to the function name.  This unique,
  108.    number should be different from the 'code' corresponding to other function 
  109.    names.  For example, if the last 
  110.    function defined has a code value of '290', make the code value of the new
  111.    function a number slightly bigger.  
  112.  
  113. name_len
  114.    
  115.    This is the number of characters in the function name.  It should be 
  116.    less than twelve.
  117.  
  118. name
  119.    
  120.    This is the name of the user defined function.  The name must have
  121.    be less than twelve characters long.
  122.  
  123. function_ptr
  124.  
  125.    This is the corresponding C function.  Refer to the above example
  126.    for the syntax.
  127.  
  128. priority
  129.  
  130.    This value is always zero for user defined functions.
  131.  
  132. return_type
  133.  
  134.    This is the dBASE type of the return.  Refer to the predefined
  135.    constants specified above.
  136.  
  137. num_parms
  138.  
  139.    This is the number of parameters for the user defined function.  Routine
  140.    'e4parse' verifies that the actual number of parameters against
  141.    this number.  By default constant 'MAX_PARMS' is three.  This
  142.    There is a maximum of three parameters.
  143.  
  144. type[MAX_PARMS]
  145.  
  146.    This is the dBASE type of each parameter.  The 
  147.    integer constants corresponding to each dBASE type are specified
  148.    above.
  149.  
  150. The prototype for the C routines corresponding
  151. to the user defined function is as follows:
  152.  
  153.    void  c_function_name( E4PARM *parms )
  154.  
  155. This is the definition of structure E4PARM:
  156.    
  157.    typedef struct
  158.    {
  159.       union
  160.       {
  161.          void   *v ;
  162.          char   *c ;  /* For Character Parameters. */
  163.          int    *i ;  /* For Logical Parameters. */
  164.          long   *l ;
  165.          double *d ;  /* For Numeric and Date parameters of Type Double. */
  166.       }  p ;          /* Pointer to the parameter */
  167.       int    type ;   /* The type of the parameter */
  168.       int    len ;    /* The number of bytes in the parameter */
  169.    }  E4PARM ;
  170.  
  171. There is an array element passed for each parameter.  For example,
  172. if the type of the second User Defined Function parameter is T_NUM_DOUB,
  173. then '*parms[1].d' refereces the parameters 'double' value.  The
  174. C function returns the User Defined Function result through the first
  175. parameter.
  176.  
  177. Following is the definition of the C routine corresponding to 
  178. dBASE function 'VAL'.  'VAL' takes a Character parameter and
  179. returns a Numeric result.  
  180.  
  181.    /* C routine 'e4val' corresponds to the following 'e4functions' entry:
  182.       {290, 3,"VAL",     e4val,     0,  T_NUM_DOUB, 1, T_STR },
  183.    */
  184.    
  185.    void  e4val( parms )
  186.    E4PARM  parms[1] ;
  187.    {
  188.       /* 'e4return_len' should be called to verify that there is enough
  189.          space on the internal Code Base stack for the return value. */
  190.       if ( e4return_len(parms, (int) sizeof(double)) < 0 )  return ;
  191.  
  192.       /* Since the parameter is specified as type 'T_STR', the parameter
  193.          is formatted as ASCII characters.  Consequently, it is 
  194.          conveniently accessed through 'parms[0].p.c'.  The number
  195.          of characters is specified by 'parms[0].len'.  Since the result
  196.          is specified as 'T_NUM_DOUB', it is formatted as a double.
  197.          The length of the result is placed in 'parms[0].len' and the
  198.          type of the result is placed in 'parms[0].type'. */
  199.       *parms[0].p.d =  c4atod( parms[0].p.c, (int) parms[0].len ) ;
  200.       parms[0].len  =  sizeof(double) ;
  201.       parms[0].type =  T_NUM_DOUB ;
  202.    }
  203.  
  204. There is a Code Base defined integer variable named 'v4original_base_ref'.
  205. It contains the reference number of the database which was selected when
  206. the dBASE expression was originally parased.  This variable is defined
  207. as an 'extern int' in file 'e4functions.c'.
  208.  
  209. Notice that the same C function can correspond to more than one
  210. dBASE function.  For example, under Code Base, "DTOS" and "DTOC"
  211. do exactly the same thing.  Consequently, both 'v4functions' entries map to
  212. the same C function.
  213.  
  214.    {180, 4,"DTOS",    e4dtoc,    0,  T_STR, 1, T_DATE_STR },
  215.    {185, 4,"DTOC",    e4dtoc,    0,  T_STR, 1, T_DATE_STR },
  216.  
  217. Another different example is dBASE function "IIF".  This function
  218. takes more than one possible parameter configuration.  There
  219. is an entry in 'v4functions' for each of these possible configurations.
  220. Each of these entries must be adjacent to one another.
  221.  
  222.    {220, 3,"IIF",     e4iif,     0,  T_STR, 3, T_LOG, T_STR, T_STR },
  223.    {220, 3,"IIF",     e4iif,     0,  T_NUM_DOUB, 3, T_LOG, T_NUM_DOUB, T_NUM_DOUB },
  224.    {220, 3,"IIF",     e4iif,     0,  T_LOG, 3, T_LOG, T_LOG, T_LOG },
  225.    {220, 3,"IIF",     e4iif,     0,  T_DATE_DOUB, 3, T_LOG, T_DATE_DOUB, T_DATE_DOUB },
  226.  
  227. In the Code for 'e4iif', the values placed in 'parms[0].type' 
  228. is dependent on the parameter type.  Conseqently, the function is 
  229. consistent with each parameter configuration:
  230.    
  231.    void  e4iif( parms )
  232.    E4PARM  parms[3] ;
  233.    {
  234.       E4PARM  *ptr ;
  235.    
  236.       if ( *parms[0].p.i )
  237.          ptr =  parms+1 ;
  238.       else
  239.          ptr =  parms+2 ;
  240.    
  241.       memmove( parms[0].p.c, ptr->p.c, ptr->len ) ;
  242.    
  243.       parms[0].type =  ptr->type ;
  244.       parms[0].len  =  ptr->len ;
  245.    }
  246.  
  247. Note that instead of a single 'e4iif' C routine, there could have been
  248. a different C routine for each parameter configuration.
  249.