home *** CD-ROM | disk | FTP | other *** search
-
- /* e4parse.c (c)Copyright Sequiter Software Inc., 1987-1990. All rights reserved. */
-
- #include "p4misc.h"
- #include "d4all.h"
- #include "u4error.h"
- #include "e4parse.h"
-
- #include <string.h>
-
- extern E4FUNCTIONS v4functions[] ;
- extern int v4type ;
-
- static int e4parse_expr(void) ;
- static int e4lookup(char *,int,int,int) ;
- static int e4operator_cur(void) ;
- static int e4parse_function(void) ;
- static int e4parse_value(void) ;
- static int e4get_operator(int *) ;
- static int e4operator_off(void) ;
- static int e4field_function(long) ;
- static int e4type_check(char *) ;
-
- static void e4push_int(int) ;
- static void e4push_str(char *, int) ;
- static void e4push(void *, int, int) ;
- static void e4operator_put(int) ;
-
- static int *op_ptr ;
- static int op_used ;
- static char *source, *err_source ;
- static int result_len, result_used ;
-
- extern int v4cur_base ;
-
- extern char *v4eval_space ;
- extern int v4eval_len ;
-
- static char *result_ptr ;
-
- /* e4lookup, searches 'v4functions' for an operator or function.
-
- str - the function name
- len - the number of characters in the function name
-
- len <= 0
-
- Needs Exact Lookup. All of the characters in 'v4functions'
- must be present in 'str'.
-
- len > 0
-
- Only examines 'len' characters in 'str'. It needs an exact
- match on 'len' characters. If 'len <= 3', there cannot
- be any extra characters in 'v4functions'.
-
- Returns:
- >= 0 The index into v4functions.
- -1 Not Located
- */
-
- static int e4lookup( char *str, int len, int start_i, int end_i )
- {
- char u_str[20] ;
- int i, exact_lookup ;
-
- if ( len <= 0 )
- {
- exact_lookup = 1 ;
-
- /* Determine 'len' */
- for ( len=0; str[len] != ' ' && str[len] != '\000'; len++ ) ;
- }
- else
- exact_lookup = 0 ;
-
- if (len >= sizeof(u_str)) len = sizeof(u_str)-1 ;
- memcpy( u_str, str, (size_t) len ) ;
- u_str[len] = '\000' ;
- u4upper( u_str ) ;
-
- for( i=start_i; i<= end_i; i++)
- {
- if ( v4functions[i].code < 0 ) break ;
-
- if ( v4functions[i].name[0] == u_str[0] )
- {
- if ( exact_lookup )
- {
- if ( v4functions[i].name_len <= len && v4functions[i].name_len > 0 )
- if (memcmp(u_str, v4functions[i].name, (size_t) v4functions[i].name_len) == 0)
- return( i ) ;
- }
- else
- if ( memcmp(u_str, v4functions[i].name, (size_t) len) == 0)
- {
- if ( len >= 4 ) return( i ) ;
- if ( v4functions[i].name_len == len ) return(i) ;
- }
- }
- }
- return -1 ;
- }
-
-
- static void e4operator_put( int operator_code)
- {
- op_used += sizeof(operator_code) ;
- if ( op_used > OPERATOR_LEN )
- u4error( E_OVERFLOW, err_source, (char *) 0 ) ;
-
- *op_ptr++ = operator_code ;
- }
-
- static int e4operator_off()
- {
- if ( op_used == 0 ) return Q_NO_FUNCTION ;
- op_used -= sizeof(int) ;
- return ( *(--op_ptr) ) ;
- }
-
- static int e4operator_cur()
- {
- if ( op_used == 0 ) return( Q_NO_FUNCTION ) ;
- return( op_ptr[-1] ) ;
- }
-
- static void e4push( void *str, int str_len, int pointer_code )
- {
- int pointer_width ;
-
- if ( pointer_code == 0 )
- pointer_width = 0 ;
- else
- pointer_width = (int) sizeof(int) ;
-
- if ( result_used + str_len + pointer_width > result_len )
- u4error( E_OVERFLOW, err_source, (char *) 0) ;
-
- result_used = result_used+ str_len+ pointer_width ;
-
- if ( pointer_code != 0 )
- {
- memcpy( result_ptr, &pointer_code, sizeof(int) ) ;
- result_ptr += sizeof(int) ;
- }
-
- memcpy( result_ptr, str, (size_t) str_len ) ;
- result_ptr += str_len ;
- }
-
- static void e4push_int( int i )
- {
- e4push( &i, (int) sizeof(i), 0 ) ;
- }
-
- static void e4push_str( char *str, int len )
- {
- e4push( str, 0, I_STRING ) ;
- e4push( &len, (int) sizeof(len), 0 ) ;
- e4push( str, len, 0 ) ;
- }
-
-
- /* Returns 0, -1 (Error) */
- static int e4parse_function()
- {
- int i, f_num, num_parms ;
- double d ;
-
- i= 0 ;
- while ( u4name_char( source[i])) i++ ;
-
- f_num = e4lookup( source, i, FIRST_FUNCTION, 0x7FFF) ;
- if (f_num== Q_NO_FUNCTION)
- {
- u4error( E_FUNCTION, err_source, (char *) 0) ;
- return(-1) ;
- }
-
- source += i ;
- while (*source != '(') source++ ;
- source++ ;
-
- e4operator_put( Q_L_BRACKET ) ;
-
- num_parms = 0 ;
-
- for(;;)
- {
- if (*source == '\000')
- {
- u4error( E_RIGHT, err_source, (char *) 0) ;
- return(-1) ;
- }
- if (*source == ')')
- {
- source++;
- break ;
- }
-
- if ( e4parse_expr() == -1 ) return( -1 ) ;
- num_parms++ ;
-
- while (*source <= ' ' && *source>='\001') source++ ;
- if (*source == ')')
- {
- source++;
- break ;
- }
- if (*source != ',')
- {
- u4error( E_EXPECT, err_source, (char *) 0) ;
- return(-1) ;
- }
- source ++ ;
- }
- e4operator_off() ; /* pop the left bracket */
-
- if ( num_parms != v4functions[f_num].num_parms )
- {
- if ( strcmp( v4functions[f_num].name, "STR" ) == 0 )
- {
- if ( num_parms == 1 )
- {
- d = 10.0 ;
- e4push( &d, sizeof(double), I_DOUBLE ) ;
- num_parms++ ;
- }
- if ( num_parms == 2 )
- {
- d = 0.0 ;
- e4push( &d, sizeof(double), I_DOUBLE ) ;
- num_parms++ ;
- }
- }
- if ( strcmp( v4functions[f_num].name, "SUBSTR" ) == 0 )
- {
- if ( num_parms == 2 )
- {
- d = (double) 0x7FFF ;
- e4push( &d, sizeof(double), I_DOUBLE ) ;
- num_parms++ ;
- }
- }
- }
-
- if ( num_parms != v4functions[f_num].num_parms )
- {
- u4error( E_NUM_PARMS, "Expression", err_source, "Function", v4functions[f_num].name, (char *) 0 ) ;
- return -1 ;
- }
-
- e4push_int( f_num ) ;
- return( 0 ) ;
- }
-
-
- /* Returns: 0, -1 (Error) */
- static int e4parse_value()
- {
- while (*source <= ' ' && *source>= '\001') source++ ;
-
- /* expression */
- if ( *source == '(')
- {
- ++source;
- e4operator_put( Q_L_BRACKET) ;
- if ( e4parse_expr() == -1) return( -1 ) ;
- while (*source <= ' ' && *source >= '\001') source++ ;
- if (*source++ != ')' )
- {
- u4error( E_RIGHT, err_source, (char *) 0) ;
- return( -1 ) ;
- }
- e4operator_off() ;
- return( 0 ) ;
- }
-
- /* logical */
- if ( *source == '.' )
- {
- int i_functions ;
-
- i_functions = e4lookup( source, -1, FIRST_LOG, LAST_LOG ) ;
-
- if ( i_functions >= 0 )
- {
- source += v4functions[i_functions].name_len ;
-
- if ( strcmp( v4functions[i_functions].name, ".NOT." ) == 0 )
- /* special case of a one operand operator */
- if ( e4parse_expr() < 0 ) return( -1 ) ;
-
- e4push_int( i_functions ) ;
- return 0 ;
- }
- }
-
- /* real */
- if (*source>='0' && *source<='9' || *source == '-' || *source == '+' || *source == '.' )
- {
- double d ;
- int len ;
-
- for( len = 1;
- source[len] >= '0' && source[len] <= '9' || source[len] == '.';
- len++ ) ;
-
- d = c4atod( source, len ) ;
- e4push( &d, sizeof(d), I_DOUBLE ) ;
- source += len ;
-
- if ( strnicmp(source-1, ".AND.",5) == 0 || strnicmp(source-1, ".OR.",4) == 0 ||
- strnicmp(source-1, ".NOT.",5) == 0 ) source-- ;
- return( 0 ) ;
- }
-
- /* string */
- if (*source == '\'' || *source == '\"')
- {
- char end_char, *on ;
- int len ;
-
- on = source ;
- end_char = *on++ ;
- len = 0 ;
- while (on[len] != end_char && on[len] != '\000') len++ ;
-
- if (on[len] == '\000')
- {
- u4error( E_STRING_LONG, err_source, (char *) 0 ) ;
- return(-1) ;
- }
-
- e4push_str( ++source, len ) ;
- source += len+1 ;
- return( 0 ) ;
- }
-
- /* function or base/field */
- if (u4name_char(*source) )
- { /* Must be a function or a base,field */
- char b_name[258], 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] >= '\001') j++;
-
- /* Function */
- if ( source[j] == '(') return( e4parse_function() ) ;
-
- save_base = v4cur_base ;
- if ( source[i] == '-' && source[i+1] == '>')
- {
- memmove(b_name, source, (size_t) i) ;
- b_name[i] = '\000' ;
-
- v4cur_base = d4ref( b_name) ;
- if (v4cur_base< 0)
- {
- v4cur_base = save_base ;
- u4error( E_BASE_NAME, err_source, (char *) 0 ) ;
- return(-1) ;
- }
- source += (i+2) ;
- i = 0 ;
- while ( u4name_char( source[i]) ) i++ ;
- }
- if (i<= 10)
- {
- memmove(f_name, source, (size_t) i) ;
- f_name[i] = '\000' ;
- f_num = f4ref( f_name) ;
- if (f_num>=0)
- {
- source += i ;
-
- e4push_int( e4field_function(f_num) ) ;
- e4push( &f_num, sizeof(f_num), 0 ) ;
- v4cur_base = save_base ;
- return( 0 ) ;
- }
- }
- v4cur_base = save_base ;
- }
-
- u4error( E_VALUE, err_source, (char *) 0) ;
- return( -1) ;
- }
-
-
- /* 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 -2 (Done), 0, -1 (Error)
- */
-
- static int e4get_operator( int *op_return)
- {
- int op ;
-
- while (*source <= ' ' && *source >= '\001' ) source++ ;
- if (*source=='\000' || *source==')' || *source==',') return(-2) ; /* Done */
-
- op = e4lookup( source, -1, FIRST_OPERATOR, LAST_OPERATOR ) ;
-
- if ( op < 0 )
- {
- u4error( E_OPERATOR, err_source, (char *) 0) ;
- return( -1 ) ;
- }
- else
- {
- source += v4functions[op].name_len ;
- *op_return = op ;
- return( 0) ;
- }
- }
-
-
- /*
- Parses an expression constisting of value [[operator value] ...]
- The expression is ended by a ')', a ',' or a '\000'.
- 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 ;
- int op_value ;
-
- if ( e4parse_value() == -1 ) return(-1) ;
-
- for(;;)
- {
- rc = e4get_operator(&op_value) ;
- if (rc == -1) return(-1) ;
- if (rc == -2)
- {
- /* Done */
- while( e4operator_cur() != Q_L_BRACKET
- && e4operator_cur() != Q_COMMA
- && e4operator_cur() != Q_NO_FUNCTION )
- e4push_int( e4operator_off() ) ;
- return( 0) ;
- }
-
- /* 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 ( e4operator_cur() >= 0 )
- {
- if ( v4functions[op_value].priority <= v4functions[ e4operator_cur() ].priority )
- e4push_int( e4operator_off() ) ;
- else
- break ;
- }
- e4operator_put( op_value) ;
-
- if ( e4parse_value() == -1) return(-1) ;
- }
- }
-
-
- /*
- 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 void ** 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( char *expr_ptr, char **compile_ptr_ptr )
- {
- void *save_compile_ptr ;
-
- err_source = source = expr_ptr ;
-
- /* Set up the stack pointers */
- result_ptr = v4eval_space ;
- result_len = v4eval_len - OPERATOR_LEN ;
- result_used= 0 ;
-
- e4push_str( expr_ptr, (int) strlen(expr_ptr)+1 ) ;
- e4push( &v4cur_base, (int) sizeof(v4cur_base), 0 ) ;
-
- op_ptr = (int *) (v4eval_space + (v4eval_len-OPERATOR_LEN) ) ;
- op_used = 0 ;
-
- save_compile_ptr = result_ptr ;
-
- if ( e4parse_expr() == -1 ) return( -1) ;
- if ( e4operator_cur() != Q_NO_FUNCTION)
- {
- u4error( E_COMPLETE, expr_ptr, (char *) 0) ;
- return(-1) ;
- }
- e4push_int( -1 ) ;
-
- if ( e4type_check( (char *) save_compile_ptr) < 0 ) return -1 ;
-
- *compile_ptr_ptr = h4alloc( result_used) ;
- if ( *compile_ptr_ptr == (char *) 0 ) return( -1) ;
-
- memcpy( *compile_ptr_ptr, v4eval_space, (size_t) result_used ) ;
-
- return( result_used ) ;
- }
-
- typedef struct parse_parm_st
- {
- char *ptr ;
- int type ;
- } PARSE_PARM ;
-
- static int get_f_code(char *,PARSE_PARM *) ;
-
- static int get_f_code( char *f_code_ptr, PARSE_PARM *parms )
- {
- int i, p_no, flg, i_functions ;
-
- /* flg Values
- -1 - Error
- 0 - OK
- 1 - Conversion Required
- */
-
- memcpy( &i_functions, f_code_ptr, sizeof(int)) ;
-
- for ( i= i_functions; ; i++ )
- {
- if ( v4functions[i].code == 0 ||
- v4functions[i].code != v4functions[i_functions].code )
- break ;
-
- /* Check the Type Match */
- for ( p_no = 0, flg = 0; p_no < v4functions[i].num_parms; p_no++ )
- {
- int i_temp ;
-
- if ( v4functions[i].type[p_no] == parms[p_no].type ) continue ;
-
- memcpy( &i_temp, parms[p_no].ptr, sizeof(int) ) ;
-
- if ( v4functions[i].type[p_no] == T_NUM_DOUB )
- {
- if ( i_temp == I_FIELD_NUM_S )
- {
- flg = 1 ;
- continue ;
- }
- }
-
- if ( v4functions[i].type[p_no] == T_DATE_DOUB )
- {
- if ( i_temp == I_FIELD_DATE_S )
- {
- flg = 1 ;
- continue ;
- }
- }
-
- flg = -1 ; /* No Match */
- break ;
- }
-
- if ( flg >= 0 )
- {
- /* Success */
- if ( flg > 0 )
- {
- /* Parameter Change Required First */
- for ( p_no = 0, flg = 0; p_no < v4functions[i].num_parms; p_no++)
- {
- int i_temp ;
-
- if ( v4functions[i].type[p_no] == parms[i].type ) continue ;
-
- memcpy( &i_temp, parms[p_no].ptr, sizeof(int) ) ;
- if ( i_temp == I_FIELD_DATE_S )
- i_temp = I_FIELD_DATE_D ;
- else
- {
- if ( i_temp == I_FIELD_NUM_S )
- i_temp = I_FIELD_NUM_D ;
- }
- memcpy( parms[p_no].ptr, &i_temp, sizeof(int) ) ;
- }
- }
-
- memcpy( f_code_ptr, &i, sizeof(int) ) ;
- f_code_ptr += sizeof(int) ;
-
- parms[0].type = v4functions[i].return_type ;
- parms[0].ptr = f_code_ptr ;
-
- return( 0 ) ;
- }
- }
-
- u4error( E_TYPE, "Expression:", err_source, "",
- "Function:", v4functions[i_functions].name, (char *) 0) ;
- return( -1 ) ;
- }
-
- static int e4type_check( char *compile_ptr )
- {
- int f_code ;
- char *f_code_ptr ;
- int n_parms, len ;
- PARSE_PARM parms[PARM_STACK_SIZE] ;
-
- parms[0].type = 0 ;
-
- for ( n_parms= 0;; )
- {
- f_code_ptr = compile_ptr ;
- memcpy( &f_code, f_code_ptr, sizeof(int) ) ;
-
- if ( f_code == -1 )
- {
- if (n_parms != 1) u4error( E_INTERNAL, "e4type_check", err_source, (char *) 0 ) ;
- v4type = parms[0].type ;
- return 0 ;
- }
-
- if ( f_code <= LAST_IMMEDIATE )
- {
- parms[n_parms].type = v4functions[f_code].return_type ;
- parms[n_parms].ptr = compile_ptr ;
- compile_ptr += sizeof(int) ;
-
- if ( f_code <= LAST_I_FIELD )
- compile_ptr = compile_ptr + sizeof(long) ;
- else
- {
- if ( f_code == I_DOUBLE )
- len = sizeof(double) ;
- else
- {
- memcpy( &len, compile_ptr, sizeof(int) ) ;
- compile_ptr += sizeof(int) ;
- }
-
- compile_ptr += len ;
- }
- }
- else
- {
- n_parms -= v4functions[f_code].num_parms ;
- if ( n_parms < 0 )
- u4error( E_INTERNAL, "e4type_check", err_source, (char *) 0 ) ;
-
- if ( get_f_code( f_code_ptr, parms+ n_parms ) < 0 ) return -1 ;
- compile_ptr += sizeof(int) ;
- }
- n_parms++ ;
-
- if ( n_parms+1 >= PARM_STACK_SIZE )
- {
- u4error( E_OVERFLOW, err_source, (char *) 0 ) ;
- return -1 ;
- }
- }
- }
-
- static int e4field_function( long field_ref )
- {
- switch( f4type(field_ref) )
- {
- case 'C':
- return I_FIELD_STR ;
-
- case 'N':
- case 'F':
- return I_FIELD_NUM_S ;
-
- case 'D':
- return I_FIELD_DATE_S ;
-
- case 'L':
- return I_FIELD_LOG ;
- }
- return -1 ;
- }
-