home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c160 / 1.ddi / SOURCE / E4EXEC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-19  |  11.0 KB  |  421 lines

  1.  
  2. /* e4exec.c   (c)Copyright Sequiter Software Inc., 1987-1990.    All rights reserved.
  3.  
  4.    Expression Execution Routines
  5. */
  6.  
  7.  
  8. #include  "p4misc.h"
  9. #include  "d4all.h"
  10. #include  "e4parse.h"
  11. #include  "u4error.h"
  12.  
  13. #include  <string.h>
  14. #include  <stdlib.h>
  15.  
  16. extern BASE        *v4base ;
  17. extern E4FUNCTIONS  v4functions[] ;
  18. extern int          v4cur_base ;
  19.  
  20.  
  21. extern char  *v4eval_space ;
  22. extern int    v4eval_len ;
  23.  
  24. static int   v4return_left ;          /* The amount of result space currently available */
  25. static char *v4compile_string ;      /* The originally compiled string */
  26. int          v4original_base_ref=-1; /* The database reference number when the expression was originally parsed */
  27. int          v4type   =  -1 ;
  28. static int   v4length =  -1 ;
  29.  
  30. #ifdef PORTABLE
  31.    static int  calc_extra_len( E4PARM * ) ;
  32.    
  33.    static int  calc_extra_len( E4PARM *parms )
  34.    {
  35.       parms[0].extra_len =  sizeof(double) - parms[0].len % sizeof(double) ;
  36.       if ( parms[0].extra_len == sizeof(double) )
  37.          parms[0].extra_len =  0 ;
  38.  
  39.       v4return_left -=  parms[0].extra_len ;
  40.       parms[1].p.c  +=  parms[0].extra_len ;
  41.  
  42.       return e4return_len( parms, parms[0].extra_len ) ;
  43.    }
  44. #endif
  45.  
  46. int  e4return_len( E4PARM *parms, int len )   
  47. {
  48.    if ( v4return_left < len )
  49.    {
  50.       parms[0].len =  -1 ;
  51.       u4error( E_OVERFLOW, v4compile_string, (char *) 0 ) ;
  52.       return -1 ;
  53.    }
  54.    return 0 ;
  55. }
  56.  
  57. char  e4type()
  58. {
  59.    return( (char) v4type ) ;
  60. }
  61.  
  62. int  e4length()
  63. {
  64.    return( v4length ) ;
  65. }
  66.  
  67. /*   1.  Get function type and parameter information.
  68.      2.  Recursively call to get the parameters.
  69.      3.  Call function with the parameters.
  70.      4.  Return the result.
  71.  
  72.      result_ptr   points to where the value should be returned.
  73.      return_len   is the length of the available space.
  74.  
  75.      If the function returns a value of a specific length, the
  76.      parameter space will not overlap the last parameter.  Otherwise,
  77.      64 bytes of space will be allocated for the return value.  If
  78.      more is returned, the expression evaluation function return
  79.      will overlap the last parameter and perhaps other parameters as well.
  80.  
  81.      Returns
  82.          -1    Error
  83.     >= 0   The length of the return value.
  84. */
  85.  
  86. #define  VOID_PTR  void *
  87.  
  88. VOID_PTR  e4vary( char *comp_ptr )
  89. {
  90.    int     f_code, len, i, n_parms ;
  91.    long    field_ref ;
  92.    BASE   *base_ptr ;
  93.    FIELD  *field_ptr ;
  94.    E4PARM  parms[PARM_STACK_SIZE] ;
  95.    void   *ptr ;
  96.  
  97.    #ifdef PORTABLE
  98.       char  *compile_ptr ;
  99.  
  100.       compile_ptr =  comp_ptr ;
  101.  
  102.       compile_ptr +=  sizeof(int) ;
  103.       memcpy( &len, compile_ptr, sizeof(int) ) ;
  104.       compile_ptr +=  sizeof(int) ;
  105.  
  106.       v4compile_string =  (char *) compile_ptr ;
  107.       compile_ptr +=  len ;
  108.    #else
  109.       int    *compile_ptr ;
  110.       long   *long_ptr ;
  111.       compile_ptr =  (int *) comp_ptr ;
  112.  
  113.       compile_ptr++ ;
  114.       len =  *compile_ptr++ ;
  115.    
  116.       v4compile_string =  (char *) compile_ptr ;
  117.       compile_ptr =  (int *) ((char *)compile_ptr + len) ;
  118.    #endif
  119.  
  120.    v4return_left =  v4eval_len ;
  121.    n_parms =  0 ;
  122.  
  123.    #ifdef PORTABLE
  124.       memcpy( &v4original_base_ref, compile_ptr, sizeof(int) ) ;
  125.       compile_ptr +=  sizeof(int) ;
  126.    #else
  127.       v4original_base_ref =  *compile_ptr++ ;
  128.    #endif
  129.    parms[0].p.c =  (char *) v4eval_space ;
  130.  
  131.    for (;;)
  132.    {
  133.       #ifdef PORTABLE
  134.          memcpy( &f_code, compile_ptr, sizeof(int) ) ;
  135.          compile_ptr +=  sizeof(int) ;
  136.       #else
  137.          f_code =  *compile_ptr++ ;
  138.       #endif
  139.  
  140.       if ( n_parms+1 >= PARM_STACK_SIZE )
  141.       {
  142.          u4error( E_OVERFLOW, v4compile_string, (char *) 0 ) ;
  143.          return( (char *) 0 ) ;
  144.       }
  145.  
  146.       if ( f_code > LAST_IMMEDIATE )
  147.       {
  148.      n_parms -=  v4functions[f_code].num_parms ;
  149.      for ( i=0; i< v4functions[f_code].num_parms; i++ )
  150.          {
  151.         v4return_left +=  parms[n_parms+i].len ;
  152.             #ifdef PORTABLE
  153.            v4return_left +=  parms[n_parms+i].extra_len ;
  154.             #endif
  155.          }
  156.  
  157.      (*v4functions[f_code].function_ptr)( parms+n_parms ) ;
  158.          if ( parms[n_parms].len < 0 )  return( (char *) 0 ) ;
  159.      v4return_left -= parms[n_parms].len ;
  160.      parms[n_parms+1].p.c =  parms[n_parms].p.c + parms[n_parms].len ;
  161.  
  162.          #ifdef PORTABLE
  163.             if ( calc_extra_len( parms+n_parms ) < 0 )  return( (VOID_PTR) 0 ) ;
  164.          #endif
  165.  
  166.          n_parms++ ;
  167.          continue ;
  168.       }
  169.  
  170.       if ( f_code < 0 )
  171.       {
  172.          v4type   =  parms[0].type ;
  173.          v4length =  parms[0].len ;
  174.  
  175.          #ifdef PORTABLE
  176.         if ( v4eval_len-v4return_left != v4length + parms[0].extra_len )
  177.          #else
  178.         if ( v4eval_len-v4return_left != v4length )
  179.          #endif
  180.         u4error( E_INTERNAL, "e4vary: Return Length Discrepency", (char *) 0 ) ;
  181.  
  182.          if ( e4return_len( parms, 1) < 0 )  return( (char *) 0 ) ;
  183.          parms[0].p.c[v4length] = '\000' ;
  184.  
  185.          return( v4eval_space ) ;
  186.       }
  187.  
  188.       /* Field or Immediate Data */
  189.       if ( f_code <= LAST_I_FIELD )
  190.       {
  191.          #ifdef PORTABLE
  192.             memcpy( &field_ref,  compile_ptr, sizeof(long) ) ;
  193.             compile_ptr +=  sizeof(long) ;
  194.          #else
  195.             long_ptr  =  (long *) compile_ptr ;
  196.             field_ref =  *long_ptr ;
  197.             compile_ptr =  (int *) (((char *) compile_ptr) + sizeof(long)) ;
  198.          #endif
  199.  
  200.          base_ptr  =  v4base +  (int) (field_ref>>16) ;
  201.          field_ptr =  base_ptr->fields + (int) (field_ref & 0xFFFF) ;
  202.  
  203.      parms[n_parms].type =  v4functions[f_code].return_type ;
  204.  
  205.          switch( f_code )
  206.          {  /* Calculate field values directly for slight extra speed */
  207.             case I_FIELD_STR:
  208.             case I_FIELD_NUM_S:
  209.             case I_FIELD_DATE_S:
  210.            if ( e4return_len( parms, field_ptr->width ) < 0 )  return( (VOID_PTR) 0 ) ;
  211.                memcpy( parms[n_parms].p.c, base_ptr->buffer + field_ptr->offset, (size_t) field_ptr->width ) ;
  212.                len =  field_ptr->width ;
  213.            if ( f_code == I_FIELD_NUM_S )
  214.            {
  215.               if ( field_ptr->decimals > 0 )
  216.              parms[n_parms].p.c[field_ptr->width-field_ptr->decimals-1] = '.' ;
  217.            }
  218.                break ;
  219.  
  220.             case I_FIELD_NUM_D:
  221.            if ( e4return_len( parms, sizeof(double) ) < 0 )  return( (VOID_PTR) 0 ) ;
  222.                *parms[n_parms].p.d =  c4atod( base_ptr->buffer+ field_ptr->offset, field_ptr->width ) ;
  223.                len =  sizeof(double) ;
  224.                break ;
  225.  
  226.             case I_FIELD_DATE_D:
  227.            if ( e4return_len( parms, sizeof(double) ) < 0 )  return( (VOID_PTR) 0 ) ;
  228.            c4dt_julian( base_ptr->buffer+ field_ptr->offset, parms[n_parms].p.d ) ;
  229.                len =  sizeof(double) ;
  230.                break ;
  231.  
  232.             case I_FIELD_LOG:
  233.            if ( e4return_len( parms, sizeof(int) ) < 0 )  return( (VOID_PTR) 0 ) ;
  234.                *parms[n_parms].p.i =  f4true( field_ref ) ;
  235.                len =  sizeof(int) ;
  236.                break ;
  237.  
  238.         #ifdef MEMO
  239.         case I_FIELD_MEMO:  /* Not Yet Supported */
  240.            break ;
  241.         #endif
  242.          }
  243.  
  244.      v4return_left -=  len ;
  245.      parms[n_parms].len =  len ;
  246.      parms[n_parms+1].p.c  =  parms[n_parms].p.c + len ;
  247.  
  248.          #ifdef PORTABLE
  249.             /* Make sure the next position is a multiple of 'sizeof(double)' */
  250.             if ( calc_extra_len( parms+n_parms ) < 0 )
  251.                return( (VOID_PTR) 0 ) ;
  252.          #endif
  253.  
  254.          n_parms++ ;
  255.      continue ;
  256.       }
  257.  
  258.       /* Immediate Data */
  259.       switch( f_code )
  260.       {
  261.      case  I_STRING:
  262.             #ifdef PORTABLE
  263.                memcpy( &len, compile_ptr, sizeof(int) ) ;
  264.            compile_ptr +=  sizeof(int) ;
  265.             #else
  266.            len =  *compile_ptr++ ;
  267.             #endif
  268.         parms[n_parms].type =  T_STR ;
  269.         break ;
  270.  
  271.      case  I_DOUBLE:
  272.         len =  (int) sizeof(double) ;
  273.         parms[n_parms].type =  T_NUM_DOUB ;
  274.         break ;
  275.       }
  276.  
  277.       if ( e4return_len( parms, len ) < 0 )  return( (VOID_PTR) 0 ) ;
  278.       v4return_left -=  len ;
  279.       parms[n_parms].len =  len ;
  280.  
  281.       ptr =  parms[n_parms].p.v ;
  282.       memcpy( ptr, compile_ptr, (size_t) len ) ;
  283.       #ifdef PORTABLE
  284.          compile_ptr += len ;
  285.       #else
  286.          compile_ptr =  (int *) ((char *) compile_ptr + len) ;
  287.       #endif
  288.       parms[n_parms+1].p.c =  (char *) ptr+ len ;
  289.  
  290.       #ifdef PORTABLE
  291.          if ( calc_extra_len( parms+n_parms ) < 0 )  return ( (VOID_PTR) 0 ) ;
  292.       #endif
  293.  
  294.       n_parms++ ;
  295.       continue ;
  296.    }
  297. }
  298.  
  299.  
  300. VOID_PTR  e4exec( char *compile_ptr )
  301. {
  302.    VOID_PTR  result_ptr ;
  303.  
  304.    result_ptr =  e4vary( compile_ptr ) ;
  305.  
  306.    if ( v4type == T_NUM_STR )
  307.    {
  308.       *((double *) result_ptr) =  c4atod( (char *) result_ptr, v4length ) ;
  309.       v4type =  T_NUM_DOUB ;
  310.    }
  311.    if ( v4type == T_DATE_DOUB )
  312.    {
  313.       double  index_date ;
  314.  
  315.       index_date =  *((double *) result_ptr) ;
  316.  
  317.       c4dt_str( (char *) result_ptr, (double *) &index_date ) ;
  318.       v4type =  T_DATE_STR ;
  319.    }
  320.  
  321.    return( result_ptr ) ;
  322. }
  323.  
  324.  
  325. extern int  v4decimals ;
  326.  
  327. char *  e4string( char *compile_ptr )
  328. {
  329.    char *result_ptr ;
  330.  
  331.    result_ptr =   (char *) e4vary( compile_ptr ) ;
  332.  
  333.    if ( v4type == T_NUM_DOUB )
  334.    {
  335.       char *str, *ptr ;
  336.       int   dig_len, is_neg, zeros_len, i ;
  337.  
  338.       v4length =  17 ;
  339.       v4type =  T_NUM_STR ;
  340.       str =  fcvt( *((double *) result_ptr), v4decimals, &dig_len, &is_neg ) ;
  341.  
  342.       zeros_len =  v4length - dig_len - 1 - v4decimals ;
  343.       if ( zeros_len < 0 )
  344.       {
  345.      memset( result_ptr, (int) '*', (size_t) v4length) ;
  346.      return( result_ptr) ;
  347.       }
  348.  
  349.       memset( result_ptr, (int) '0', (size_t) zeros_len ) ;
  350.       ptr =  result_ptr + zeros_len ;
  351.       memcpy( ptr, str, (size_t) dig_len ) ;
  352.       ptr += dig_len ;
  353.       *ptr = '.' ;
  354.       memcpy( ++ptr, str+dig_len, (size_t) v4decimals ) ;
  355.       ptr[v4decimals] = '\000' ;
  356.  
  357.       if ( is_neg )
  358.       {
  359.      for ( i=0; i< v4length; i++ )
  360.         result_ptr[i] = (char) 0x5c - result_ptr[i] ;
  361.       }
  362.       return( result_ptr ) ;
  363.    }
  364.  
  365.    if ( v4type == T_NUM_STR )
  366.    {
  367.       int   i, negative ;
  368.       char *p ;
  369.  
  370.       for ( i= negative= 0, p= result_ptr; i< v4length; i++, p++ )
  371.       {
  372.          if ( *p == ' ' )
  373.          {
  374.         *p =  '0' ;
  375.          }
  376.          else
  377.          {
  378.         if ( *p == '-' )
  379.         {
  380.            *p =  '0' ;
  381.            negative =  1 ;
  382.         }
  383.          }
  384.       }
  385.  
  386.       if ( negative )
  387.       {
  388.          for ( i= 0, p= result_ptr; i< v4length; i++, p++ )
  389.         *p =  (char) 0x5c - *p ;
  390.       }
  391.  
  392.       return result_ptr ;
  393.    }
  394.  
  395.    if ( v4type == T_DATE_DOUB )
  396.    {
  397.       double  index_date ;
  398.  
  399.       index_date =  *((double *) result_ptr) ;
  400.  
  401.       c4dt_str( (char *) result_ptr, (double *) &index_date ) ;
  402.       v4type =  T_DATE_STR ;
  403.       v4length =  8 ;
  404.    }
  405.  
  406.    return( (char *) result_ptr ) ;
  407. }
  408.  
  409.  
  410. VOID_PTR e4eval( char *expr_ptr )
  411. {
  412.    char     *compile_ptr ;
  413.    VOID_PTR  result_ptr ;
  414.  
  415.    if ( e4parse( expr_ptr, &compile_ptr) < 0)  return( (VOID_PTR) 0) ;
  416.    result_ptr =  e4exec( compile_ptr ) ;
  417.    h4free_memory( compile_ptr ) ;
  418.    return( (VOID_PTR) result_ptr ) ;
  419. }
  420.  
  421.