@@ -1,682 +0,0 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* $Id$
* Subroutines used to convert an infix expression to a postfix expression
*
* Author: Bob Dalesio
* Date: 12-12-86
*/
/*
* Subroutines
*
* Public
*
* sCalcPostfix convert an algebraic expression to symbolic postfix
* args
* pinfix the algebraic expression
* pp_postfix address of the symbolic postfix expression
* perror error information
* returns
* 0 successful
* -1 not successful
* Private routines for calcPostfix
*
* find_element finds a symbolic element in the expression element tbl
* args
* pbuffer pointer to the infix expression element
* pelement pointer to the expression element table entry
* pno_bytes pointer to the size of this element
* parg pointer to arg (used for fetch)
* returns
* TRUE element found
* FALSE element not found
*
* get_element finds the next expression element in the infix expr
* args
* pinfix pointer into the infix expression
* pelement pointer to the expression element table
* pno_bytes size of the element in the infix expression
* parg pointer to argument (used for fetch)
* returns
* FINE found an expression element
* VARIABLE found a database reference
* UNKNOWN_ELEMENT unknown element found in the infix expression
*/
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <ctype.h>
# include "dbDefs.h"
# define epicsExportSharedSymbols
# include "sCalcPostfix.h"
# include "sCalcPostfixPvt.h"
# define OVERRIDESTDCALC 0
# define DEBUG 0
volatile int sCalcPostfixDebug = 0 ;
/* declarations for postfix */
/* element types */
# define OPERAND 0
# define UNARY_OPERATOR 1
# define BINARY_OPERATOR 2
# define EXPR_TERM 3
# define COND 4
# define CLOSE_PAREN 5
# define CONDITIONAL 6
# define ELSE 7
# define SEPARATOR 8
# define TRASH 9
# define FLOAT_PT_CONST 10
# define MINUS_OPERATOR 11
# define STRING_CONST 12
# define CLOSE_BRACKET 13
# define CLOSE_CURLY 14
# define UNARY_MINUS_I_S_P 7
# define UNARY_MINUS_I_C_P 8
# define UNARY_MINUS_CODE UNARY_NEG
# define BINARY_MINUS_I_S_P 4
# define BINARY_MINUS_I_C_P 4
# define BINARY_MINUS_CODE SUB
/* parsing return values */
# define FINE 0
# define UNKNOWN_ELEMENT -1
# define END -2
/*
* element table
*
* structure of an element
*/
struct expression_element {
char element [ 10 ] ; /* character representation of an element */
char in_stack_pri ; /* priority in translation stack */
char in_coming_pri ; /* priority when first checking */
char type ; /* element type */
char code ; /* postfix representation */
} ;
/*
* NOTE: DO NOT CHANGE WITHOUT READING THIS NOTICE !!!!!!!!!!!!!!!!!!!!
* Because the routine that looks for a match in this table takes the first
* match it finds, elements whose designations are contained in other elements
* MUST come first in this list. (e.g. ABS will match A if A preceeds ABS and
* then try to find BS therefore ABS must be first in this list
*/
static struct expression_element elements [ ] = {
/*
element i_s_p i_c_p type_element internal_rep */
{ " ABS " , 7 , 8 , UNARY_OPERATOR , ABS_VAL } , /* absolute value */
{ " NOT " , 7 , 8 , UNARY_OPERATOR , UNARY_NEG } , /* unary negate */
{ " - " , 7 , 8 , MINUS_OPERATOR , UNARY_NEG } , /* unary negate (or binary op) */
{ " SQRT " , 7 , 8 , UNARY_OPERATOR , SQU_RT } , /* square root */
{ " SQR " , 7 , 8 , UNARY_OPERATOR , SQU_RT } , /* square root */
{ " EXP " , 7 , 8 , UNARY_OPERATOR , EXP } , /* exponential function */
{ " LOGE " , 7 , 8 , UNARY_OPERATOR , LOG_E } , /* log E */
{ " LN " , 7 , 8 , UNARY_OPERATOR , LOG_E } , /* log E */
{ " LOG " , 7 , 8 , UNARY_OPERATOR , LOG_10 } , /* log 10 */
{ " ACOS " , 7 , 8 , UNARY_OPERATOR , ACOS } , /* arc cosine */
{ " ASIN " , 7 , 8 , UNARY_OPERATOR , ASIN } , /* arc sine */
{ " ATAN2 " , 7 , 8 , UNARY_OPERATOR , ATAN2 } , /* arc tangent */
{ " ATAN " , 7 , 8 , UNARY_OPERATOR , ATAN } , /* arc tangent */
{ " MAX " , 7 , 8 , UNARY_OPERATOR , MAX_VAL } , /* maximum of 2 args */
{ " MIN " , 7 , 8 , UNARY_OPERATOR , MIN_VAL } , /* minimum of 2 args */
{ " CEIL " , 7 , 8 , UNARY_OPERATOR , CEIL } , /* smallest integer >= */
{ " FLOOR " , 7 , 8 , UNARY_OPERATOR , FLOOR } , /* largest integer <= */
{ " NINT " , 7 , 8 , UNARY_OPERATOR , NINT } , /* nearest integer */
{ " INT " , 7 , 8 , UNARY_OPERATOR , NINT } , /* nearest integer */
{ " COSH " , 7 , 8 , UNARY_OPERATOR , COSH } , /* hyperbolic cosine */
{ " COS " , 7 , 8 , UNARY_OPERATOR , COS } , /* cosine */
{ " SINH " , 7 , 8 , UNARY_OPERATOR , SINH } , /* hyperbolic sine */
{ " SIN " , 7 , 8 , UNARY_OPERATOR , SIN } , /* sine */
{ " TANH " , 7 , 8 , UNARY_OPERATOR , TANH } , /* hyperbolic tangent*/
{ " TAN " , 7 , 8 , UNARY_OPERATOR , TAN } , /* tangent */
{ " != " , 3 , 3 , BINARY_OPERATOR , NOT_EQ } , /* not equal */
{ " ! " , 7 , 8 , UNARY_OPERATOR , REL_NOT } , /* not */
{ " ~ " , 7 , 8 , UNARY_OPERATOR , BIT_NOT } , /* bitwise not */
{ " DBL " , 7 , 8 , UNARY_OPERATOR , TO_DOUBLE } , /* convert to double */
{ " STR " , 7 , 8 , UNARY_OPERATOR , TO_STRING } , /* convert to string */
{ " $P " , 7 , 8 , UNARY_OPERATOR , PRINTF } , /* formatted print to string */
{ " PRINTF " , 7 , 8 , UNARY_OPERATOR , PRINTF } , /* formatted print to string */
{ " $S " , 7 , 8 , UNARY_OPERATOR , SSCANF } , /* scan string argument */
{ " SSCANF " , 7 , 8 , UNARY_OPERATOR , SSCANF } , /* scan string argument */
{ " RNDM " , 0 , 0 , OPERAND , RANDOM } , /* Random Number */
{ " OR " , 1 , 1 , BINARY_OPERATOR , BIT_OR } , /* or */
{ " AND " , 2 , 2 , BINARY_OPERATOR , BIT_AND } , /* and */
{ " XOR " , 1 , 1 , BINARY_OPERATOR , BIT_EXCL_OR } , /* exclusive or */
{ " PI " , 0 , 0 , OPERAND , CONST_PI } , /* pi */
{ " D2R " , 0 , 0 , OPERAND , CONST_D2R } , /* pi/180 */
{ " R2D " , 0 , 0 , OPERAND , CONST_R2D } , /* 180/pi */
{ " S2R " , 0 , 0 , OPERAND , CONST_S2R } , /* arc-sec to radians: pi/(180*3600) */
{ " R2S " , 0 , 0 , OPERAND , CONST_R2S } , /* radians to arc-sec: (180*3600)/pi */
{ " 0 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 1 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 2 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 3 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 4 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 5 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 6 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 7 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 8 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " 9 " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " . " , 0 , 0 , FLOAT_PT_CONST , LITERAL } , /* flt pt constant */
{ " \" " , 0 , 0 , STRING_CONST , SLITERAL } , /* string constant */
{ " ' " , 0 , 0 , STRING_CONST , SLITERAL } , /* string constant */
{ " ? " , 0 , 0 , CONDITIONAL , COND_IF } , /* conditional */
{ " : " , 0 , 0 , CONDITIONAL , COND_ELSE } , /* else */
{ " ( " , 0 , 8 , UNARY_OPERATOR , PAREN } , /* open paren */
{ " [ " , 0 , 8 , BINARY_OPERATOR , SUBRANGE } , /* string subrange */
{ " { " , 0 , 8 , BINARY_OPERATOR , REPLACE } , /* string replace */
{ " ^ " , 6 , 6 , BINARY_OPERATOR , EXPON } , /* exponentiation */
{ " ** " , 6 , 6 , BINARY_OPERATOR , EXPON } , /* exponentiation */
{ " + " , 4 , 4 , BINARY_OPERATOR , ADD } , /* addition */
#if 0 /* "-" operator is overloaded; may be unary or binary */
{"-", 4, 4, BINARY_OPERATOR,SUB}, /* subtraction */
#endif
{ " * " , 5 , 5 , BINARY_OPERATOR , MULT } , /* multiplication */
{ " / " , 5 , 5 , BINARY_OPERATOR , DIV } , /* division */
{ " % " , 5 , 5 , BINARY_OPERATOR , MODULO } , /* modulo */
{ " , " , 0 , 0 , SEPARATOR , COMMA } , /* comma */
{ " ) " , 0 , 0 , CLOSE_PAREN , PAREN } , /* close paren */
{ " ] " , 0 , 0 , CLOSE_BRACKET , SUBRANGE } , /* close bracket */
{ " } " , 0 , 0 , CLOSE_CURLY , REPLACE } , /* close curly bracket */
{ " || " , 1 , 1 , BINARY_OPERATOR , REL_OR } , /* logical or */
{ " | " , 1 , 1 , BINARY_OPERATOR , BIT_OR } , /* bitwise or */
{ " && " , 2 , 2 , BINARY_OPERATOR , REL_AND } , /* logical and */
{ " & " , 2 , 2 , BINARY_OPERATOR , BIT_AND } , /* bitwise and */
{ " >> " , 2 , 2 , BINARY_OPERATOR , RIGHT_SHIFT } , /* right shift */
{ " >= " , 3 , 3 , BINARY_OPERATOR , GR_OR_EQ } , /* greater or equal*/
{ " > " , 3 , 3 , BINARY_OPERATOR , GR_THAN } , /* greater than */
{ " << " , 2 , 2 , BINARY_OPERATOR , LEFT_SHIFT } , /* left shift */
{ " <= " , 3 , 3 , BINARY_OPERATOR , LESS_OR_EQ } , /* less or equal to*/
{ " < " , 3 , 3 , BINARY_OPERATOR , LESS_THAN } , /* less than */
{ " # " , 3 , 3 , BINARY_OPERATOR , NOT_EQ } , /* not equal */
{ " == " , 3 , 3 , BINARY_OPERATOR , EQUAL } , /* equal */
{ " = " , 3 , 3 , BINARY_OPERATOR , EQUAL } , /* equal */
{ " " }
} ;
/*
* Element-table entry for "fetch" operation. This element is used for all
* named variables. Currently, letters A-Z (double) and AA-ZZ (string) are
* allowed. Lower and upper case letters mean the same thing.
*/
static struct expression_element fetch_element = {
" A " , 0 , 0 , OPERAND , FETCH , /* fetch var */
} ;
static struct expression_element fetch_string_element = {
" AA " , 0 , 0 , OPERAND , SFETCH , /* fetch var */
} ;
static int strncasecmpPrivate ( char * s1 , char * s2 , size_t n )
{
short i ;
for ( i = 0 ; i < ( short ) n & & ( * s1 | | * s2 ) ; i + + , s1 + + , s2 + + ) {
if ( toupper ( ( int ) * s1 ) > toupper ( ( int ) * s2 ) ) return ( 1 ) ;
if ( toupper ( ( int ) * s1 ) < toupper ( ( int ) * s2 ) ) return ( - 1 ) ;
}
return ( 0 ) ;
}
/*
* FIND_ELEMENT
*
* find the pointer to an entry in the element table
*/
static int find_element ( pbuffer , pelement , pno_bytes , parg )
char * pbuffer ;
struct expression_element * * pelement ;
short * pno_bytes , * parg ;
{
* parg = 0 ;
/* compare the string to each element in the element table */
* pelement = & elements [ 0 ] ;
while ( ( * pelement ) - > element [ 0 ] ! = NULL ) {
if ( strncasecmpPrivate ( pbuffer , ( * pelement ) - > element , strlen ( ( * pelement ) - > element ) ) = = 0 ) {
* pno_bytes + = strlen ( ( * pelement ) - > element ) ;
return ( TRUE ) ;
}
* pelement + = 1 ;
}
/* look for a variable reference */
/* double variables: ["a" - "z"], numbered 1-26 */
if ( isalpha ( ( int ) * pbuffer ) ) {
* pelement = & fetch_element ; /* fetch means "variable reference" (fetch or store) */
* parg = * pbuffer - ( isupper ( ( int ) * pbuffer ) ? ' A ' : ' a ' ) ;
* pno_bytes + = 1 ;
/* string variables: ["aa" - "zz"], numbered 1-26 */
if ( pbuffer [ 1 ] = = pbuffer [ 0 ] ) {
* pelement = & fetch_string_element ;
* pno_bytes + = 1 ;
}
return ( TRUE ) ;
}
if ( sCalcPostfixDebug ) printf ( " find_element: can't find '%s' \n " , pbuffer ) ;
return ( FALSE ) ;
}
/*
* GET_ELEMENT
*
* get an expression element
*/
static int get_element ( pinfix , pelement , pno_bytes , parg )
char * pinfix ;
struct expression_element * * pelement ;
short * pno_bytes , * parg ;
{
/* get the next expression element from the infix expression */
if ( * pinfix = = NULL ) return ( END ) ;
* pno_bytes = 0 ;
while ( * pinfix = = 0x20 ) {
* pno_bytes + = 1 ;
pinfix + + ;
}
if ( * pinfix = = NULL ) return ( END ) ;
if ( ! find_element ( pinfix , pelement , pno_bytes , parg ) )
return ( UNKNOWN_ELEMENT ) ;
if ( sCalcPostfixDebug > 5 ) printf ( " get_element: found element '%s', arg=%d \n " , ( * pelement ) - > element , * parg ) ;
return ( FINE ) ;
}
# if OVERRIDESTDCALC
/* Override standard EPICS expression evaluator (if we're loaded after it). */
long epicsShareAPI postfix ( const char * pinfix , char * ppostfix , short * perror )
{
char * my_ppostfix = NULL , * s , * d ;
long retval ;
retval = sCalcPostfix ( pinfix , & my_ppostfix , perror ) ;
if ( * my_ppostfix = = BAD_EXPRESSION ) {
* ppostfix = BAD_EXPRESSION ;
} else {
for ( s = my_ppostfix , d = ppostfix ; * s ! = END_STACK ; ) {
* d + + = * s + + ;
}
* d = * s ;
}
free ( my_ppostfix ) ;
return ( retval ) ;
}
# endif
/*
* sCalcPostFix
*
* convert an infix expression to a postfix expression
*/
# define MAX_POSTFIX_SIZE 100
long epicsShareAPI sCalcPostfix ( const char * pin , char * * pp_postfix , short * perror )
{
short no_bytes ;
short operand_needed ;
short new_expression ;
struct expression_element stack [ 80 ] ;
struct expression_element * pelement ;
struct expression_element * pstacktop ;
double constant ;
char c , * pposthold ;
char in_stack_pri , in_coming_pri , code ;
char * ppostfix , * ppostfixStart ;
short arg ;
char infix [ MAX_POSTFIX_SIZE ] ;
char * pinfix = & infix [ 0 ] ;
int len ;
if ( sCalcPostfixDebug ) printf ( " sCalcPostfix: entry \n " ) ;
len = strlen ( pin ) ;
if ( len > = MAX_POSTFIX_SIZE ) return ( - 1 ) ;
strcpy ( infix , pin ) ;
/* Allocate a buffer for the postfix expression. */
if ( * pp_postfix ) free ( * pp_postfix ) ; /* Free old buffer. */
ppostfix = calloc ( 5 * strlen ( pinfix ) + 7 , 1 ) ;
* pp_postfix = ppostfix ;
ppostfixStart = ppostfix + + ;
* ppostfixStart = BAD_EXPRESSION ;
* ppostfix = END_STACK ;
/* place the expression elements into postfix */
operand_needed = TRUE ;
new_expression = TRUE ;
* perror = 0 ;
if ( * pinfix = = 0 ) {
return ( 0 ) ;
}
pstacktop = & stack [ 0 ] ;
while ( get_element ( pinfix , & pelement , & no_bytes , & arg ) ! = END ) {
pinfix + = no_bytes ;
code = pelement - > code ;
if ( ( * ppostfixStart ! = USES_STRING ) & & ( ( code = = TO_STRING ) | |
( code = = PRINTF ) | | ( code = = SSCANF ) | | ( code = = SLITERAL ) | |
( code = = SUBRANGE ) | | ( code = = SFETCH ) ) ) {
* ppostfixStart = USES_STRING ;
}
switch ( pelement - > type ) {
case OPERAND :
if ( ! operand_needed ) {
* perror = 5 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operand to the expression */
* ppostfix + + = pelement - > code ;
/* if this is a variable reference, append variable number */
if ( ( pelement - > code = = ( char ) FETCH ) | | ( pelement - > code = = ( char ) SFETCH ) ) {
* ppostfix + + = arg ;
}
operand_needed = FALSE ;
new_expression = FALSE ;
break ;
case FLOAT_PT_CONST :
if ( ! operand_needed ) {
* perror = 5 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add constant to postfix expression */
* ppostfix + + = pelement - > code ;
pposthold = ppostfix ;
pinfix - = no_bytes ;
while ( * pinfix = = ' ' ) * ppostfix + + = * pinfix + + ;
while ( TRUE ) {
if ( ( * pinfix > = ' 0 ' & & * pinfix < = ' 9 ' ) | | * pinfix = = ' . ' ) {
* ppostfix + + = * pinfix ;
pinfix + + ;
} else if ( * pinfix = = ' E ' | | * pinfix = = ' e ' ) {
* ppostfix + + = * pinfix ;
pinfix + + ;
if ( * pinfix = = ' + ' | | * pinfix = = ' - ' ) {
* ppostfix + + = * pinfix ;
pinfix + + ;
}
} else break ;
}
* ppostfix + + = ' \0 ' ;
ppostfix = pposthold ;
if ( sscanf ( ppostfix , " %lg " , & constant ) ! = 1 ) {
* ppostfix = ' \0 ' ;
} else {
memcpy ( ppostfix , ( void * ) & constant , 8 ) ;
}
ppostfix + = 8 ;
operand_needed = FALSE ;
new_expression = FALSE ;
break ;
case STRING_CONST :
if ( ! operand_needed ) {
* perror = 5 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add string literal to the postfix expression */
* ppostfix + + = pelement - > code ;
c = pinfix [ - 1 ] ;
while ( * pinfix ! = c & & * pinfix ) * ppostfix + + = * pinfix + + ;
* ppostfix + + = ' \0 ' ;
if ( * pinfix ) pinfix + + ;
operand_needed = FALSE ;
new_expression = FALSE ;
break ;
case BINARY_OPERATOR :
if ( operand_needed ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operators of higher or equal priority to postfix expression */
while ( ( pstacktop > = & stack [ 1 ] ) & &
( pstacktop - > in_stack_pri > = pelement - > in_coming_pri ) ) {
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
/* add new operator to stack */
pstacktop + + ;
* pstacktop = * pelement ;
operand_needed = TRUE ;
break ;
case UNARY_OPERATOR :
if ( ! operand_needed ) {
* perror = 5 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operators of higher or equal priority to postfix expression */
while ( ( pstacktop > = & stack [ 1 ] ) & &
( pstacktop - > in_stack_pri > = pelement - > in_coming_pri ) ) {
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
/* add new operator to stack */
pstacktop + + ;
* pstacktop = * pelement ;
new_expression = FALSE ;
break ;
case MINUS_OPERATOR :
if ( operand_needed ) {
/* then assume minus was intended as a unary operator */
in_coming_pri = UNARY_MINUS_I_C_P ;
in_stack_pri = UNARY_MINUS_I_S_P ;
code = UNARY_MINUS_CODE ;
new_expression = FALSE ;
} else {
/* then assume minus was intended as a binary operator */
in_coming_pri = BINARY_MINUS_I_C_P ;
in_stack_pri = BINARY_MINUS_I_S_P ;
code = BINARY_MINUS_CODE ;
operand_needed = TRUE ;
}
/* add operators of higher or equal priority to postfix expression */
while ( ( pstacktop > = & stack [ 1 ] ) & &
( pstacktop - > in_stack_pri > = in_coming_pri ) ) {
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
/* add new operator to stack */
pstacktop + + ;
* pstacktop = * pelement ;
pstacktop - > in_stack_pri = in_stack_pri ;
pstacktop - > code = code ;
break ;
case SEPARATOR :
if ( operand_needed ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operators to postfix until open paren */
while ( ( pstacktop - > element [ 0 ] ! = ' ( ' ) & & ( pstacktop - > element [ 0 ] ! = ' [ ' )
& & ( pstacktop - > element [ 0 ] ! = ' { ' ) ) {
if ( pstacktop = = & stack [ 1 ] | | pstacktop = = & stack [ 0 ] ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
operand_needed = TRUE ;
break ;
case CLOSE_PAREN :
if ( operand_needed ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operators to postfix until matching paren */
while ( pstacktop - > element [ 0 ] ! = ' ( ' ) {
if ( pstacktop = = & stack [ 1 ] | | pstacktop = = & stack [ 0 ] ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
pstacktop - - ; /* remove ( from stack */
break ;
case CLOSE_BRACKET :
if ( operand_needed ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operators to postfix until matching bracket */
while ( pstacktop - > element [ 0 ] ! = ' [ ' ) {
if ( pstacktop = = & stack [ 1 ] | | pstacktop = = & stack [ 0 ] ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
/* add SUBRANGE operator to postfix */
if ( pstacktop = = & stack [ 0 ] ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
break ;
case CLOSE_CURLY :
if ( operand_needed ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operators to postfix until matching bracket */
while ( pstacktop - > element [ 0 ] ! = ' { ' ) {
if ( pstacktop = = & stack [ 1 ] | | pstacktop = = & stack [ 0 ] ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
/* add REPLACE operator to postfix */
if ( pstacktop = = & stack [ 0 ] ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
break ;
case CONDITIONAL :
if ( operand_needed ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add operators of higher priority to postfix expression */
while ( ( pstacktop > = & stack [ 1 ] ) & &
( pstacktop - > in_stack_pri > pelement - > in_coming_pri ) ) {
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
/* add new element to the postfix expression */
* ppostfix + + = pelement - > code ;
/* add : operator with COND_END code to stack */
if ( pelement - > element [ 0 ] = = ' : ' ) {
pstacktop + + ;
* pstacktop = * pelement ;
pstacktop - > code = COND_END ;
}
operand_needed = TRUE ;
break ;
case EXPR_TERM :
if ( operand_needed & & ! new_expression ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add all operators on stack to postfix */
while ( pstacktop > = & stack [ 1 ] ) {
if ( pstacktop - > element [ 0 ] = = ' ( ' ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
/* add new element to the postfix expression */
* ppostfix + + = pelement - > code ;
operand_needed = TRUE ;
new_expression = TRUE ;
break ;
default :
* perror = 8 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
}
if ( operand_needed ) {
* perror = 4 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
/* add all operators on stack to postfix */
while ( pstacktop > = & stack [ 1 ] ) {
if ( pstacktop - > element [ 0 ] = = ' ( ' ) {
* perror = 6 ;
* ppostfixStart = BAD_EXPRESSION ; return ( - 1 ) ;
}
* ppostfix + + = pstacktop - > code ;
pstacktop - - ;
}
* ppostfix + + = END_STACK ;
* ppostfix = ' \0 ' ;
if ( ppostfixStart [ 1 ] = = END_STACK )
* ppostfixStart = BAD_EXPRESSION ;
else if ( * ppostfixStart ! = USES_STRING )
* ppostfixStart = NO_STRING ;
return ( 0 ) ;
}