home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / CODE4-1.ZIP / SOURCE.ZIP / E4PARSE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-13  |  12.8 KB  |  579 lines

  1.  
  2. /*  e4parse.c    (c)Copyright Sequiter Software Inc., 1987, 1988, 1989.  All rights reserved.
  3.  
  4. */
  5.  
  6. #include "d4base.h"
  7. #include "u4error.h"
  8. #include "e4parse.h"
  9.  
  10. #include <string.h>
  11. #include <stdlib.h>
  12.  
  13. static  int   e4parse_expr(void), e4funct_num(char *,int), e4cur_operator(void),
  14.           e4parse_function(void), e4parse_value(void), e4get_operator(char *) ;
  15. static  void  e4push_operator(char), e4push_check(void), e4push_double(double),
  16.           e4push_long(long), e4push_char(char), e4push_str(char *, int ) ;
  17. static  char  e4pop_operator(void) ;
  18.  
  19. static char  *result_bottom, *operator, *operator_top, *operator_bottom,
  20.          *source, *err_source ;
  21. extern int    v4cur_base ;
  22.  
  23. extern char  *v4eval_space ;
  24. extern char  *v4eval_end ;
  25.  
  26. static union
  27. {
  28.    char   *ch ;
  29.    double *doub ;
  30.    int      *i ;
  31.    long   *l ;
  32. }  result ;
  33.  
  34. static int  e4funct_num(str, len)
  35. char * str ;   /* the function name */
  36. int    len ;   /* the number of characters in the function name */
  37. {
  38.    char u_str[10] ;
  39.  
  40.    strncpy( u_str, str, sizeof( u_str)    )  ;
  41.    u_str[9] = '\0' ;
  42.    strupr( u_str ) ;
  43.  
  44.    if (len==3)
  45.    {
  46.       if (strncmp(u_str,"STR",3) == 0 )   return( F_STR ) ;
  47.       if (strncmp(u_str,"VAL",3) == 0 )   return( F_VAL ) ;
  48.       if (strncmp(u_str,"IIF",3) == 0 )   return( F_IIF) ;
  49.       if (strncmp(u_str,"DEL",3) == 0 )   return( F_DEL) ;
  50.    }
  51.    if (len==4)
  52.    {
  53.       if (strncmp(u_str, "DATE", 4) == 0)  return( F_DATE ) ;
  54.       if (strncmp(u_str, "DTOC", 4) == 0)  return( F_DTOC ) ;
  55.       if (strncmp(u_str, "DTOS", 4) == 0)  return( F_DTOS ) ;
  56.       if (strncmp(u_str, "CTOD", 4) == 0)  return( F_CTOD ) ;
  57.       if (strncmp(u_str, "TIME", 4) == 0)  return( F_TIME ) ;
  58.    }
  59.    if (len==5)
  60.    {
  61.       if (strncmp(u_str,"RECNO",5) == 0)   return( F_RECNO) ;
  62.       if (strncmp(u_str,"UPPER",5) == 0)   return( F_UPPER) ;
  63.    }
  64.    if (len==6)
  65.       if (strncmp(u_str,"SUBSTR",6) == 0)  return( F_SUBSTR ) ;
  66.    if (len==7)
  67.       if (strncmp(u_str,"DELETED",7) == 0) return( F_DELETED) ;
  68.    if (len==8)
  69.       if (strncmp(u_str,"RECCOUNT",8)== 0) return(F_RECCOUNT) ;
  70.  
  71.    return( Q_NO_FUNCTION ) ;
  72. }
  73.  
  74. static void  e4push_operator( operator_code)
  75. char operator_code ;
  76. {
  77.    *(--operator) = operator_code ;
  78.    if (operator< operator_bottom)
  79.    {
  80.        u4error( E_OVERFLOW, err_source, (char *) 0 ) ;
  81.    }
  82. }
  83.  
  84. static char e4pop_operator()
  85. {
  86.    if (operator>= operator_top)  return( '\0') ;
  87.    return ( *(operator++)  ) ;
  88. }
  89.  
  90. static int  e4cur_operator()
  91. {
  92.    if (operator>= operator_top) return( Q_NO_FUNCTION ) ;
  93.    return( *operator) ;
  94. }
  95.  
  96. static void  e4push_check()
  97. {
  98.    if (result.ch< result_bottom)
  99.    {
  100.       u4error( E_OVERFLOW, err_source, (char *) 0) ;
  101.    }
  102. }
  103.  
  104. static  void  e4push_double( doub)
  105. double doub ;
  106. {
  107.    *(--result.doub)  = doub ;
  108.    e4push_char( (char) I_NUM) ;
  109.    e4push_check() ;
  110. }
  111.  
  112. static void  e4push_long( l )
  113. long l ;
  114. {
  115.    *(--result.l) = l ;
  116.    e4push_check() ;
  117. }
  118.  
  119. static void  e4push_char ( ch)
  120. char ch ;
  121. {
  122.    *(--result.ch) = ch ;
  123.    e4push_check() ;
  124. }
  125.  
  126. static void  e4push_str( str, len)
  127. char * str ;
  128. int len ;
  129. {
  130.    if (len> 255 || len< 0)
  131.    {
  132.        u4error( E_OVERFLOW, err_source, (char *) 0) ;
  133.    }
  134.    result.ch -= len ;
  135.    e4push_check() ;
  136.    memmove( result.ch, str, len) ;
  137.    e4push_char( (char) len ) ;
  138.    e4push_char( I_CHAR )     ;
  139. }
  140.  
  141.  
  142. /* Returns  OK, ERROR */
  143. static  int e4parse_function()
  144. {
  145.    int i, f_num, num_param ;
  146.  
  147.    i= 0 ;
  148.    while ( u4name_char( source[i] )  ) i++ ;
  149.  
  150.    f_num =  e4funct_num( source, i) ;
  151.    if (f_num== Q_NO_FUNCTION)
  152.    {
  153.       u4error( E_FUNCTION, err_source, (char *) 0) ;
  154.       return(ERROR) ;
  155.    }
  156.  
  157.    source += i ;
  158.    while (*source != '(') source++ ;
  159.    source++ ;
  160.  
  161.    e4push_operator( Q_L_BRACKET ) ;
  162.  
  163.    num_param = 0 ;
  164.  
  165.    while ( 1 )
  166.    {
  167.       if (*source == '\0')
  168.       {
  169.      u4error( E_RIGHT, err_source, (char *) 0) ;
  170.      return(ERROR) ;
  171.       }
  172.       if (*source == ')')
  173.       {
  174.      source++;
  175.      break ;
  176.       }
  177.  
  178.       if ( e4parse_expr() == ERROR )  return( ERROR )  ;
  179.       num_param++ ;
  180.  
  181.       while (*source <= ' ' &&  *source>='\1') source++ ;
  182.       if (*source == ')')
  183.       {
  184.      source++;
  185.      break ;
  186.       }
  187.       if (*source != ',')
  188.       {
  189.      u4error( E_EXPECT, err_source, (char *) 0) ;
  190.      return(ERROR) ;
  191.       }
  192.       source ++ ;
  193.    }
  194.    e4pop_operator() ;  /* pop the left bracket */
  195.  
  196.    e4push_char( (char) num_param) ;
  197.    e4push_char( (char) f_num ) ;
  198.    return(  OK ) ;
  199. }
  200.  
  201.  
  202. /*  Returns:  OK, ERROR */
  203. static int  e4parse_value()
  204. {
  205.    while (*source <= ' ' && *source>= '\1') source++ ;
  206.  
  207.    /* expression */
  208.    if ( *source == '(')
  209.    {
  210.       ++source;
  211.       e4push_operator( Q_L_BRACKET) ;
  212.       if ( e4parse_expr() == ERROR)  return( ERROR ) ;
  213.       while (*source <= ' ' && *source >= '\1') source++ ;
  214.       if (*source++ != ')' )
  215.       {
  216.      u4error( E_RIGHT, err_source, (char *) 0) ;
  217.      return( ERROR ) ;
  218.       }
  219.       e4pop_operator() ;
  220.       return( OK ) ;
  221.    }
  222.  
  223.  
  224.    /* logical */
  225.    if (*source == '.')
  226.    {
  227.       char log_str[8] ;
  228.  
  229.       strncpy( log_str, source, 7) ;
  230.       log_str[7] = '\0' ;
  231.       strupr( log_str) ;
  232.       if (strncmp(log_str, ".TRUE.", 6) == 0)
  233.       {
  234.      e4push_char( I_TRUE) ;
  235.      source += 6 ;
  236.      return( OK) ;
  237.       }
  238.       if (strncmp(log_str, ".FALSE.", 7) == 0)
  239.       {
  240.      e4push_char( I_FALSE) ;
  241.      source += 7 ;
  242.      return ( OK) ;
  243.       }
  244.       if (strncmp(log_str, ".T.", 3) == 0)
  245.       {
  246.      e4push_char( I_TRUE) ;
  247.      source += 3 ;
  248.      return ( OK) ;
  249.       }
  250.       if (strncmp( log_str, ".F.", 3) == 0)
  251.       {
  252.      e4push_char( I_FALSE) ;
  253.      source += 3;
  254.      return ( OK) ;
  255.       }
  256.       if (strncmp( log_str, ".NOT.", 5) == 0)
  257.       {
  258.      /* special case of a one operand operator */
  259.      source += 5 ;
  260.      if ( e4parse_value() == ERROR) return( ERROR) ;
  261.      e4push_char( L_NOT) ;
  262.      return ( OK) ;
  263.       }
  264.    }
  265.  
  266.  
  267.    /* function or base/field */
  268.    if (u4name_char(*source) )
  269.    {  /* Must be a function or a  base,field */
  270.       char b_name[9], f_name[11] ;
  271.       int  save_base, i, j ;
  272.       long f_num ;
  273.  
  274.       i=0 ;
  275.       while ( u4name_char( source[i] ) ) i++ ;
  276.       j=i ;
  277.       while ( source[j] <= ' ' && source[j] >= '\1') j++;
  278.  
  279.       /* Function */
  280.       if    ( source[j] == '(')  return( e4parse_function() ) ;
  281.  
  282.       save_base = v4cur_base ;
  283.       if    ( source[i] == '-' && source[i+1] == '>')
  284.       {
  285.      memmove(b_name, source, i) ;
  286.      b_name[i] = '\0' ;
  287.  
  288.      v4cur_base =  d4ref( b_name) ;
  289.      if (v4cur_base< 0)
  290.      {
  291.         v4cur_base =  save_base ;
  292.         u4error( E_BASE_NAME, err_source, (char *) 0 ) ;
  293.         return(ERROR) ;
  294.      }
  295.      source += (i+2) ;
  296.      i = 0 ;
  297.      while ( u4name_char( source[i]) ) i++ ;
  298.       }
  299.       if (i<= 10)
  300.       {
  301.      memmove(f_name, source, i) ;
  302.      f_name[i]  =  '\0' ;
  303.      f_num        =  f4ref( f_name) ;
  304.      if (f_num>=0)
  305.      {
  306.         source += i ;
  307.  
  308.         e4push_long( f_num) ;
  309.         e4push_char( F_BASE_FIELD) ;
  310.         v4cur_base =  save_base ;
  311.         return( OK ) ;
  312.      }
  313.       }
  314.       v4cur_base =  save_base ;
  315.    }
  316.  
  317.    /* real */
  318.    if (*source>='0' && *source<='9' || *source == '-' || *source == '+')
  319.    {
  320.       e4push_double(strtod(source, &source) ) ;
  321.       if ( strncmp(source-1, ".AND.",5) == 0 || strncmp(source-1, ".OR.",4) == 0 ||
  322.        strncmp(source-1, ".NOT.",5) == 0 )   source-- ;
  323.       return( OK ) ;
  324.    }
  325.    /* string */
  326.    if (*source == '\'' || *source == '\"')
  327.    {
  328.       char end_char, *on ;
  329.       int  len ;
  330.  
  331.       on = source ;
  332.       end_char = *on++ ;
  333.       len = 0 ;
  334.       while (on[len] != end_char && on[len] != '\0') len++ ;
  335.  
  336.       if (on[len] == '\0')
  337.       {
  338.      u4error( E_STRING_LONG, err_source, (char *) 0 ) ;
  339.      return(ERROR) ;
  340.       }
  341.  
  342.       e4push_str( ++source, len) ;
  343.       source += len+1;
  344.       return( OK) ;
  345.    }
  346.    u4error( E_VALUE, err_source, (char *) 0) ;
  347.    return( ERROR) ;
  348. }
  349.  
  350.  
  351. /*    Looks at the input string and returns and puts a character code on the
  352.    result stack corresponding to the next operator.  The operators all operate
  353.    on two operands.  Ex. +,-,*,/, >=, <, .AND., ...
  354.  
  355.       If the operator is ambiguous, return the arithmatic choice.
  356.  
  357.    Returns DONE, OK, ERROR
  358. */
  359.  
  360. static int  e4get_operator(op_return)
  361. char *op_return ;
  362. {
  363.    char  op ;
  364.  
  365.    op = '\xFF' ;
  366.  
  367.    while (*source <= ' ' && *source >= '\1' ) source++ ;
  368.    if (*source=='\0' || *source==')' || *source==',') return(DONE) ;
  369.  
  370.    switch(*source)
  371.    {
  372.       case '+':
  373.      op =    A_ADD ;
  374.      source++;
  375.      break ;
  376.       case '-':
  377.      op =  A_SUBTRACT ;
  378.      source++;
  379.      break ;
  380.  
  381.       case '/':
  382.      op =  A_DIVIDE ;
  383.      source++;
  384.      break ;
  385.       case '*':
  386.      source++ ;
  387.      #ifndef UNIX
  388.      if ( *source == '*')
  389.      {
  390.         op =  A_POWER ;
  391.         source ++ ;
  392.      }
  393.      else
  394.      #endif
  395.         op =  A_MULTIPLY ;
  396.      break ;
  397.       #ifndef UNIX
  398.       case '^':
  399.      op = A_POWER ;
  400.      source++ ;
  401.       #endif
  402.       case '.':
  403.      if (strnicmp(source, ".AND.", 5) == 0)
  404.      {
  405.         op = L_AND ;
  406.         source += 5 ;
  407.      }
  408.      if (strnicmp(source, ".OR.", 4) == 0)
  409.      {
  410.         op = L_OR ;
  411.         source += 4 ;
  412.      }
  413.      if (strnicmp(source, ".NOT.", 5) == 0)
  414.      {
  415.         op = L_NOT ;
  416.         source += 5 ;
  417.      }
  418.      break ;
  419.       case '<':
  420.      source++ ;
  421.      if (*source == '=' || *source == '>')
  422.      {
  423.         if (*source == '=')
  424.            op =  R_LE;
  425.         else
  426.            op =  R_NE ;
  427.         source++ ;
  428.      }
  429.      else
  430.         op = R_LT;
  431.      break ;
  432.       case '>':
  433.      source++ ;
  434.      if (*source == '=')
  435.      {
  436.         op =  R_GE ;
  437.         source ++ ;
  438.      }
  439.      else
  440.         op = R_GT ;
  441.      break ;
  442.       case '#':
  443.      op = R_NE ;
  444.      source++ ;
  445.      break ;
  446.       case '=':
  447.      op= R_EQ;
  448.      source++;
  449.      break;
  450.       case '$':
  451.      op = R_SUB_COMPARE;
  452.      source++;
  453.      break ;
  454.    }
  455.  
  456.    if ( op == '\xFF')
  457.    {
  458.       u4error( E_OPERATOR, err_source, (char *) 0) ;
  459.       return( ERROR ) ;
  460.    }
  461.    else
  462.    {
  463.       *op_return = op ;
  464.       return( OK) ;
  465.    }
  466. }
  467.  
  468.  
  469.  
  470. /*
  471.    Parses an expression constisting of     value [[operator value] ...]
  472.    The expression is ended by a ')', a ',' or a '\0'.
  473.    Operators are only popped until a '(', a ',' or the start of the stack.
  474.    Left to right evaluation for operators of equal priority.
  475.  
  476.       An ambiguous operator is one which can be interpreted differently
  477.    depending on its operands.  However, its operands depend on the
  478.    priority of the operators and the evaluation order.    Fortunately, the
  479.    priority of an ambigous operator is constant regardless of its
  480.    interpretation.  Consequently, the evaluation order is determined first.
  481.    Then ambiguous operators can be exactly determined.
  482.  
  483.    Ambigous operators:    +, -,  >, <, <=, >=, =, <>, #
  484.  
  485.    Return
  486.  
  487.        0  Normal
  488.       -1  Error
  489. */
  490. static int e4parse_expr ( )
  491. {
  492.    int rc ;
  493.    char op_value ;
  494.  
  495.    if ( ERROR == e4parse_value() )  return( ERROR ) ;
  496.  
  497.    while(1)
  498.    {
  499.       rc =  e4get_operator(&op_value) ;
  500.       if (rc  == ERROR)  return(ERROR) ;
  501.       if (rc  == DONE)
  502.       {
  503.      while( e4cur_operator() != Q_L_BRACKET
  504.          && e4cur_operator() != Q_COMMA
  505.          && e4cur_operator() != Q_NO_FUNCTION )
  506.      {
  507.         e4push_char( e4pop_operator() ) ;
  508.      }
  509.      return( OK) ;
  510.       }
  511.  
  512.       /* Everything with a higher or equal priority than 'op_value' must be
  513.      exectuted first. (equal because of left to right evaluation order)
  514.      Consequently, all high priority operators are sent to the result
  515.      stack.
  516.       */
  517.       while( e4priority(op_value) <=  e4priority( (char) e4cur_operator())   )
  518.       {
  519.      e4push_char( e4pop_operator() ) ;
  520.       }
  521.       e4push_operator( op_value) ;
  522.  
  523.       if ( e4parse_value() == ERROR) return(ERROR) ;
  524.    }
  525. }
  526.  
  527.  
  528. /*
  529.    e4parse
  530.  
  531.    Parameter Name    Type      Purpose
  532.  
  533.    base_ref         int       The expression will be parsed assuming
  534.                    'base_ref' refers to the active database.
  535.    expr_ptr         char *    Points to the source expression.
  536.    compile_ptr_ptr   char **   The value of the memory allocated
  537.                    compile string will be returned through
  538.                    'compile_ptr_ptr'.
  539.    Function Returns
  540.  
  541.       >=0   The length of the compiled expression
  542.        <0   Error
  543. */
  544.  
  545. e4parse ( expr_ptr, compile_ptr_ptr )
  546. char  *expr_ptr ;
  547. char **compile_ptr_ptr ;
  548. {
  549.    #define OPERATOR_LEN  64
  550.    int       len_used ;
  551.  
  552.    err_source = source =  expr_ptr ;
  553.  
  554.    /*  set up the stack pointers */
  555.    operator  = operator_top = v4eval_space+ OPERATOR_LEN ;
  556.    result.ch = v4eval_end ;
  557.    operator_bottom = v4eval_space ;
  558.    result_bottom   = v4eval_space+ OPERATOR_LEN ;
  559.  
  560.    if ( e4parse_expr() == ERROR )  return( -1) ;
  561.    if ( e4cur_operator() != Q_NO_FUNCTION)
  562.    {
  563.       u4error( E_COMPLETE, expr_ptr, (char *) 0) ;
  564.       return(-1) ;
  565.    }
  566.  
  567.    e4push_str( expr_ptr, strlen(expr_ptr) +1) ;
  568.    e4push_double( (double) v4cur_base) ;
  569.  
  570.    len_used =  (int) (v4eval_end - result.ch) ;
  571.    *compile_ptr_ptr =  h4alloc( len_used) ;
  572.    if ( *compile_ptr_ptr == (char *) 0 )   return( -1) ;
  573.  
  574.    memcpy( *compile_ptr_ptr, result.ch, len_used) ;
  575.  
  576.    return( len_used ) ;
  577. }
  578.  
  579.