/cfitsio/eval.y
Happy | 5837 lines | 5275 code | 562 blank | 0 comment | 0 complexity | 05e094fffb8f04f7bfaeec5c1e661f58 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- %{
- /************************************************************************/
- /* */
- /* CFITSIO Lexical Parser */
- /* */
- /* This file is one of 3 files containing code which parses an */
- /* arithmetic expression and evaluates it in the context of an input */
- /* FITS file table extension. The CFITSIO lexical parser is divided */
- /* into the following 3 parts/files: the CFITSIO "front-end", */
- /* eval_f.c, contains the interface between the user/CFITSIO and the */
- /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */
- /* input string and parses it into tokens and identifies the FITS */
- /* information required to evaluate the expression (ie, keywords and */
- /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */
- /* receives the FLEX output and determines and performs the actual */
- /* operations. The files eval_l.c and eval_y.c are produced from */
- /* running flex and bison on the files eval.l and eval.y, respectively. */
- /* (flex and bison are available from any GNU archive: see www.gnu.org) */
- /* */
- /* The grammar rules, rather than evaluating the expression in situ, */
- /* builds a tree, or Nodal, structure mapping out the order of */
- /* operations and expression dependencies. This "compilation" process */
- /* allows for much faster processing of multiple rows. This technique */
- /* was developed by Uwe Lammers of the XMM Science Analysis System, */
- /* although the CFITSIO implementation is entirely code original. */
- /* */
- /* */
- /* Modification History: */
- /* */
- /* Kent Blackburn c1992 Original parser code developed for the */
- /* FTOOLS software package, in particular, */
- /* the fselect task. */
- /* Kent Blackburn c1995 BIT column support added */
- /* Peter D Wilson Feb 1998 Vector column support added */
- /* Peter D Wilson May 1998 Ported to CFITSIO library. User */
- /* interface routines written, in essence */
- /* making fselect, fcalc, and maketime */
- /* capabilities available to all tools */
- /* via single function calls. */
- /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */
- /* create a run-time evaluation tree, */
- /* inspired by the work of Uwe Lammers, */
- /* resulting in a speed increase of */
- /* 10-100 times. */
- /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */
- /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */
- /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */
- /* allowing a purely vector-based usage */
- /* Craig B Markwardt Jun 2004 Add MEDIAN() function */
- /* Craig B Markwardt Jun 2004 Add SUM(), and MIN/MAX() for bit arrays */
- /* Craig B Markwardt Jun 2004 Allow subscripting of nX bit arrays */
- /* Craig B Markwardt Jun 2004 Implement statistical functions */
- /* NVALID(), AVERAGE(), and STDDEV() */
- /* for integer and floating point vectors */
- /* Craig B Markwardt Jun 2004 Use NULL values for range errors instead*/
- /* of throwing a parse error */
- /* Craig B Markwardt Oct 2004 Add ACCUM() and SEQDIFF() functions */
- /* Craig B Markwardt Feb 2005 Add ANGSEP() function */
- /* Craig B Markwardt Aug 2005 CIRCLE, BOX, ELLIPSE, NEAR and REGFILTER*/
- /* functions now accept vector arguments */
- /* Craig B Markwardt Sum 2006 Add RANDOMN() and RANDOMP() functions */
- /* Craig B Markwardt Mar 2007 Allow arguments to RANDOM and RANDOMN to*/
- /* determine the output dimensions */
- /* Craig B Markwardt Aug 2009 Add substring STRMID() and string search*/
- /* STRSTR() functions; more overflow checks*/
- /* */
- /************************************************************************/
- #define APPROX 1.0e-7
- #include "eval_defs.h"
- #include "region.h"
- #include <time.h>
- #include <stdlib.h>
- #ifndef alloca
- #define alloca malloc
- #endif
- /* Shrink the initial stack depth to keep local data <32K (mac limit) */
- /* yacc will allocate more space if needed, though. */
- #define YYINITDEPTH 100
- /***************************************************************/
- /* Replace Bison's BACKUP macro with one that fixes a bug -- */
- /* must update state after popping the stack -- and allows */
- /* popping multiple terms at one time. */
- /***************************************************************/
- #define YYNEWBACKUP(token, value) \
- do \
- if (yychar == YYEMPTY ) \
- { yychar = (token); \
- memcpy( &yylval, &(value), sizeof(value) ); \
- yychar1 = YYTRANSLATE (yychar); \
- while (yylen--) YYPOPSTACK; \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { yyerror ("syntax error: cannot back up"); YYERROR; } \
- while (0)
- /***************************************************************/
- /* Useful macros for accessing/testing Nodes */
- /***************************************************************/
- #define TEST(a) if( (a)<0 ) YYERROR
- #define SIZE(a) gParse.Nodes[ a ].value.nelem
- #define TYPE(a) gParse.Nodes[ a ].type
- #define OPER(a) gParse.Nodes[ a ].operation
- #define PROMOTE(a,b) if( TYPE(a) > TYPE(b) ) \
- b = New_Unary( TYPE(a), 0, b ); \
- else if( TYPE(a) < TYPE(b) ) \
- a = New_Unary( TYPE(b), 0, a );
- /***** Internal functions *****/
- #ifdef __cplusplus
- extern "C" {
- #endif
- static int Alloc_Node ( void );
- static void Free_Last_Node( void );
- static void Evaluate_Node ( int thisNode );
- static int New_Const ( int returnType, void *value, long len );
- static int New_Column( int ColNum );
- static int New_Offset( int ColNum, int offset );
- static int New_Unary ( int returnType, int Op, int Node1 );
- static int New_BinOp ( int returnType, int Node1, int Op, int Node2 );
- static int New_Func ( int returnType, funcOp Op, int nNodes,
- int Node1, int Node2, int Node3, int Node4,
- int Node5, int Node6, int Node7 );
- static int New_FuncSize( int returnType, funcOp Op, int nNodes,
- int Node1, int Node2, int Node3, int Node4,
- int Node5, int Node6, int Node7, int Size);
- static int New_Deref ( int Var, int nDim,
- int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 );
- static int New_GTI ( char *fname, int Node1, char *start, char *stop );
- static int New_REG ( char *fname, int NodeX, int NodeY, char *colNames );
- static int New_Vector( int subNode );
- static int Close_Vec ( int vecNode );
- static int Locate_Col( Node *this );
- static int Test_Dims ( int Node1, int Node2 );
- static void Copy_Dims ( int Node1, int Node2 );
- static void Allocate_Ptrs( Node *this );
- static void Do_Unary ( Node *this );
- static void Do_Offset ( Node *this );
- static void Do_BinOp_bit ( Node *this );
- static void Do_BinOp_str ( Node *this );
- static void Do_BinOp_log ( Node *this );
- static void Do_BinOp_lng ( Node *this );
- static void Do_BinOp_dbl ( Node *this );
- static void Do_Func ( Node *this );
- static void Do_Deref ( Node *this );
- static void Do_GTI ( Node *this );
- static void Do_REG ( Node *this );
- static void Do_Vector ( Node *this );
- static long Search_GTI ( double evtTime, long nGTI, double *start,
- double *stop, int ordered );
- static char saobox (double xcen, double ycen, double xwid, double ywid,
- double rot, double xcol, double ycol);
- static char ellipse(double xcen, double ycen, double xrad, double yrad,
- double rot, double xcol, double ycol);
- static char circle (double xcen, double ycen, double rad,
- double xcol, double ycol);
- static char bnear (double x, double y, double tolerance);
- static char bitcmp (char *bitstrm1, char *bitstrm2);
- static char bitlgte(char *bits1, int oper, char *bits2);
- static void bitand(char *result, char *bitstrm1, char *bitstrm2);
- static void bitor (char *result, char *bitstrm1, char *bitstrm2);
- static void bitnot(char *result, char *bits);
- static int cstrmid(char *dest_str, int dest_len,
- char *src_str, int src_len, int pos);
- static void yyerror(char *msg);
- #ifdef __cplusplus
- }
- #endif
- %}
- %union {
- int Node; /* Index of Node */
- double dbl; /* real value */
- long lng; /* integer value */
- char log; /* logical value */
- char str[MAX_STRLEN]; /* string value */
- }
- %token <log> BOOLEAN /* First 3 must be in order of */
- %token <lng> LONG /* increasing promotion for later use */
- %token <dbl> DOUBLE
- %token <str> STRING
- %token <str> BITSTR
- %token <str> FUNCTION
- %token <str> BFUNCTION /* Bit function */
- %token <str> IFUNCTION /* Integer function */
- %token <str> GTIFILTER
- %token <str> REGFILTER
- %token <lng> COLUMN
- %token <lng> BCOLUMN
- %token <lng> SCOLUMN
- %token <lng> BITCOL
- %token <lng> ROWREF
- %token <lng> NULLREF
- %token <lng> SNULLREF
- %type <Node> expr
- %type <Node> bexpr
- %type <Node> sexpr
- %type <Node> bits
- %type <Node> vector
- %type <Node> bvector
- %left ',' '=' ':' '{' '}'
- %right '?'
- %left OR
- %left AND
- %left EQ NE '~'
- %left GT LT LTE GTE
- %left '+' '-' '%'
- %left '*' '/'
- %left '|' '&'
- %right POWER
- %left NOT
- %left INTCAST FLTCAST
- %left UMINUS
- %left '['
- %right ACCUM DIFF
- %%
- lines: /* nothing ; was | lines line */
- | lines line
- ;
- line: '\n' {}
- | expr '\n'
- { if( $1<0 ) {
- yyerror("Couldn't build node structure: out of memory?");
- YYERROR; }
- gParse.resultNode = $1;
- }
- | bexpr '\n'
- { if( $1<0 ) {
- yyerror("Couldn't build node structure: out of memory?");
- YYERROR; }
- gParse.resultNode = $1;
- }
- | sexpr '\n'
- { if( $1<0 ) {
- yyerror("Couldn't build node structure: out of memory?");
- YYERROR; }
- gParse.resultNode = $1;
- }
- | bits '\n'
- { if( $1<0 ) {
- yyerror("Couldn't build node structure: out of memory?");
- YYERROR; }
- gParse.resultNode = $1;
- }
- | error '\n' { yyerrok; }
- ;
- bvector: '{' bexpr
- { $$ = New_Vector( $2 ); TEST($$); }
- | bvector ',' bexpr
- {
- if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
- $1 = Close_Vec( $1 ); TEST($1);
- $$ = New_Vector( $1 ); TEST($$);
- } else {
- $$ = $1;
- }
- gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
- = $3;
- }
- ;
- vector: '{' expr
- { $$ = New_Vector( $2 ); TEST($$); }
- | vector ',' expr
- {
- if( TYPE($1) < TYPE($3) )
- TYPE($1) = TYPE($3);
- if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
- $1 = Close_Vec( $1 ); TEST($1);
- $$ = New_Vector( $1 ); TEST($$);
- } else {
- $$ = $1;
- }
- gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
- = $3;
- }
- | vector ',' bexpr
- {
- if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
- $1 = Close_Vec( $1 ); TEST($1);
- $$ = New_Vector( $1 ); TEST($$);
- } else {
- $$ = $1;
- }
- gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
- = $3;
- }
- | bvector ',' expr
- {
- TYPE($1) = TYPE($3);
- if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
- $1 = Close_Vec( $1 ); TEST($1);
- $$ = New_Vector( $1 ); TEST($$);
- } else {
- $$ = $1;
- }
- gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
- = $3;
- }
- ;
- expr: vector '}'
- { $$ = Close_Vec( $1 ); TEST($$); }
- ;
- bexpr: bvector '}'
- { $$ = Close_Vec( $1 ); TEST($$); }
- ;
- bits: BITSTR
- {
- $$ = New_Const( BITSTR, $1, strlen($1)+1 ); TEST($$);
- SIZE($$) = strlen($1); }
- | BITCOL
- { $$ = New_Column( $1 ); TEST($$); }
- | BITCOL '{' expr '}'
- {
- if( TYPE($3) != LONG
- || OPER($3) != CONST_OP ) {
- yyerror("Offset argument must be a constant integer");
- YYERROR;
- }
- $$ = New_Offset( $1, $3 ); TEST($$);
- }
- | bits '&' bits
- { $$ = New_BinOp( BITSTR, $1, '&', $3 ); TEST($$);
- SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); }
- | bits '|' bits
- { $$ = New_BinOp( BITSTR, $1, '|', $3 ); TEST($$);
- SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); }
- | bits '+' bits
- {
- if (SIZE($1)+SIZE($3) >= MAX_STRLEN) {
- yyerror("Combined bit string size exceeds " MAX_STRLEN_S " bits");
- YYERROR;
- }
- $$ = New_BinOp( BITSTR, $1, '+', $3 ); TEST($$);
- SIZE($$) = SIZE($1) + SIZE($3);
- }
- | bits '[' expr ']'
- { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); }
- | bits '[' expr ',' expr ']'
- { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); }
- | bits '[' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); }
- | bits '[' expr ',' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); }
- | bits '[' expr ',' expr ',' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
- | NOT bits
- { $$ = New_Unary( BITSTR, NOT, $2 ); TEST($$); }
- | '(' bits ')'
- { $$ = $2; }
- ;
- expr: LONG
- { $$ = New_Const( LONG, &($1), sizeof(long) ); TEST($$); }
- | DOUBLE
- { $$ = New_Const( DOUBLE, &($1), sizeof(double) ); TEST($$); }
- | COLUMN
- { $$ = New_Column( $1 ); TEST($$); }
- | COLUMN '{' expr '}'
- {
- if( TYPE($3) != LONG
- || OPER($3) != CONST_OP ) {
- yyerror("Offset argument must be a constant integer");
- YYERROR;
- }
- $$ = New_Offset( $1, $3 ); TEST($$);
- }
- | ROWREF
- { $$ = New_Func( LONG, row_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
- | NULLREF
- { $$ = New_Func( LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
- | expr '%' expr
- { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '%', $3 );
- TEST($$); }
- | expr '+' expr
- { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '+', $3 );
- TEST($$); }
- | expr '-' expr
- { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '-', $3 );
- TEST($$); }
- | expr '*' expr
- { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '*', $3 );
- TEST($$); }
- | expr '/' expr
- { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '/', $3 );
- TEST($$); }
- | expr POWER expr
- { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, POWER, $3 );
- TEST($$); }
- | '+' expr %prec UMINUS
- { $$ = $2; }
- | '-' expr %prec UMINUS
- { $$ = New_Unary( TYPE($2), UMINUS, $2 ); TEST($$); }
- | '(' expr ')'
- { $$ = $2; }
- | expr '*' bexpr
- { $3 = New_Unary( TYPE($1), 0, $3 );
- $$ = New_BinOp( TYPE($1), $1, '*', $3 );
- TEST($$); }
- | bexpr '*' expr
- { $1 = New_Unary( TYPE($3), 0, $1 );
- $$ = New_BinOp( TYPE($3), $1, '*', $3 );
- TEST($$); }
- | bexpr '?' expr ':' expr
- {
- PROMOTE($3,$5);
- if( ! Test_Dims($3,$5) ) {
- yyerror("Incompatible dimensions in '?:' arguments");
- YYERROR;
- }
- $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
- 0, 0, 0, 0 );
- TEST($$);
- if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
- TYPE($1) = TYPE($3);
- if( ! Test_Dims($1,$$) ) {
- yyerror("Incompatible dimensions in '?:' condition");
- YYERROR;
- }
- TYPE($1) = BOOLEAN;
- if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
- }
- | bexpr '?' bexpr ':' expr
- {
- PROMOTE($3,$5);
- if( ! Test_Dims($3,$5) ) {
- yyerror("Incompatible dimensions in '?:' arguments");
- YYERROR;
- }
- $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
- 0, 0, 0, 0 );
- TEST($$);
- if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
- TYPE($1) = TYPE($3);
- if( ! Test_Dims($1,$$) ) {
- yyerror("Incompatible dimensions in '?:' condition");
- YYERROR;
- }
- TYPE($1) = BOOLEAN;
- if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
- }
- | bexpr '?' expr ':' bexpr
- {
- PROMOTE($3,$5);
- if( ! Test_Dims($3,$5) ) {
- yyerror("Incompatible dimensions in '?:' arguments");
- YYERROR;
- }
- $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
- 0, 0, 0, 0 );
- TEST($$);
- if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
- TYPE($1) = TYPE($3);
- if( ! Test_Dims($1,$$) ) {
- yyerror("Incompatible dimensions in '?:' condition");
- YYERROR;
- }
- TYPE($1) = BOOLEAN;
- if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
- }
- | FUNCTION ')'
- { if (FSTRCMP($1,"RANDOM(") == 0) { /* Scalar RANDOM() */
- srand( (unsigned int) time(NULL) );
- $$ = New_Func( DOUBLE, rnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
- } else if (FSTRCMP($1,"RANDOMN(") == 0) {/*Scalar RANDOMN()*/
- srand( (unsigned int) time(NULL) );
- $$ = New_Func( DOUBLE, gasrnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
- } else {
- yyerror("Function() not supported");
- YYERROR;
- }
- TEST($$);
- }
- | FUNCTION bexpr ')'
- { if (FSTRCMP($1,"SUM(") == 0) {
- $$ = New_Func( LONG, sum_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- } else if (FSTRCMP($1,"NELEM(") == 0) {
- $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
- } else if (FSTRCMP($1,"ACCUM(") == 0) {
- long zero = 0;
- $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
- } else {
- yyerror("Function(bool) not supported");
- YYERROR;
- }
- TEST($$);
- }
- | FUNCTION sexpr ')'
- { if (FSTRCMP($1,"NELEM(") == 0) {
- $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
- } else if (FSTRCMP($1,"NVALID(") == 0) {
- $$ = New_Func( LONG, nonnull_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- } else {
- yyerror("Function(str) not supported");
- YYERROR;
- }
- TEST($$);
- }
- | FUNCTION bits ')'
- { if (FSTRCMP($1,"NELEM(") == 0) {
- $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
- } else if (FSTRCMP($1,"NVALID(") == 0) { /* Bit arrays do not have NULL */
- $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
- } else if (FSTRCMP($1,"SUM(") == 0) {
- $$ = New_Func( LONG, sum_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- } else if (FSTRCMP($1,"MIN(") == 0) {
- $$ = New_Func( TYPE($2), /* Force 1D result */
- min1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- /* Note: $2 is a vector so the result can never
- be a constant. Therefore it will never be set
- inside New_Func(), and it is safe to set SIZE() */
- SIZE($$) = 1;
- } else if (FSTRCMP($1,"ACCUM(") == 0) {
- long zero = 0;
- $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
- } else if (FSTRCMP($1,"MAX(") == 0) {
- $$ = New_Func( TYPE($2), /* Force 1D result */
- max1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- /* Note: $2 is a vector so the result can never
- be a constant. Therefore it will never be set
- inside New_Func(), and it is safe to set SIZE() */
- SIZE($$) = 1;
- } else {
- yyerror("Function(bits) not supported");
- YYERROR;
- }
- TEST($$);
- }
- | FUNCTION expr ')'
- { if (FSTRCMP($1,"SUM(") == 0)
- $$ = New_Func( TYPE($2), sum_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"AVERAGE(") == 0)
- $$ = New_Func( DOUBLE, average_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"STDDEV(") == 0)
- $$ = New_Func( DOUBLE, stddev_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"MEDIAN(") == 0)
- $$ = New_Func( TYPE($2), median_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"NELEM(") == 0)
- $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
- else if (FSTRCMP($1,"NVALID(") == 0)
- $$ = New_Func( LONG, nonnull_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- else if ((FSTRCMP($1,"ACCUM(") == 0) && (TYPE($2) == LONG)) {
- long zero = 0;
- $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
- } else if ((FSTRCMP($1,"ACCUM(") == 0) && (TYPE($2) == DOUBLE)) {
- double zero = 0;
- $$ = New_BinOp( DOUBLE , $2, ACCUM, New_Const( DOUBLE, &zero, sizeof(zero) ));
- } else if ((FSTRCMP($1,"SEQDIFF(") == 0) && (TYPE($2) == LONG)) {
- long zero = 0;
- $$ = New_BinOp( LONG , $2, DIFF, New_Const( LONG, &zero, sizeof(zero) ));
- } else if ((FSTRCMP($1,"SEQDIFF(") == 0) && (TYPE($2) == DOUBLE)) {
- double zero = 0;
- $$ = New_BinOp( DOUBLE , $2, DIFF, New_Const( DOUBLE, &zero, sizeof(zero) ));
- } else if (FSTRCMP($1,"ABS(") == 0)
- $$ = New_Func( 0, abs_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"MIN(") == 0)
- $$ = New_Func( TYPE($2), /* Force 1D result */
- min1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"MAX(") == 0)
- $$ = New_Func( TYPE($2), /* Force 1D result */
- max1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"RANDOM(") == 0) { /* Vector RANDOM() */
- srand( (unsigned int) time(NULL) );
- $$ = New_Func( 0, rnd_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- TEST($$);
- TYPE($$) = DOUBLE;
- } else if (FSTRCMP($1,"RANDOMN(") == 0) {
- srand( (unsigned int) time(NULL) ); /* Vector RANDOMN() */
- $$ = New_Func( 0, gasrnd_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- TEST($$);
- TYPE($$) = DOUBLE;
- }
- else { /* These all take DOUBLE arguments */
- if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
- if (FSTRCMP($1,"SIN(") == 0)
- $$ = New_Func( 0, sin_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"COS(") == 0)
- $$ = New_Func( 0, cos_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"TAN(") == 0)
- $$ = New_Func( 0, tan_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"ARCSIN(") == 0
- || FSTRCMP($1,"ASIN(") == 0)
- $$ = New_Func( 0, asin_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"ARCCOS(") == 0
- || FSTRCMP($1,"ACOS(") == 0)
- $$ = New_Func( 0, acos_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"ARCTAN(") == 0
- || FSTRCMP($1,"ATAN(") == 0)
- $$ = New_Func( 0, atan_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"SINH(") == 0)
- $$ = New_Func( 0, sinh_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"COSH(") == 0)
- $$ = New_Func( 0, cosh_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"TANH(") == 0)
- $$ = New_Func( 0, tanh_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"EXP(") == 0)
- $$ = New_Func( 0, exp_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"LOG(") == 0)
- $$ = New_Func( 0, log_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"LOG10(") == 0)
- $$ = New_Func( 0, log10_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"SQRT(") == 0)
- $$ = New_Func( 0, sqrt_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"ROUND(") == 0)
- $$ = New_Func( 0, round_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"FLOOR(") == 0)
- $$ = New_Func( 0, floor_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"CEIL(") == 0)
- $$ = New_Func( 0, ceil_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
- else if (FSTRCMP($1,"RANDOMP(") == 0) {
- srand( (unsigned int) time(NULL) );
- $$ = New_Func( 0, poirnd_fct, 1, $2,
- 0, 0, 0, 0, 0, 0 );
- TYPE($$) = LONG;
- } else {
- yyerror("Function(expr) not supported");
- YYERROR;
- }
- }
- TEST($$);
- }
- | IFUNCTION sexpr ',' sexpr ')'
- {
- if (FSTRCMP($1,"STRSTR(") == 0) {
- $$ = New_Func( LONG, strpos_fct, 2, $2, $4, 0,
- 0, 0, 0, 0 );
- TEST($$);
- }
- }
- | FUNCTION expr ',' expr ')'
- {
- if (FSTRCMP($1,"DEFNULL(") == 0) {
- if( SIZE($2)>=SIZE($4) && Test_Dims( $2, $4 ) ) {
- PROMOTE($2,$4);
- $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0,
- 0, 0, 0, 0 );
- TEST($$);
- } else {
- yyerror("Dimensions of DEFNULL arguments "
- "are not compatible");
- YYERROR;
- }
- } else if (FSTRCMP($1,"ARCTAN2(") == 0) {
- if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
- if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
- if( Test_Dims( $2, $4 ) ) {
- $$ = New_Func( 0, atan2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
- TEST($$);
- if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
- } else {
- yyerror("Dimensions of arctan2 arguments "
- "are not compatible");
- YYERROR;
- }
- } else if (FSTRCMP($1,"MIN(") == 0) {
- PROMOTE( $2, $4 );
- if( Test_Dims( $2, $4 ) ) {
- $$ = New_Func( 0, min2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
- TEST($$);
- if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
- } else {
- yyerror("Dimensions of min(a,b) arguments "
- "are not compatible");
- YYERROR;
- }
- } else if (FSTRCMP($1,"MAX(") == 0) {
- PROMOTE( $2, $4 );
- if( Test_Dims( $2, $4 ) ) {
- $$ = New_Func( 0, max2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
- TEST($$);
- if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
- } else {
- yyerror("Dimensions of max(a,b) arguments "
- "are not compatible");
- YYERROR;
- }
- #if 0
- } else if (FSTRCMP($1,"STRSTR(") == 0) {
- if( TYPE($2) != STRING || TYPE($4) != STRING) {
- yyerror("Arguments to strstr(s,r) must be strings");
- YYERROR;
- }
- $$ = New_Func( LONG, strpos_fct, 2, $2, $4, 0,
- 0, 0, 0, 0 );
- TEST($$);
- #endif
- } else {
- yyerror("Function(expr,expr) not supported");
- YYERROR;
- }
- }
- | FUNCTION expr ',' expr ',' expr ',' expr ')'
- {
- if (FSTRCMP($1,"ANGSEP(") == 0) {
- if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
- if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
- if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
- if( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
- if( Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) &&
- Test_Dims( $6, $8 ) ) {
- $$ = New_Func( 0, angsep_fct, 4, $2, $4, $6, $8,0,0,0 );
- TEST($$);
- if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
- if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
- if( SIZE($6)<SIZE($8) ) Copy_Dims($$, $8);
- } else {
- yyerror("Dimensions of ANGSEP arguments "
- "are not compatible");
- YYERROR;
- }
- } else {
- yyerror("Function(expr,expr,expr,expr) not supported");
- YYERROR;
- }
- }
- | expr '[' expr ']'
- { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); }
- | expr '[' expr ',' expr ']'
- { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); }
- | expr '[' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); }
- | expr '[' expr ',' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); }
- | expr '[' expr ',' expr ',' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
- | INTCAST expr
- { $$ = New_Unary( LONG, INTCAST, $2 ); TEST($$); }
- | INTCAST bexpr
- { $$ = New_Unary( LONG, INTCAST, $2 ); TEST($$); }
- | FLTCAST expr
- { $$ = New_Unary( DOUBLE, FLTCAST, $2 ); TEST($$); }
- | FLTCAST bexpr
- { $$ = New_Unary( DOUBLE, FLTCAST, $2 ); TEST($$); }
- ;
- bexpr: BOOLEAN
- { $$ = New_Const( BOOLEAN, &($1), sizeof(char) ); TEST($$); }
- | BCOLUMN
- { $$ = New_Column( $1 ); TEST($$); }
- | BCOLUMN '{' expr '}'
- {
- if( TYPE($3) != LONG
- || OPER($3) != CONST_OP ) {
- yyerror("Offset argument must be a constant integer");
- YYERROR;
- }
- $$ = New_Offset( $1, $3 ); TEST($$);
- }
- | bits EQ bits
- { $$ = New_BinOp( BOOLEAN, $1, EQ, $3 ); TEST($$);
- SIZE($$) = 1; }
- | bits NE bits
- { $$ = New_BinOp( BOOLEAN, $1, NE, $3 ); TEST($$);
- SIZE($$) = 1; }
- | bits LT bits
- { $$ = New_BinOp( BOOLEAN, $1, LT, $3 ); TEST($$);
- SIZE($$) = 1; }
- | bits LTE bits
- { $$ = New_BinOp( BOOLEAN, $1, LTE, $3 ); TEST($$);
- SIZE($$) = 1; }
- | bits GT bits
- { $$ = New_BinOp( BOOLEAN, $1, GT, $3 ); TEST($$);
- SIZE($$) = 1; }
- | bits GTE bits
- { $$ = New_BinOp( BOOLEAN, $1, GTE, $3 ); TEST($$);
- SIZE($$) = 1; }
- | expr GT expr
- { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, GT, $3 );
- TEST($$); }
- | expr LT expr
- { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, LT, $3 );
- TEST($$); }
- | expr GTE expr
- { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, GTE, $3 );
- TEST($$); }
- | expr LTE expr
- { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, LTE, $3 );
- TEST($$); }
- | expr '~' expr
- { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, '~', $3 );
- TEST($$); }
- | expr EQ expr
- { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, EQ, $3 );
- TEST($$); }
- | expr NE expr
- { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, NE, $3 );
- TEST($$); }
- | sexpr EQ sexpr
- { $$ = New_BinOp( BOOLEAN, $1, EQ, $3 ); TEST($$);
- SIZE($$) = 1; }
- | sexpr NE sexpr
- { $$ = New_BinOp( BOOLEAN, $1, NE, $3 ); TEST($$);
- SIZE($$) = 1; }
- | sexpr GT sexpr
- { $$ = New_BinOp( BOOLEAN, $1, GT, $3 ); TEST($$);
- SIZE($$) = 1; }
- | sexpr GTE sexpr
- { $$ = New_BinOp( BOOLEAN, $1, GTE, $3 ); TEST($$);
- SIZE($$) = 1; }
- | sexpr LT sexpr
- { $$ = New_BinOp( BOOLEAN, $1, LT, $3 ); TEST($$);
- SIZE($$) = 1; }
- | sexpr LTE sexpr
- { $$ = New_BinOp( BOOLEAN, $1, LTE, $3 ); TEST($$);
- SIZE($$) = 1; }
- | bexpr AND bexpr
- { $$ = New_BinOp( BOOLEAN, $1, AND, $3 ); TEST($$); }
- | bexpr OR bexpr
- { $$ = New_BinOp( BOOLEAN, $1, OR, $3 ); TEST($$); }
- | bexpr EQ bexpr
- { $$ = New_BinOp( BOOLEAN, $1, EQ, $3 ); TEST($$); }
- | bexpr NE bexpr
- { $$ = New_BinOp( BOOLEAN, $1, NE, $3 ); TEST($$); }
- | expr '=' expr ':' expr
- { PROMOTE($1,$3); PROMOTE($1,$5); PROMOTE($3,$5);
- $3 = New_BinOp( BOOLEAN, $3, LTE, $1 );
- $5 = New_BinOp( BOOLEAN, $1, LTE, $5 );
- $$ = New_BinOp( BOOLEAN, $3, AND, $5 );
- TEST($$); }
- | bexpr '?' bexpr ':' bexpr
- {
- if( ! Test_Dims($3,$5) ) {
- yyerror("Incompatible dimensions in '?:' arguments");
- YYERROR;
- }
- $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
- 0, 0, 0, 0 );
- TEST($$);
- if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
- if( ! Test_Dims($1,$$) ) {
- yyerror("Incompatible dimensions in '?:' condition");
- YYERROR;
- }
- if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
- }
- | BFUNCTION expr ')'
- {
- if (FSTRCMP($1,"ISNULL(") == 0) {
- $$ = New_Func( 0, isnull_fct, 1, $2, 0, 0,
- 0, 0, 0, 0 );
- TEST($$);
- /* Use expression's size, but return BOOLEAN */
- TYPE($$) = BOOLEAN;
- } else {
- yyerror("Boolean Function(expr) not supported");
- YYERROR;
- }
- }
- | BFUNCTION bexpr ')'
- {
- if (FSTRCMP($1,"ISNULL(") == 0) {
- $$ = New_Func( 0, isnull_fct, 1, $2, 0, 0,
- 0, 0, 0, 0 );
- TEST($$);
- /* Use expression's size, but return BOOLEAN */
- TYPE($$) = BOOLEAN;
- } else {
- yyerror("Boolean Function(expr) not supported");
- YYERROR;
- }
- }
- | BFUNCTION sexpr ')'
- {
- if (FSTRCMP($1,"ISNULL(") == 0) {
- $$ = New_Func( BOOLEAN, isnull_fct, 1, $2, 0, 0,
- 0, 0, 0, 0 );
- TEST($$);
- } else {
- yyerror("Boolean Function(expr) not supported");
- YYERROR;
- }
- }
- | FUNCTION bexpr ',' bexpr ')'
- {
- if (FSTRCMP($1,"DEFNULL(") == 0) {
- if( SIZE($2)>=SIZE($4) && Test_Dims( $2, $4 ) ) {
- $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0,
- 0, 0, 0, 0 );
- TEST($$);
- } else {
- yyerror("Dimensions of DEFNULL arguments are not compatible");
- YYERROR;
- }
- } else {
- yyerror("Boolean Function(expr,expr) not supported");
- YYERROR;
- }
- }
- | BFUNCTION expr ',' expr ',' expr ')'
- {
- if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
- if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
- if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
- if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) ) ) {
- yyerror("Dimensions of NEAR arguments "
- "are not compatible");
- YYERROR;
- } else {
- if (FSTRCMP($1,"NEAR(") == 0) {
- $$ = New_Func( BOOLEAN, near_fct, 3, $2, $4, $6,
- 0, 0, 0, 0 );
- } else {
- yyerror("Boolean Function not supported");
- YYERROR;
- }
- TEST($$);
- if( SIZE($$)<SIZE($2) ) Copy_Dims($$, $2);
- if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
- if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
- }
- }
- | BFUNCTION expr ',' expr ',' expr ',' expr ',' expr ')'
- {
- if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
- if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
- if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
- if( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
- if( TYPE($10)!= DOUBLE ) $10= New_Unary( DOUBLE, 0, $10);
- if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) &&
- Test_Dims( $6, $8 ) && Test_Dims( $8, $10 )) ) {
- yyerror("Dimensions of CIRCLE arguments "
- "are not compatible");
- YYERROR;
- } else {
- if (FSTRCMP($1,"CIRCLE(") == 0) {
- $$ = New_Func( BOOLEAN, circle_fct, 5, $2, $4, $6, $8,
- $10, 0, 0 );
- } else {
- yyerror("Boolean Function not supported");
- YYERROR;
- }
- TEST($$);
- if( SIZE($$)<SIZE($2) ) Copy_Dims($$, $2);
- if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
- if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
- if( SIZE($6)<SIZE($8) ) Copy_Dims($$, $8);
- if( SIZE($8)<SIZE($10) ) Copy_Dims($$, $10);
- }
- }
- | BFUNCTION expr ',' expr ',' expr ',' expr ',' expr ',' expr ',' expr ')'
- {
- if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
- if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
- if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
- if( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
- if( TYPE($10)!= DOUBLE ) $10= New_Unary( DOUBLE, 0, $10);
- if( TYPE($12)!= DOUBLE ) $12= New_Unary( DOUBLE, 0, $12);
- if( TYPE($14)!= DOUBLE ) $14= New_Unary( DOUBLE, 0, $14);
- if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) &&
- Test_Dims( $6, $8 ) && Test_Dims( $8, $10 ) &&
- Test_Dims($10,$12 ) && Test_Dims($12, $14 ) ) ) {
- yyerror("Dimensions of BOX or ELLIPSE arguments "
- "are not compatible");
- YYERROR;
- } else {
- if (FSTRCMP($1,"BOX(") == 0) {
- $$ = New_Func( BOOLEAN, box_fct, 7, $2, $4, $6, $8,
- $10, $12, $14 );
- } else if (FSTRCMP($1,"ELLIPSE(") == 0) {
- $$ = New_Func( BOOLEAN, elps_fct, 7, $2, $4, $6, $8,
- $10, $12, $14 );
- } else {
- yyerror("SAO Image Function not supported");
- YYERROR;
- }
- TEST($$);
- if( SIZE($$)<SIZE($2) ) Copy_Dims($$, $2);
- if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
- if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
- if( SIZE($6)<SIZE($8) ) Copy_Dims($$, $8);
- if( SIZE($8)<SIZE($10) ) Copy_Dims($$, $10);
- if( SIZE($10)<SIZE($12) ) Copy_Dims($$, $12);
- if( SIZE($12)<SIZE($14) ) Copy_Dims($$, $14);
- }
- }
- | GTIFILTER ')'
- { /* Use defaults for all elements */
- $$ = New_GTI( "", -99, "*START*", "*STOP*" );
- TEST($$); }
- | GTIFILTER STRING ')'
- { /* Use defaults for all except filename */
- $$ = New_GTI( $2, -99, "*START*", "*STOP*" );
- TEST($$); }
- | GTIFILTER STRING ',' expr ')'
- { $$ = New_GTI( $2, $4, "*START*", "*STOP*" );
- TEST($$); }
- | GTIFILTER STRING ',' expr ',' STRING ',' STRING ')'
- { $$ = New_GTI( $2, $4, $6, $8 );
- TEST($$); }
- | REGFILTER STRING ')'
- { /* Use defaults for all except filename */
- $$ = New_REG( $2, -99, -99, "" );
- TEST($$); }
- | REGFILTER STRING ',' expr ',' expr ')'
- { $$ = New_REG( $2, $4, $6, "" );
- TEST($$); }
- | REGFILTER STRING ',' expr ',' expr ',' STRING ')'
- { $$ = New_REG( $2, $4, $6, $8 );
- TEST($$); }
- | bexpr '[' expr ']'
- { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); }
- | bexpr '[' expr ',' expr ']'
- { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); }
- | bexpr '[' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); }
- | bexpr '[' expr ',' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); }
- | bexpr '[' expr ',' expr ',' expr ',' expr ',' expr ']'
- { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
- | NOT bexpr
- { $$ = New_Unary( BOOLEAN, NOT, $2 ); TEST($$); }
- | '(' bexpr ')'
- { $$ = $2; }
- ;
- sexpr: STRING
- { $$ = New_Const( STRING, $1, strlen($1)+1 ); TEST($$);
- SIZE($$) = strlen($1); }
- | SCOLUMN
- { $$ = New_Column( $1 ); TEST($$); }
- | SCOLUMN '{' expr '}'
- {
- if( TYPE($3) != LONG
- || OPER($3) != CONST_OP ) {
- yyerror("Offset argument must be a constant integer");
- YYERROR;
- }
- $$ = New_Offset( $1, $3 ); TEST($$);
- }
- | SNULLREF
- { $$ = New_Func( STRING, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
- | '(' sexpr ')'
- { $$ = $2; }
- | sexpr '+' sexpr
- {
- if (SIZE($1)+SIZE($3) >= MAX_STRLEN) {
- yyerror("Combined string size exceeds " MAX_STRLEN_S " characters");
- YYERROR;
- }
- $$ = New_BinOp( STRING, $1, '+', $3 ); TEST($$);
- SIZE($$) = SIZE($1) + SIZE($3);
- }
- | bexpr '?' sexpr ':' sexpr
- {
- int outSize;
- if( SIZE($1)!=1 ) {
- yyerror("Cannot have a vector string column");
- YYERROR;
- }
- /* Since the output can be calculated now, as a constant
- scalar, we must precalculate the output size, in
- order to avoid an overflow. */
- outSize = SIZE($3);
- if (SIZE($5) > outSize) outSize = SIZE($5);
- $$ = New_FuncSize( 0, ifthenelse_fct, 3, $3, $5, $1,
- 0, 0, 0, 0, outSize);
-
- TEST($$);
- if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
- }
- | FUNCTION sexpr ',' sexpr ')'
- {
- if (FSTRCMP($1,"DEFNULL(") == 0) {
- int outSize;
- /* Since the output can be calculated now, as a constant
- scalar, we must precalculate the output size, in
- order to avoid an overflow. */
- outSize = SIZE($2);
- if (SIZE($4) > outSize) outSize = SIZE($4);
-
- $$ = New_FuncSize( 0, defnull_fct, 2, $2, $4, 0,
- 0, 0, 0, 0, outSize );
- TEST($$);
- if( SIZE($4)>SIZE($2) ) SIZE($$) = SIZE($4);
- } else {
- yyerror("Function(string,string) not supported");
- YYERROR;
- }
- }
- | FUNCTION sexpr ',' expr ',' expr ')'
- {
- if (FSTRCMP($1,"STRMID(") == 0) {
- int len;
- if( TYPE($4) != LONG || SIZE($4) != 1 ||
- TYPE($6) != LONG || SIZE($6) != 1) {
- yyerror("When using STRMID(S,P,N), P and N must be integers (and not vector columns)");
- YYERROR;
- }
- if (OPER($6) == CONST_OP) {
- /* Constant value: use that directly */
- len = (gParse.Nodes[$6].value.data.lng);
- } else {
- /* Variable value: use the maximum possible (from $2) */
- len = SIZE($2);
- }
- if (len <= 0 || len >= MAX_STRLEN) {
- yyerror("STRMID(S,P,N), N must be 1-" MAX_STRLEN_S);
- YYERROR;
- }
- $$ = New_FuncSize( 0, strmid_fct, 3, $2, $4,$6,0,0,0,0,len);
- TEST($$);
- } else {
- yyerror("Function(string,expr,expr) not supported");
- YYERROR;
- }
- }
- ;
- %%
- /*************************************************************************/
- /* Start of "New" routines which build the expression Nodal structure */
- /*************************************************************************/
- static int Alloc_Node( void )
- {
- /* Use this for allocation to guarantee *Nodes */
- Node *newNodePtr; /* survives on failure, making it still valid */
- /* while working our way out of this error */
- if( gParse.nNodes == gParse.nNodesAlloc ) {
- if( gParse.Nodes ) {
- gParse.nNodesAlloc += gParse.nNodesAlloc;
- newNodePtr = (Node *)realloc( gParse.Nodes,
- sizeof(Node)*gParse.nNodesAlloc );
- } else {
- gParse.nNodesAlloc = 100;
- newNodePtr = (Node *)malloc ( sizeof(Node)*gParse.nNodesAlloc );
- }
- if( newNodePtr ) {
- gParse.Nodes = newNodePtr;
- } else {
- gParse.status = MEMORY_ALLOCATION;
- return( -1 );
- }
- }
- return ( gParse.nNodes++ );
- }
- static void Free_Last_Node( void )
- {
- if( gParse.nNodes ) gParse.nNodes--;
- }
- static int New_Const( int returnType, void *value, long len )
- {
- Node *this;
- int n;
- n = Alloc_Node();
- if( n>=0 ) {
- this = gParse.Nodes + n;
- this->operation = CONST_OP; /* Flag a constant */
- this->DoOp = NULL;
- this->nSubNodes = 0;
- this->type = returnType;
- memcpy( &(this->value.data), value, len );
- this->value.undef = NULL;
- this->value.nelem = 1;
- this->value.naxis = 1;
- this->value.naxes[0] = 1;
- }
- return(n);
- }
- static int New_Column( int ColNum )
- {
- Node *this;
- int n, i;
- n = Alloc_Node();
- if( n>=0 ) {
- this = gParse.Nodes + n;
- this->operation = -ColNum;
- this->DoOp = NULL;
- this->nSubNodes = 0;
- this->type = gParse.varData[ColNum].type;
- this->value.nelem = gParse.varData[ColNum].nelem;
- this->value.naxis = gParse.varData[ColNum].naxis;
- for( i=0; i<gParse.varData[ColNum].naxis; i++ )
- this->value.naxes[i] = gParse.varData[ColNum].naxes[i];
- }
- return(n);
- }
- static int New_Offset( int ColNum, int offsetNode )
- {
- Node *this;
- int n, i, colNode;
- colNode = New_Column( ColNum );
- if( colNode<0 ) return(-1);
- n = Alloc_Node();
- if( n>=0 ) {
- this = gParse.Nodes + n;
- this->operation = '{';
- this->DoOp = Do_Offset;
- this->nSubNodes = 2;
- this->SubNodes[0] = colNode;
- this->SubNodes[1] = offsetNode;
- this->type = gParse.varData[ColNum].type;
- this->value.nelem = gParse.varData[ColNum].nelem;
- this->value.naxis = gParse.varData[ColNum].naxis;
- for( i=0; i<gParse.varData[ColNum].naxis; i++ )
- this->value.naxes[i] = gParse.varData[ColNum].naxes[i];
- }
- return(n);
- }
- static int New_Unary( int returnType, int Op, int Node1 )
- {
- Node *this, *that;
- int i,n;
- if( Node1<0 ) return(-1);
- that = gParse.Nodes + Node1;
- if( !Op ) Op = returnType;
- if( (Op==DOUBLE || Op==FLTCAST) && that->type==DOUBLE ) return( Node1 );
- if( (Op==LONG || Op==INTCAST) && that->type==LONG ) return( Node1 );
- if( (Op==BOOLEAN ) && that->type==BOOLEAN ) return( Node1 );
-
- n = Alloc_Node();
- if( n>=0 ) {
- this = gParse.Nodes + n;
- this->operation = Op;
- this->DoOp = Do_Unary;
- this->nSubNodes = 1;
- this->SubNodes[0] = Node1;
- this->type = returnType;
- that = gParse.Nodes + Node1; /* Reset in case .Nodes mv'd */
- this->value.nelem = that->value.nelem;
- this->value.naxis = that->value.naxis;
- for( i=0; i<that->value.naxis; i++ )
- this->value.naxes[i] = that->value.naxes[i];
- if( that->operation==CONST_OP ) this->DoOp( this );
- }
- return( n );
- }
- static int New_BinOp( int returnType, int Node1, int Op, int Node2 )
- {
- Node…
Large files files are truncated, but you can click here to view the full file