home *** CD-ROM | disk | FTP | other *** search
-
- /* e4parse.c (c)Copyright Sequiter Software Inc., 1987, 1988, 1989. All rights reserved.
-
- */
-
- #include "d4base.h"
- #include "u4error.h"
- #include "e4parse.h"
-
- #include <string.h>
- #include <stdlib.h>
-
- static int e4parse_expr(void), e4funct_num(char *,int), e4cur_operator(void),
- e4parse_function(void), e4parse_value(void), e4get_operator(char *) ;
- static void e4push_operator(char), e4push_check(void), e4push_double(double),
- e4push_long(long), e4push_char(char), e4push_str(char *, int ) ;
- static char e4pop_operator(void) ;
-
- static char *result_bottom, *operator, *operator_top, *operator_bottom,
- *source, *err_source ;
- extern int v4cur_base ;
-
- extern char *v4eval_space ;
- extern char *v4eval_end ;
-
- static union
- {
- char *ch ;
- double *doub ;
- int *i ;
- long *l ;
- } result ;
-
- static int e4funct_num(str, len)
- char * str ; /* the function name */
- int len ; /* the number of characters in the function name */
- {
- char u_str[10] ;
-
- strncpy( u_str, str, sizeof( u_str) ) ;
- u_str[9] = '\0' ;
- strupr( u_str ) ;
-
- if (len==3)
- {
- if (strncmp(u_str,"STR",3) == 0 ) return( F_STR ) ;
- if (strncmp(u_str,"VAL",3) == 0 ) return( F_VAL ) ;
- if (strncmp(u_str,"IIF",3) == 0 ) return( F_IIF) ;
- if (strncmp(u_str,"DEL",3) == 0 ) return( F_DEL) ;
- }
- if (len==4)
- {
- if (strncmp(u_str, "DATE", 4) == 0) return( F_DATE ) ;
- if (strncmp(u_str, "DTOC", 4) == 0) return( F_DTOC ) ;
- if (strncmp(u_str, "DTOS", 4) == 0) return( F_DTOS ) ;
- if (strncmp(u_str, "CTOD", 4) == 0) return( F_CTOD ) ;
- if (strncmp(u_str, "TIME", 4) == 0) return( F_TIME ) ;
- }
- if (len==5)
- {
- if (strncmp(u_str,"RECNO",5) == 0) return( F_RECNO) ;
- if (strncmp(u_str,"UPPER",5) == 0) return( F_UPPER) ;
- }
- if (len==6)
- if (strncmp(u_str,"SUBSTR",6) == 0) return( F_SUBSTR ) ;
- if (len==7)
- if (strncmp(u_str,"DELETED",7) == 0) return( F_DELETED) ;
- if (len==8)
- if (strncmp(u_str,"RECCOUNT",8)== 0) return(F_RECCOUNT) ;
-
- return( Q_NO_FUNCTION ) ;
- }
-
- static void e4push_operator( operator_code)
- char operator_code ;
- {
- *(--operator) = operator_code ;
- if (operator< operator_bottom)
- {
- u4error( E_OVERFLOW, err_source, (char *) 0 ) ;
- }
- }
-
- static char e4pop_operator()
- {
- if (operator>= operator_top) return( '\0') ;
- return ( *(operator++) ) ;
- }
-
- static int e4cur_operator()
- {
- if (operator>= operator_top) return( Q_NO_FUNCTION ) ;
- return( *operator) ;
- }
-
- static void e4push_check()
- {
- if (result.ch< result_bottom)
- {
- u4error( E_OVERFLOW, err_source, (char *) 0) ;
- }
- }
-
- static void e4push_double( doub)
- double doub ;
- {
- *(--result.doub) = doub ;
- e4push_char( (char) I_NUM) ;
- e4push_check() ;
- }
-
- static void e4push_long( l )
- long l ;
- {
- *(--result.l) = l ;
- e4push_check() ;
- }
-
- static void e4push_char ( ch)
- char ch ;
- {
- *(--result.ch) = ch ;
- e4push_check() ;
- }
-
- static void e4push_str( str, len)
- char * str ;
- int len ;
- {
- if (len> 255 || len< 0)
- {
- u4error( E_OVERFLOW, err_source, (char *) 0) ;
- }
- result.ch -= len ;
- e4push_check() ;
- memmove( result.ch, str, len) ;
- e4push_char( (char) len ) ;
- e4push_char( I_CHAR ) ;
- }
-
-
- /* Returns OK, ERROR */
- static int e4parse_function()
- {
- int i, f_num, num_param ;
-
- i= 0 ;
- while ( u4name_char( source[i] ) ) i++ ;
-
- f_num = e4funct_num( source, i) ;
- if (f_num== Q_NO_FUNCTION)
- {
- u4error( E_FUNCTION, err_source, (char *) 0) ;
- return(ERROR) ;
- }
-
- source += i ;
- while (*source != '(') source++ ;
- source++ ;
-
- e4push_operator( Q_L_BRACKET ) ;
-
- num_param = 0 ;
-
- while ( 1 )
- {
- if (*source == '\0')
- {
- u4error( E_RIGHT, err_source, (char *) 0) ;
- return(ERROR) ;
- }
- if (*source == ')')
- {
- source++;
- break ;
- }
-
- if ( e4parse_expr() == ERROR ) return( ERROR ) ;
- num_param++ ;
-
- while (*source <= ' ' && *source>='\1') source++ ;
- if (*source == ')')
- {
- source++;
- break ;
- }
- if (*source != ',')
- {
- u4error( E_EXPECT, err_source, (char *) 0) ;
- return(ERROR) ;
- }
- source ++ ;
- }
- e4pop_operator() ; /* pop the left bracket */
-
- e4push_char( (char) num_param) ;
- e4push_char( (char) f_num ) ;
- return( OK ) ;
- }
-
-
- /* Returns: OK, ERROR */
- static int e4parse_value()
- {
- while (*source <= ' ' && *source>= '\1') source++ ;
-
- /* expression */
- if ( *source == '(')
- {
- ++source;
- e4push_operator( Q_L_BRACKET) ;
- if ( e4parse_expr() == ERROR) return( ERROR ) ;
- while (*source <= ' ' && *source >= '\1') source++ ;
- if (*source++ != ')' )
- {
- u4error( E_RIGHT, err_source, (char *) 0) ;
- return( ERROR ) ;
- }
- e4pop_operator() ;
- return( OK ) ;
- }
-
-
- /* logical */
- if (*source == '.')
- {
- char log_str[8] ;
-
- strncpy( log_str, source, 7) ;
- log_str[7] = '\0' ;
- strupr( log_str) ;
- if (strncmp(log_str, ".TRUE.", 6) == 0)
- {
- e4push_char( I_TRUE) ;
- source += 6 ;
- return( OK) ;
- }
- if (strncmp(log_str, ".FALSE.", 7) == 0)
- {
- e4push_char( I_FALSE) ;
- source += 7 ;
- return ( OK) ;
- }
- if (strncmp(log_str, ".T.", 3) == 0)
- {
- e4push_char( I_TRUE) ;
- source += 3 ;
- return ( OK) ;
- }
- if (strncmp( log_str, ".F.", 3) == 0)
- {
- e4push_char( I_FALSE) ;
- source += 3;
- return ( OK) ;
- }
- if (strncmp( log_str, ".NOT.", 5) == 0)
- {
- /* special case of a one operand operator */
- source += 5 ;
- if ( e4parse_value() == ERROR) return( ERROR) ;
- e4push_char( L_NOT) ;
- return ( OK) ;
- }
- }
-
-
- /* function or base/field */
- if (u4name_char(*source) )
- { /* Must be a function or a base,field */
- char b_name[9], f_name[11] ;
- int save_base, i, j ;
- long f_num ;
-
- i=0 ;
- while ( u4name_char( source[i] ) ) i++ ;
- j=i ;
- while ( source[j] <= ' ' && source[j] >= '\1') j++;
-
- /* Function */
- if ( source[j] == '(') return( e4parse_function() ) ;
-
- save_base = v4cur_base ;
- if ( source[i] == '-' && source[i+1] == '>')
- {
- memmove(b_name, source, i) ;
- b_name[i] = '\0' ;
-
- v4cur_base = d4ref( b_name) ;
- if (v4cur_base< 0)
- {
- v4cur_base = save_base ;
- u4error( E_BASE_NAME, err_source, (char *) 0 ) ;
- return(ERROR) ;
- }
- source += (i+2) ;
- i = 0 ;
- while ( u4name_char( source[i]) ) i++ ;
- }
- if (i<= 10)
- {
- memmove(f_name, source, i) ;
- f_name[i] = '\0' ;
- f_num = f4ref( f_name) ;
- if (f_num>=0)
- {
- source += i ;
-
- e4push_long( f_num) ;
- e4push_char( F_BASE_FIELD) ;
- v4cur_base = save_base ;
- return( OK ) ;
- }
- }
- v4cur_base = save_base ;
- }
-
- /* real */
- if (*source>='0' && *source<='9' || *source == '-' || *source == '+')
- {
- e4push_double(strtod(source, &source) ) ;
- if ( strncmp(source-1, ".AND.",5) == 0 || strncmp(source-1, ".OR.",4) == 0 ||
- strncmp(source-1, ".NOT.",5) == 0 ) source-- ;
- return( OK ) ;
- }
- /* string */
- if (*source == '\'' || *source == '\"')
- {
- char end_char, *on ;
- int len ;
-
- on = source ;
- end_char = *on++ ;
- len = 0 ;
- while (on[len] != end_char && on[len] != '\0') len++ ;
-
- if (on[len] == '\0')
- {
- u4error( E_STRING_LONG, err_source, (char *) 0 ) ;
- return(ERROR) ;
- }
-
- e4push_str( ++source, len) ;
- source += len+1;
- return( OK) ;
- }
- u4error( E_VALUE, err_source, (char *) 0) ;
- return( ERROR) ;
- }
-
-
- /* Looks at the input string and returns and puts a character code on the
- result stack corresponding to the next operator. The operators all operate
- on two operands. Ex. +,-,*,/, >=, <, .AND., ...
-
- If the operator is ambiguous, return the arithmatic choice.
-
- Returns DONE, OK, ERROR
- */
-
- static int e4get_operator(op_return)
- char *op_return ;
- {
- char op ;
-
- op = '\xFF' ;
-
- while (*source <= ' ' && *source >= '\1' ) source++ ;
- if (*source=='\0' || *source==')' || *source==',') return(DONE) ;
-
- switch(*source)
- {
- case '+':
- op = A_ADD ;
- source++;
- break ;
- case '-':
- op = A_SUBTRACT ;
- source++;
- break ;
-
- case '/':
- op = A_DIVIDE ;
- source++;
- break ;
- case '*':
- source++ ;
- #ifndef UNIX
- if ( *source == '*')
- {
- op = A_POWER ;
- source ++ ;
- }
- else
- #endif
- op = A_MULTIPLY ;
- break ;
- #ifndef UNIX
- case '^':
- op = A_POWER ;
- source++ ;
- #endif
- case '.':
- if (strnicmp(source, ".AND.", 5) == 0)
- {
- op = L_AND ;
- source += 5 ;
- }
- if (strnicmp(source, ".OR.", 4) == 0)
- {
- op = L_OR ;
- source += 4 ;
- }
- if (strnicmp(source, ".NOT.", 5) == 0)
- {
- op = L_NOT ;
- source += 5 ;
- }
- break ;
- case '<':
- source++ ;
- if (*source == '=' || *source == '>')
- {
- if (*source == '=')
- op = R_LE;
- else
- op = R_NE ;
- source++ ;
- }
- else
- op = R_LT;
- break ;
- case '>':
- source++ ;
- if (*source == '=')
- {
- op = R_GE ;
- source ++ ;
- }
- else
- op = R_GT ;
- break ;
- case '#':
- op = R_NE ;
- source++ ;
- break ;
- case '=':
- op= R_EQ;
- source++;
- break;
- case '$':
- op = R_SUB_COMPARE;
- source++;
- break ;
- }
-
- if ( op == '\xFF')
- {
- u4error( E_OPERATOR, err_source, (char *) 0) ;
- return( ERROR ) ;
- }
- else
- {
- *op_return = op ;
- return( OK) ;
- }
- }
-
-
-
- /*
- Parses an expression constisting of value [[operator value] ...]
- The expression is ended by a ')', a ',' or a '\0'.
- Operators are only popped until a '(', a ',' or the start of the stack.
- Left to right evaluation for operators of equal priority.
-
- An ambiguous operator is one which can be interpreted differently
- depending on its operands. However, its operands depend on the
- priority of the operators and the evaluation order. Fortunately, the
- priority of an ambigous operator is constant regardless of its
- interpretation. Consequently, the evaluation order is determined first.
- Then ambiguous operators can be exactly determined.
-
- Ambigous operators: +, -, >, <, <=, >=, =, <>, #
-
- Return
-
- 0 Normal
- -1 Error
- */
- static int e4parse_expr ( )
- {
- int rc ;
- char op_value ;
-
- if ( ERROR == e4parse_value() ) return( ERROR ) ;
-
- while(1)
- {
- rc = e4get_operator(&op_value) ;
- if (rc == ERROR) return(ERROR) ;
- if (rc == DONE)
- {
- while( e4cur_operator() != Q_L_BRACKET
- && e4cur_operator() != Q_COMMA
- && e4cur_operator() != Q_NO_FUNCTION )
- {
- e4push_char( e4pop_operator() ) ;
- }
- return( OK) ;
- }
-
- /* Everything with a higher or equal priority than 'op_value' must be
- exectuted first. (equal because of left to right evaluation order)
- Consequently, all high priority operators are sent to the result
- stack.
- */
- while( e4priority(op_value) <= e4priority( (char) e4cur_operator()) )
- {
- e4push_char( e4pop_operator() ) ;
- }
- e4push_operator( op_value) ;
-
- if ( e4parse_value() == ERROR) return(ERROR) ;
- }
- }
-
-
- /*
- e4parse
-
- Parameter Name Type Purpose
-
- base_ref int The expression will be parsed assuming
- 'base_ref' refers to the active database.
- expr_ptr char * Points to the source expression.
- compile_ptr_ptr char ** The value of the memory allocated
- compile string will be returned through
- 'compile_ptr_ptr'.
- Function Returns
-
- >=0 The length of the compiled expression
- <0 Error
- */
-
- e4parse ( expr_ptr, compile_ptr_ptr )
- char *expr_ptr ;
- char **compile_ptr_ptr ;
- {
- #define OPERATOR_LEN 64
- int len_used ;
-
- err_source = source = expr_ptr ;
-
- /* set up the stack pointers */
- operator = operator_top = v4eval_space+ OPERATOR_LEN ;
- result.ch = v4eval_end ;
- operator_bottom = v4eval_space ;
- result_bottom = v4eval_space+ OPERATOR_LEN ;
-
- if ( e4parse_expr() == ERROR ) return( -1) ;
- if ( e4cur_operator() != Q_NO_FUNCTION)
- {
- u4error( E_COMPLETE, expr_ptr, (char *) 0) ;
- return(-1) ;
- }
-
- e4push_str( expr_ptr, strlen(expr_ptr) +1) ;
- e4push_double( (double) v4cur_base) ;
-
- len_used = (int) (v4eval_end - result.ch) ;
- *compile_ptr_ptr = h4alloc( len_used) ;
- if ( *compile_ptr_ptr == (char *) 0 ) return( -1) ;
-
- memcpy( *compile_ptr_ptr, result.ch, len_used) ;
-
- return( len_used ) ;
- }
-