PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/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

  1. %{
  2. /************************************************************************/
  3. /* */
  4. /* CFITSIO Lexical Parser */
  5. /* */
  6. /* This file is one of 3 files containing code which parses an */
  7. /* arithmetic expression and evaluates it in the context of an input */
  8. /* FITS file table extension. The CFITSIO lexical parser is divided */
  9. /* into the following 3 parts/files: the CFITSIO "front-end", */
  10. /* eval_f.c, contains the interface between the user/CFITSIO and the */
  11. /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */
  12. /* input string and parses it into tokens and identifies the FITS */
  13. /* information required to evaluate the expression (ie, keywords and */
  14. /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */
  15. /* receives the FLEX output and determines and performs the actual */
  16. /* operations. The files eval_l.c and eval_y.c are produced from */
  17. /* running flex and bison on the files eval.l and eval.y, respectively. */
  18. /* (flex and bison are available from any GNU archive: see www.gnu.org) */
  19. /* */
  20. /* The grammar rules, rather than evaluating the expression in situ, */
  21. /* builds a tree, or Nodal, structure mapping out the order of */
  22. /* operations and expression dependencies. This "compilation" process */
  23. /* allows for much faster processing of multiple rows. This technique */
  24. /* was developed by Uwe Lammers of the XMM Science Analysis System, */
  25. /* although the CFITSIO implementation is entirely code original. */
  26. /* */
  27. /* */
  28. /* Modification History: */
  29. /* */
  30. /* Kent Blackburn c1992 Original parser code developed for the */
  31. /* FTOOLS software package, in particular, */
  32. /* the fselect task. */
  33. /* Kent Blackburn c1995 BIT column support added */
  34. /* Peter D Wilson Feb 1998 Vector column support added */
  35. /* Peter D Wilson May 1998 Ported to CFITSIO library. User */
  36. /* interface routines written, in essence */
  37. /* making fselect, fcalc, and maketime */
  38. /* capabilities available to all tools */
  39. /* via single function calls. */
  40. /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */
  41. /* create a run-time evaluation tree, */
  42. /* inspired by the work of Uwe Lammers, */
  43. /* resulting in a speed increase of */
  44. /* 10-100 times. */
  45. /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */
  46. /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */
  47. /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */
  48. /* allowing a purely vector-based usage */
  49. /* Craig B Markwardt Jun 2004 Add MEDIAN() function */
  50. /* Craig B Markwardt Jun 2004 Add SUM(), and MIN/MAX() for bit arrays */
  51. /* Craig B Markwardt Jun 2004 Allow subscripting of nX bit arrays */
  52. /* Craig B Markwardt Jun 2004 Implement statistical functions */
  53. /* NVALID(), AVERAGE(), and STDDEV() */
  54. /* for integer and floating point vectors */
  55. /* Craig B Markwardt Jun 2004 Use NULL values for range errors instead*/
  56. /* of throwing a parse error */
  57. /* Craig B Markwardt Oct 2004 Add ACCUM() and SEQDIFF() functions */
  58. /* Craig B Markwardt Feb 2005 Add ANGSEP() function */
  59. /* Craig B Markwardt Aug 2005 CIRCLE, BOX, ELLIPSE, NEAR and REGFILTER*/
  60. /* functions now accept vector arguments */
  61. /* Craig B Markwardt Sum 2006 Add RANDOMN() and RANDOMP() functions */
  62. /* Craig B Markwardt Mar 2007 Allow arguments to RANDOM and RANDOMN to*/
  63. /* determine the output dimensions */
  64. /* Craig B Markwardt Aug 2009 Add substring STRMID() and string search*/
  65. /* STRSTR() functions; more overflow checks*/
  66. /* */
  67. /************************************************************************/
  68. #define APPROX 1.0e-7
  69. #include "eval_defs.h"
  70. #include "region.h"
  71. #include <time.h>
  72. #include <stdlib.h>
  73. #ifndef alloca
  74. #define alloca malloc
  75. #endif
  76. /* Shrink the initial stack depth to keep local data <32K (mac limit) */
  77. /* yacc will allocate more space if needed, though. */
  78. #define YYINITDEPTH 100
  79. /***************************************************************/
  80. /* Replace Bison's BACKUP macro with one that fixes a bug -- */
  81. /* must update state after popping the stack -- and allows */
  82. /* popping multiple terms at one time. */
  83. /***************************************************************/
  84. #define YYNEWBACKUP(token, value) \
  85. do \
  86. if (yychar == YYEMPTY ) \
  87. { yychar = (token); \
  88. memcpy( &yylval, &(value), sizeof(value) ); \
  89. yychar1 = YYTRANSLATE (yychar); \
  90. while (yylen--) YYPOPSTACK; \
  91. yystate = *yyssp; \
  92. goto yybackup; \
  93. } \
  94. else \
  95. { yyerror ("syntax error: cannot back up"); YYERROR; } \
  96. while (0)
  97. /***************************************************************/
  98. /* Useful macros for accessing/testing Nodes */
  99. /***************************************************************/
  100. #define TEST(a) if( (a)<0 ) YYERROR
  101. #define SIZE(a) gParse.Nodes[ a ].value.nelem
  102. #define TYPE(a) gParse.Nodes[ a ].type
  103. #define OPER(a) gParse.Nodes[ a ].operation
  104. #define PROMOTE(a,b) if( TYPE(a) > TYPE(b) ) \
  105. b = New_Unary( TYPE(a), 0, b ); \
  106. else if( TYPE(a) < TYPE(b) ) \
  107. a = New_Unary( TYPE(b), 0, a );
  108. /***** Internal functions *****/
  109. #ifdef __cplusplus
  110. extern "C" {
  111. #endif
  112. static int Alloc_Node ( void );
  113. static void Free_Last_Node( void );
  114. static void Evaluate_Node ( int thisNode );
  115. static int New_Const ( int returnType, void *value, long len );
  116. static int New_Column( int ColNum );
  117. static int New_Offset( int ColNum, int offset );
  118. static int New_Unary ( int returnType, int Op, int Node1 );
  119. static int New_BinOp ( int returnType, int Node1, int Op, int Node2 );
  120. static int New_Func ( int returnType, funcOp Op, int nNodes,
  121. int Node1, int Node2, int Node3, int Node4,
  122. int Node5, int Node6, int Node7 );
  123. static int New_FuncSize( int returnType, funcOp Op, int nNodes,
  124. int Node1, int Node2, int Node3, int Node4,
  125. int Node5, int Node6, int Node7, int Size);
  126. static int New_Deref ( int Var, int nDim,
  127. int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 );
  128. static int New_GTI ( char *fname, int Node1, char *start, char *stop );
  129. static int New_REG ( char *fname, int NodeX, int NodeY, char *colNames );
  130. static int New_Vector( int subNode );
  131. static int Close_Vec ( int vecNode );
  132. static int Locate_Col( Node *this );
  133. static int Test_Dims ( int Node1, int Node2 );
  134. static void Copy_Dims ( int Node1, int Node2 );
  135. static void Allocate_Ptrs( Node *this );
  136. static void Do_Unary ( Node *this );
  137. static void Do_Offset ( Node *this );
  138. static void Do_BinOp_bit ( Node *this );
  139. static void Do_BinOp_str ( Node *this );
  140. static void Do_BinOp_log ( Node *this );
  141. static void Do_BinOp_lng ( Node *this );
  142. static void Do_BinOp_dbl ( Node *this );
  143. static void Do_Func ( Node *this );
  144. static void Do_Deref ( Node *this );
  145. static void Do_GTI ( Node *this );
  146. static void Do_REG ( Node *this );
  147. static void Do_Vector ( Node *this );
  148. static long Search_GTI ( double evtTime, long nGTI, double *start,
  149. double *stop, int ordered );
  150. static char saobox (double xcen, double ycen, double xwid, double ywid,
  151. double rot, double xcol, double ycol);
  152. static char ellipse(double xcen, double ycen, double xrad, double yrad,
  153. double rot, double xcol, double ycol);
  154. static char circle (double xcen, double ycen, double rad,
  155. double xcol, double ycol);
  156. static char bnear (double x, double y, double tolerance);
  157. static char bitcmp (char *bitstrm1, char *bitstrm2);
  158. static char bitlgte(char *bits1, int oper, char *bits2);
  159. static void bitand(char *result, char *bitstrm1, char *bitstrm2);
  160. static void bitor (char *result, char *bitstrm1, char *bitstrm2);
  161. static void bitnot(char *result, char *bits);
  162. static int cstrmid(char *dest_str, int dest_len,
  163. char *src_str, int src_len, int pos);
  164. static void yyerror(char *msg);
  165. #ifdef __cplusplus
  166. }
  167. #endif
  168. %}
  169. %union {
  170. int Node; /* Index of Node */
  171. double dbl; /* real value */
  172. long lng; /* integer value */
  173. char log; /* logical value */
  174. char str[MAX_STRLEN]; /* string value */
  175. }
  176. %token <log> BOOLEAN /* First 3 must be in order of */
  177. %token <lng> LONG /* increasing promotion for later use */
  178. %token <dbl> DOUBLE
  179. %token <str> STRING
  180. %token <str> BITSTR
  181. %token <str> FUNCTION
  182. %token <str> BFUNCTION /* Bit function */
  183. %token <str> IFUNCTION /* Integer function */
  184. %token <str> GTIFILTER
  185. %token <str> REGFILTER
  186. %token <lng> COLUMN
  187. %token <lng> BCOLUMN
  188. %token <lng> SCOLUMN
  189. %token <lng> BITCOL
  190. %token <lng> ROWREF
  191. %token <lng> NULLREF
  192. %token <lng> SNULLREF
  193. %type <Node> expr
  194. %type <Node> bexpr
  195. %type <Node> sexpr
  196. %type <Node> bits
  197. %type <Node> vector
  198. %type <Node> bvector
  199. %left ',' '=' ':' '{' '}'
  200. %right '?'
  201. %left OR
  202. %left AND
  203. %left EQ NE '~'
  204. %left GT LT LTE GTE
  205. %left '+' '-' '%'
  206. %left '*' '/'
  207. %left '|' '&'
  208. %right POWER
  209. %left NOT
  210. %left INTCAST FLTCAST
  211. %left UMINUS
  212. %left '['
  213. %right ACCUM DIFF
  214. %%
  215. lines: /* nothing ; was | lines line */
  216. | lines line
  217. ;
  218. line: '\n' {}
  219. | expr '\n'
  220. { if( $1<0 ) {
  221. yyerror("Couldn't build node structure: out of memory?");
  222. YYERROR; }
  223. gParse.resultNode = $1;
  224. }
  225. | bexpr '\n'
  226. { if( $1<0 ) {
  227. yyerror("Couldn't build node structure: out of memory?");
  228. YYERROR; }
  229. gParse.resultNode = $1;
  230. }
  231. | sexpr '\n'
  232. { if( $1<0 ) {
  233. yyerror("Couldn't build node structure: out of memory?");
  234. YYERROR; }
  235. gParse.resultNode = $1;
  236. }
  237. | bits '\n'
  238. { if( $1<0 ) {
  239. yyerror("Couldn't build node structure: out of memory?");
  240. YYERROR; }
  241. gParse.resultNode = $1;
  242. }
  243. | error '\n' { yyerrok; }
  244. ;
  245. bvector: '{' bexpr
  246. { $$ = New_Vector( $2 ); TEST($$); }
  247. | bvector ',' bexpr
  248. {
  249. if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
  250. $1 = Close_Vec( $1 ); TEST($1);
  251. $$ = New_Vector( $1 ); TEST($$);
  252. } else {
  253. $$ = $1;
  254. }
  255. gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
  256. = $3;
  257. }
  258. ;
  259. vector: '{' expr
  260. { $$ = New_Vector( $2 ); TEST($$); }
  261. | vector ',' expr
  262. {
  263. if( TYPE($1) < TYPE($3) )
  264. TYPE($1) = TYPE($3);
  265. if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
  266. $1 = Close_Vec( $1 ); TEST($1);
  267. $$ = New_Vector( $1 ); TEST($$);
  268. } else {
  269. $$ = $1;
  270. }
  271. gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
  272. = $3;
  273. }
  274. | vector ',' bexpr
  275. {
  276. if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
  277. $1 = Close_Vec( $1 ); TEST($1);
  278. $$ = New_Vector( $1 ); TEST($$);
  279. } else {
  280. $$ = $1;
  281. }
  282. gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
  283. = $3;
  284. }
  285. | bvector ',' expr
  286. {
  287. TYPE($1) = TYPE($3);
  288. if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) {
  289. $1 = Close_Vec( $1 ); TEST($1);
  290. $$ = New_Vector( $1 ); TEST($$);
  291. } else {
  292. $$ = $1;
  293. }
  294. gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ]
  295. = $3;
  296. }
  297. ;
  298. expr: vector '}'
  299. { $$ = Close_Vec( $1 ); TEST($$); }
  300. ;
  301. bexpr: bvector '}'
  302. { $$ = Close_Vec( $1 ); TEST($$); }
  303. ;
  304. bits: BITSTR
  305. {
  306. $$ = New_Const( BITSTR, $1, strlen($1)+1 ); TEST($$);
  307. SIZE($$) = strlen($1); }
  308. | BITCOL
  309. { $$ = New_Column( $1 ); TEST($$); }
  310. | BITCOL '{' expr '}'
  311. {
  312. if( TYPE($3) != LONG
  313. || OPER($3) != CONST_OP ) {
  314. yyerror("Offset argument must be a constant integer");
  315. YYERROR;
  316. }
  317. $$ = New_Offset( $1, $3 ); TEST($$);
  318. }
  319. | bits '&' bits
  320. { $$ = New_BinOp( BITSTR, $1, '&', $3 ); TEST($$);
  321. SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); }
  322. | bits '|' bits
  323. { $$ = New_BinOp( BITSTR, $1, '|', $3 ); TEST($$);
  324. SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); }
  325. | bits '+' bits
  326. {
  327. if (SIZE($1)+SIZE($3) >= MAX_STRLEN) {
  328. yyerror("Combined bit string size exceeds " MAX_STRLEN_S " bits");
  329. YYERROR;
  330. }
  331. $$ = New_BinOp( BITSTR, $1, '+', $3 ); TEST($$);
  332. SIZE($$) = SIZE($1) + SIZE($3);
  333. }
  334. | bits '[' expr ']'
  335. { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); }
  336. | bits '[' expr ',' expr ']'
  337. { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); }
  338. | bits '[' expr ',' expr ',' expr ']'
  339. { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); }
  340. | bits '[' expr ',' expr ',' expr ',' expr ']'
  341. { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); }
  342. | bits '[' expr ',' expr ',' expr ',' expr ',' expr ']'
  343. { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
  344. | NOT bits
  345. { $$ = New_Unary( BITSTR, NOT, $2 ); TEST($$); }
  346. | '(' bits ')'
  347. { $$ = $2; }
  348. ;
  349. expr: LONG
  350. { $$ = New_Const( LONG, &($1), sizeof(long) ); TEST($$); }
  351. | DOUBLE
  352. { $$ = New_Const( DOUBLE, &($1), sizeof(double) ); TEST($$); }
  353. | COLUMN
  354. { $$ = New_Column( $1 ); TEST($$); }
  355. | COLUMN '{' expr '}'
  356. {
  357. if( TYPE($3) != LONG
  358. || OPER($3) != CONST_OP ) {
  359. yyerror("Offset argument must be a constant integer");
  360. YYERROR;
  361. }
  362. $$ = New_Offset( $1, $3 ); TEST($$);
  363. }
  364. | ROWREF
  365. { $$ = New_Func( LONG, row_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
  366. | NULLREF
  367. { $$ = New_Func( LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
  368. | expr '%' expr
  369. { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '%', $3 );
  370. TEST($$); }
  371. | expr '+' expr
  372. { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '+', $3 );
  373. TEST($$); }
  374. | expr '-' expr
  375. { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '-', $3 );
  376. TEST($$); }
  377. | expr '*' expr
  378. { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '*', $3 );
  379. TEST($$); }
  380. | expr '/' expr
  381. { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '/', $3 );
  382. TEST($$); }
  383. | expr POWER expr
  384. { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, POWER, $3 );
  385. TEST($$); }
  386. | '+' expr %prec UMINUS
  387. { $$ = $2; }
  388. | '-' expr %prec UMINUS
  389. { $$ = New_Unary( TYPE($2), UMINUS, $2 ); TEST($$); }
  390. | '(' expr ')'
  391. { $$ = $2; }
  392. | expr '*' bexpr
  393. { $3 = New_Unary( TYPE($1), 0, $3 );
  394. $$ = New_BinOp( TYPE($1), $1, '*', $3 );
  395. TEST($$); }
  396. | bexpr '*' expr
  397. { $1 = New_Unary( TYPE($3), 0, $1 );
  398. $$ = New_BinOp( TYPE($3), $1, '*', $3 );
  399. TEST($$); }
  400. | bexpr '?' expr ':' expr
  401. {
  402. PROMOTE($3,$5);
  403. if( ! Test_Dims($3,$5) ) {
  404. yyerror("Incompatible dimensions in '?:' arguments");
  405. YYERROR;
  406. }
  407. $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
  408. 0, 0, 0, 0 );
  409. TEST($$);
  410. if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
  411. TYPE($1) = TYPE($3);
  412. if( ! Test_Dims($1,$$) ) {
  413. yyerror("Incompatible dimensions in '?:' condition");
  414. YYERROR;
  415. }
  416. TYPE($1) = BOOLEAN;
  417. if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
  418. }
  419. | bexpr '?' bexpr ':' expr
  420. {
  421. PROMOTE($3,$5);
  422. if( ! Test_Dims($3,$5) ) {
  423. yyerror("Incompatible dimensions in '?:' arguments");
  424. YYERROR;
  425. }
  426. $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
  427. 0, 0, 0, 0 );
  428. TEST($$);
  429. if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
  430. TYPE($1) = TYPE($3);
  431. if( ! Test_Dims($1,$$) ) {
  432. yyerror("Incompatible dimensions in '?:' condition");
  433. YYERROR;
  434. }
  435. TYPE($1) = BOOLEAN;
  436. if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
  437. }
  438. | bexpr '?' expr ':' bexpr
  439. {
  440. PROMOTE($3,$5);
  441. if( ! Test_Dims($3,$5) ) {
  442. yyerror("Incompatible dimensions in '?:' arguments");
  443. YYERROR;
  444. }
  445. $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
  446. 0, 0, 0, 0 );
  447. TEST($$);
  448. if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
  449. TYPE($1) = TYPE($3);
  450. if( ! Test_Dims($1,$$) ) {
  451. yyerror("Incompatible dimensions in '?:' condition");
  452. YYERROR;
  453. }
  454. TYPE($1) = BOOLEAN;
  455. if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
  456. }
  457. | FUNCTION ')'
  458. { if (FSTRCMP($1,"RANDOM(") == 0) { /* Scalar RANDOM() */
  459. srand( (unsigned int) time(NULL) );
  460. $$ = New_Func( DOUBLE, rnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
  461. } else if (FSTRCMP($1,"RANDOMN(") == 0) {/*Scalar RANDOMN()*/
  462. srand( (unsigned int) time(NULL) );
  463. $$ = New_Func( DOUBLE, gasrnd_fct, 0, 0, 0, 0, 0, 0, 0, 0 );
  464. } else {
  465. yyerror("Function() not supported");
  466. YYERROR;
  467. }
  468. TEST($$);
  469. }
  470. | FUNCTION bexpr ')'
  471. { if (FSTRCMP($1,"SUM(") == 0) {
  472. $$ = New_Func( LONG, sum_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  473. } else if (FSTRCMP($1,"NELEM(") == 0) {
  474. $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
  475. } else if (FSTRCMP($1,"ACCUM(") == 0) {
  476. long zero = 0;
  477. $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
  478. } else {
  479. yyerror("Function(bool) not supported");
  480. YYERROR;
  481. }
  482. TEST($$);
  483. }
  484. | FUNCTION sexpr ')'
  485. { if (FSTRCMP($1,"NELEM(") == 0) {
  486. $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
  487. } else if (FSTRCMP($1,"NVALID(") == 0) {
  488. $$ = New_Func( LONG, nonnull_fct, 1, $2,
  489. 0, 0, 0, 0, 0, 0 );
  490. } else {
  491. yyerror("Function(str) not supported");
  492. YYERROR;
  493. }
  494. TEST($$);
  495. }
  496. | FUNCTION bits ')'
  497. { if (FSTRCMP($1,"NELEM(") == 0) {
  498. $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
  499. } else if (FSTRCMP($1,"NVALID(") == 0) { /* Bit arrays do not have NULL */
  500. $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
  501. } else if (FSTRCMP($1,"SUM(") == 0) {
  502. $$ = New_Func( LONG, sum_fct, 1, $2,
  503. 0, 0, 0, 0, 0, 0 );
  504. } else if (FSTRCMP($1,"MIN(") == 0) {
  505. $$ = New_Func( TYPE($2), /* Force 1D result */
  506. min1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  507. /* Note: $2 is a vector so the result can never
  508. be a constant. Therefore it will never be set
  509. inside New_Func(), and it is safe to set SIZE() */
  510. SIZE($$) = 1;
  511. } else if (FSTRCMP($1,"ACCUM(") == 0) {
  512. long zero = 0;
  513. $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
  514. } else if (FSTRCMP($1,"MAX(") == 0) {
  515. $$ = New_Func( TYPE($2), /* Force 1D result */
  516. max1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  517. /* Note: $2 is a vector so the result can never
  518. be a constant. Therefore it will never be set
  519. inside New_Func(), and it is safe to set SIZE() */
  520. SIZE($$) = 1;
  521. } else {
  522. yyerror("Function(bits) not supported");
  523. YYERROR;
  524. }
  525. TEST($$);
  526. }
  527. | FUNCTION expr ')'
  528. { if (FSTRCMP($1,"SUM(") == 0)
  529. $$ = New_Func( TYPE($2), sum_fct, 1, $2,
  530. 0, 0, 0, 0, 0, 0 );
  531. else if (FSTRCMP($1,"AVERAGE(") == 0)
  532. $$ = New_Func( DOUBLE, average_fct, 1, $2,
  533. 0, 0, 0, 0, 0, 0 );
  534. else if (FSTRCMP($1,"STDDEV(") == 0)
  535. $$ = New_Func( DOUBLE, stddev_fct, 1, $2,
  536. 0, 0, 0, 0, 0, 0 );
  537. else if (FSTRCMP($1,"MEDIAN(") == 0)
  538. $$ = New_Func( TYPE($2), median_fct, 1, $2,
  539. 0, 0, 0, 0, 0, 0 );
  540. else if (FSTRCMP($1,"NELEM(") == 0)
  541. $$ = New_Const( LONG, &( SIZE($2) ), sizeof(long) );
  542. else if (FSTRCMP($1,"NVALID(") == 0)
  543. $$ = New_Func( LONG, nonnull_fct, 1, $2,
  544. 0, 0, 0, 0, 0, 0 );
  545. else if ((FSTRCMP($1,"ACCUM(") == 0) && (TYPE($2) == LONG)) {
  546. long zero = 0;
  547. $$ = New_BinOp( LONG , $2, ACCUM, New_Const( LONG, &zero, sizeof(zero) ));
  548. } else if ((FSTRCMP($1,"ACCUM(") == 0) && (TYPE($2) == DOUBLE)) {
  549. double zero = 0;
  550. $$ = New_BinOp( DOUBLE , $2, ACCUM, New_Const( DOUBLE, &zero, sizeof(zero) ));
  551. } else if ((FSTRCMP($1,"SEQDIFF(") == 0) && (TYPE($2) == LONG)) {
  552. long zero = 0;
  553. $$ = New_BinOp( LONG , $2, DIFF, New_Const( LONG, &zero, sizeof(zero) ));
  554. } else if ((FSTRCMP($1,"SEQDIFF(") == 0) && (TYPE($2) == DOUBLE)) {
  555. double zero = 0;
  556. $$ = New_BinOp( DOUBLE , $2, DIFF, New_Const( DOUBLE, &zero, sizeof(zero) ));
  557. } else if (FSTRCMP($1,"ABS(") == 0)
  558. $$ = New_Func( 0, abs_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  559. else if (FSTRCMP($1,"MIN(") == 0)
  560. $$ = New_Func( TYPE($2), /* Force 1D result */
  561. min1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  562. else if (FSTRCMP($1,"MAX(") == 0)
  563. $$ = New_Func( TYPE($2), /* Force 1D result */
  564. max1_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  565. else if (FSTRCMP($1,"RANDOM(") == 0) { /* Vector RANDOM() */
  566. srand( (unsigned int) time(NULL) );
  567. $$ = New_Func( 0, rnd_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  568. TEST($$);
  569. TYPE($$) = DOUBLE;
  570. } else if (FSTRCMP($1,"RANDOMN(") == 0) {
  571. srand( (unsigned int) time(NULL) ); /* Vector RANDOMN() */
  572. $$ = New_Func( 0, gasrnd_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  573. TEST($$);
  574. TYPE($$) = DOUBLE;
  575. }
  576. else { /* These all take DOUBLE arguments */
  577. if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
  578. if (FSTRCMP($1,"SIN(") == 0)
  579. $$ = New_Func( 0, sin_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  580. else if (FSTRCMP($1,"COS(") == 0)
  581. $$ = New_Func( 0, cos_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  582. else if (FSTRCMP($1,"TAN(") == 0)
  583. $$ = New_Func( 0, tan_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  584. else if (FSTRCMP($1,"ARCSIN(") == 0
  585. || FSTRCMP($1,"ASIN(") == 0)
  586. $$ = New_Func( 0, asin_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  587. else if (FSTRCMP($1,"ARCCOS(") == 0
  588. || FSTRCMP($1,"ACOS(") == 0)
  589. $$ = New_Func( 0, acos_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  590. else if (FSTRCMP($1,"ARCTAN(") == 0
  591. || FSTRCMP($1,"ATAN(") == 0)
  592. $$ = New_Func( 0, atan_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  593. else if (FSTRCMP($1,"SINH(") == 0)
  594. $$ = New_Func( 0, sinh_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  595. else if (FSTRCMP($1,"COSH(") == 0)
  596. $$ = New_Func( 0, cosh_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  597. else if (FSTRCMP($1,"TANH(") == 0)
  598. $$ = New_Func( 0, tanh_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  599. else if (FSTRCMP($1,"EXP(") == 0)
  600. $$ = New_Func( 0, exp_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  601. else if (FSTRCMP($1,"LOG(") == 0)
  602. $$ = New_Func( 0, log_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  603. else if (FSTRCMP($1,"LOG10(") == 0)
  604. $$ = New_Func( 0, log10_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  605. else if (FSTRCMP($1,"SQRT(") == 0)
  606. $$ = New_Func( 0, sqrt_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  607. else if (FSTRCMP($1,"ROUND(") == 0)
  608. $$ = New_Func( 0, round_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  609. else if (FSTRCMP($1,"FLOOR(") == 0)
  610. $$ = New_Func( 0, floor_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  611. else if (FSTRCMP($1,"CEIL(") == 0)
  612. $$ = New_Func( 0, ceil_fct, 1, $2, 0, 0, 0, 0, 0, 0 );
  613. else if (FSTRCMP($1,"RANDOMP(") == 0) {
  614. srand( (unsigned int) time(NULL) );
  615. $$ = New_Func( 0, poirnd_fct, 1, $2,
  616. 0, 0, 0, 0, 0, 0 );
  617. TYPE($$) = LONG;
  618. } else {
  619. yyerror("Function(expr) not supported");
  620. YYERROR;
  621. }
  622. }
  623. TEST($$);
  624. }
  625. | IFUNCTION sexpr ',' sexpr ')'
  626. {
  627. if (FSTRCMP($1,"STRSTR(") == 0) {
  628. $$ = New_Func( LONG, strpos_fct, 2, $2, $4, 0,
  629. 0, 0, 0, 0 );
  630. TEST($$);
  631. }
  632. }
  633. | FUNCTION expr ',' expr ')'
  634. {
  635. if (FSTRCMP($1,"DEFNULL(") == 0) {
  636. if( SIZE($2)>=SIZE($4) && Test_Dims( $2, $4 ) ) {
  637. PROMOTE($2,$4);
  638. $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0,
  639. 0, 0, 0, 0 );
  640. TEST($$);
  641. } else {
  642. yyerror("Dimensions of DEFNULL arguments "
  643. "are not compatible");
  644. YYERROR;
  645. }
  646. } else if (FSTRCMP($1,"ARCTAN2(") == 0) {
  647. if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
  648. if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
  649. if( Test_Dims( $2, $4 ) ) {
  650. $$ = New_Func( 0, atan2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
  651. TEST($$);
  652. if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
  653. } else {
  654. yyerror("Dimensions of arctan2 arguments "
  655. "are not compatible");
  656. YYERROR;
  657. }
  658. } else if (FSTRCMP($1,"MIN(") == 0) {
  659. PROMOTE( $2, $4 );
  660. if( Test_Dims( $2, $4 ) ) {
  661. $$ = New_Func( 0, min2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
  662. TEST($$);
  663. if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
  664. } else {
  665. yyerror("Dimensions of min(a,b) arguments "
  666. "are not compatible");
  667. YYERROR;
  668. }
  669. } else if (FSTRCMP($1,"MAX(") == 0) {
  670. PROMOTE( $2, $4 );
  671. if( Test_Dims( $2, $4 ) ) {
  672. $$ = New_Func( 0, max2_fct, 2, $2, $4, 0, 0, 0, 0, 0 );
  673. TEST($$);
  674. if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
  675. } else {
  676. yyerror("Dimensions of max(a,b) arguments "
  677. "are not compatible");
  678. YYERROR;
  679. }
  680. #if 0
  681. } else if (FSTRCMP($1,"STRSTR(") == 0) {
  682. if( TYPE($2) != STRING || TYPE($4) != STRING) {
  683. yyerror("Arguments to strstr(s,r) must be strings");
  684. YYERROR;
  685. }
  686. $$ = New_Func( LONG, strpos_fct, 2, $2, $4, 0,
  687. 0, 0, 0, 0 );
  688. TEST($$);
  689. #endif
  690. } else {
  691. yyerror("Function(expr,expr) not supported");
  692. YYERROR;
  693. }
  694. }
  695. | FUNCTION expr ',' expr ',' expr ',' expr ')'
  696. {
  697. if (FSTRCMP($1,"ANGSEP(") == 0) {
  698. if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
  699. if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
  700. if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
  701. if( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
  702. if( Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) &&
  703. Test_Dims( $6, $8 ) ) {
  704. $$ = New_Func( 0, angsep_fct, 4, $2, $4, $6, $8,0,0,0 );
  705. TEST($$);
  706. if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
  707. if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
  708. if( SIZE($6)<SIZE($8) ) Copy_Dims($$, $8);
  709. } else {
  710. yyerror("Dimensions of ANGSEP arguments "
  711. "are not compatible");
  712. YYERROR;
  713. }
  714. } else {
  715. yyerror("Function(expr,expr,expr,expr) not supported");
  716. YYERROR;
  717. }
  718. }
  719. | expr '[' expr ']'
  720. { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); }
  721. | expr '[' expr ',' expr ']'
  722. { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); }
  723. | expr '[' expr ',' expr ',' expr ']'
  724. { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); }
  725. | expr '[' expr ',' expr ',' expr ',' expr ']'
  726. { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); }
  727. | expr '[' expr ',' expr ',' expr ',' expr ',' expr ']'
  728. { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
  729. | INTCAST expr
  730. { $$ = New_Unary( LONG, INTCAST, $2 ); TEST($$); }
  731. | INTCAST bexpr
  732. { $$ = New_Unary( LONG, INTCAST, $2 ); TEST($$); }
  733. | FLTCAST expr
  734. { $$ = New_Unary( DOUBLE, FLTCAST, $2 ); TEST($$); }
  735. | FLTCAST bexpr
  736. { $$ = New_Unary( DOUBLE, FLTCAST, $2 ); TEST($$); }
  737. ;
  738. bexpr: BOOLEAN
  739. { $$ = New_Const( BOOLEAN, &($1), sizeof(char) ); TEST($$); }
  740. | BCOLUMN
  741. { $$ = New_Column( $1 ); TEST($$); }
  742. | BCOLUMN '{' expr '}'
  743. {
  744. if( TYPE($3) != LONG
  745. || OPER($3) != CONST_OP ) {
  746. yyerror("Offset argument must be a constant integer");
  747. YYERROR;
  748. }
  749. $$ = New_Offset( $1, $3 ); TEST($$);
  750. }
  751. | bits EQ bits
  752. { $$ = New_BinOp( BOOLEAN, $1, EQ, $3 ); TEST($$);
  753. SIZE($$) = 1; }
  754. | bits NE bits
  755. { $$ = New_BinOp( BOOLEAN, $1, NE, $3 ); TEST($$);
  756. SIZE($$) = 1; }
  757. | bits LT bits
  758. { $$ = New_BinOp( BOOLEAN, $1, LT, $3 ); TEST($$);
  759. SIZE($$) = 1; }
  760. | bits LTE bits
  761. { $$ = New_BinOp( BOOLEAN, $1, LTE, $3 ); TEST($$);
  762. SIZE($$) = 1; }
  763. | bits GT bits
  764. { $$ = New_BinOp( BOOLEAN, $1, GT, $3 ); TEST($$);
  765. SIZE($$) = 1; }
  766. | bits GTE bits
  767. { $$ = New_BinOp( BOOLEAN, $1, GTE, $3 ); TEST($$);
  768. SIZE($$) = 1; }
  769. | expr GT expr
  770. { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, GT, $3 );
  771. TEST($$); }
  772. | expr LT expr
  773. { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, LT, $3 );
  774. TEST($$); }
  775. | expr GTE expr
  776. { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, GTE, $3 );
  777. TEST($$); }
  778. | expr LTE expr
  779. { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, LTE, $3 );
  780. TEST($$); }
  781. | expr '~' expr
  782. { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, '~', $3 );
  783. TEST($$); }
  784. | expr EQ expr
  785. { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, EQ, $3 );
  786. TEST($$); }
  787. | expr NE expr
  788. { PROMOTE($1,$3); $$ = New_BinOp( BOOLEAN, $1, NE, $3 );
  789. TEST($$); }
  790. | sexpr EQ sexpr
  791. { $$ = New_BinOp( BOOLEAN, $1, EQ, $3 ); TEST($$);
  792. SIZE($$) = 1; }
  793. | sexpr NE sexpr
  794. { $$ = New_BinOp( BOOLEAN, $1, NE, $3 ); TEST($$);
  795. SIZE($$) = 1; }
  796. | sexpr GT sexpr
  797. { $$ = New_BinOp( BOOLEAN, $1, GT, $3 ); TEST($$);
  798. SIZE($$) = 1; }
  799. | sexpr GTE sexpr
  800. { $$ = New_BinOp( BOOLEAN, $1, GTE, $3 ); TEST($$);
  801. SIZE($$) = 1; }
  802. | sexpr LT sexpr
  803. { $$ = New_BinOp( BOOLEAN, $1, LT, $3 ); TEST($$);
  804. SIZE($$) = 1; }
  805. | sexpr LTE sexpr
  806. { $$ = New_BinOp( BOOLEAN, $1, LTE, $3 ); TEST($$);
  807. SIZE($$) = 1; }
  808. | bexpr AND bexpr
  809. { $$ = New_BinOp( BOOLEAN, $1, AND, $3 ); TEST($$); }
  810. | bexpr OR bexpr
  811. { $$ = New_BinOp( BOOLEAN, $1, OR, $3 ); TEST($$); }
  812. | bexpr EQ bexpr
  813. { $$ = New_BinOp( BOOLEAN, $1, EQ, $3 ); TEST($$); }
  814. | bexpr NE bexpr
  815. { $$ = New_BinOp( BOOLEAN, $1, NE, $3 ); TEST($$); }
  816. | expr '=' expr ':' expr
  817. { PROMOTE($1,$3); PROMOTE($1,$5); PROMOTE($3,$5);
  818. $3 = New_BinOp( BOOLEAN, $3, LTE, $1 );
  819. $5 = New_BinOp( BOOLEAN, $1, LTE, $5 );
  820. $$ = New_BinOp( BOOLEAN, $3, AND, $5 );
  821. TEST($$); }
  822. | bexpr '?' bexpr ':' bexpr
  823. {
  824. if( ! Test_Dims($3,$5) ) {
  825. yyerror("Incompatible dimensions in '?:' arguments");
  826. YYERROR;
  827. }
  828. $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1,
  829. 0, 0, 0, 0 );
  830. TEST($$);
  831. if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
  832. if( ! Test_Dims($1,$$) ) {
  833. yyerror("Incompatible dimensions in '?:' condition");
  834. YYERROR;
  835. }
  836. if( SIZE($$)<SIZE($1) ) Copy_Dims($$, $1);
  837. }
  838. | BFUNCTION expr ')'
  839. {
  840. if (FSTRCMP($1,"ISNULL(") == 0) {
  841. $$ = New_Func( 0, isnull_fct, 1, $2, 0, 0,
  842. 0, 0, 0, 0 );
  843. TEST($$);
  844. /* Use expression's size, but return BOOLEAN */
  845. TYPE($$) = BOOLEAN;
  846. } else {
  847. yyerror("Boolean Function(expr) not supported");
  848. YYERROR;
  849. }
  850. }
  851. | BFUNCTION bexpr ')'
  852. {
  853. if (FSTRCMP($1,"ISNULL(") == 0) {
  854. $$ = New_Func( 0, isnull_fct, 1, $2, 0, 0,
  855. 0, 0, 0, 0 );
  856. TEST($$);
  857. /* Use expression's size, but return BOOLEAN */
  858. TYPE($$) = BOOLEAN;
  859. } else {
  860. yyerror("Boolean Function(expr) not supported");
  861. YYERROR;
  862. }
  863. }
  864. | BFUNCTION sexpr ')'
  865. {
  866. if (FSTRCMP($1,"ISNULL(") == 0) {
  867. $$ = New_Func( BOOLEAN, isnull_fct, 1, $2, 0, 0,
  868. 0, 0, 0, 0 );
  869. TEST($$);
  870. } else {
  871. yyerror("Boolean Function(expr) not supported");
  872. YYERROR;
  873. }
  874. }
  875. | FUNCTION bexpr ',' bexpr ')'
  876. {
  877. if (FSTRCMP($1,"DEFNULL(") == 0) {
  878. if( SIZE($2)>=SIZE($4) && Test_Dims( $2, $4 ) ) {
  879. $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0,
  880. 0, 0, 0, 0 );
  881. TEST($$);
  882. } else {
  883. yyerror("Dimensions of DEFNULL arguments are not compatible");
  884. YYERROR;
  885. }
  886. } else {
  887. yyerror("Boolean Function(expr,expr) not supported");
  888. YYERROR;
  889. }
  890. }
  891. | BFUNCTION expr ',' expr ',' expr ')'
  892. {
  893. if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
  894. if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
  895. if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
  896. if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) ) ) {
  897. yyerror("Dimensions of NEAR arguments "
  898. "are not compatible");
  899. YYERROR;
  900. } else {
  901. if (FSTRCMP($1,"NEAR(") == 0) {
  902. $$ = New_Func( BOOLEAN, near_fct, 3, $2, $4, $6,
  903. 0, 0, 0, 0 );
  904. } else {
  905. yyerror("Boolean Function not supported");
  906. YYERROR;
  907. }
  908. TEST($$);
  909. if( SIZE($$)<SIZE($2) ) Copy_Dims($$, $2);
  910. if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
  911. if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
  912. }
  913. }
  914. | BFUNCTION expr ',' expr ',' expr ',' expr ',' expr ')'
  915. {
  916. if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
  917. if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
  918. if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
  919. if( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
  920. if( TYPE($10)!= DOUBLE ) $10= New_Unary( DOUBLE, 0, $10);
  921. if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) &&
  922. Test_Dims( $6, $8 ) && Test_Dims( $8, $10 )) ) {
  923. yyerror("Dimensions of CIRCLE arguments "
  924. "are not compatible");
  925. YYERROR;
  926. } else {
  927. if (FSTRCMP($1,"CIRCLE(") == 0) {
  928. $$ = New_Func( BOOLEAN, circle_fct, 5, $2, $4, $6, $8,
  929. $10, 0, 0 );
  930. } else {
  931. yyerror("Boolean Function not supported");
  932. YYERROR;
  933. }
  934. TEST($$);
  935. if( SIZE($$)<SIZE($2) ) Copy_Dims($$, $2);
  936. if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
  937. if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
  938. if( SIZE($6)<SIZE($8) ) Copy_Dims($$, $8);
  939. if( SIZE($8)<SIZE($10) ) Copy_Dims($$, $10);
  940. }
  941. }
  942. | BFUNCTION expr ',' expr ',' expr ',' expr ',' expr ',' expr ',' expr ')'
  943. {
  944. if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 );
  945. if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 );
  946. if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 );
  947. if( TYPE($8) != DOUBLE ) $8 = New_Unary( DOUBLE, 0, $8 );
  948. if( TYPE($10)!= DOUBLE ) $10= New_Unary( DOUBLE, 0, $10);
  949. if( TYPE($12)!= DOUBLE ) $12= New_Unary( DOUBLE, 0, $12);
  950. if( TYPE($14)!= DOUBLE ) $14= New_Unary( DOUBLE, 0, $14);
  951. if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) &&
  952. Test_Dims( $6, $8 ) && Test_Dims( $8, $10 ) &&
  953. Test_Dims($10,$12 ) && Test_Dims($12, $14 ) ) ) {
  954. yyerror("Dimensions of BOX or ELLIPSE arguments "
  955. "are not compatible");
  956. YYERROR;
  957. } else {
  958. if (FSTRCMP($1,"BOX(") == 0) {
  959. $$ = New_Func( BOOLEAN, box_fct, 7, $2, $4, $6, $8,
  960. $10, $12, $14 );
  961. } else if (FSTRCMP($1,"ELLIPSE(") == 0) {
  962. $$ = New_Func( BOOLEAN, elps_fct, 7, $2, $4, $6, $8,
  963. $10, $12, $14 );
  964. } else {
  965. yyerror("SAO Image Function not supported");
  966. YYERROR;
  967. }
  968. TEST($$);
  969. if( SIZE($$)<SIZE($2) ) Copy_Dims($$, $2);
  970. if( SIZE($2)<SIZE($4) ) Copy_Dims($$, $4);
  971. if( SIZE($4)<SIZE($6) ) Copy_Dims($$, $6);
  972. if( SIZE($6)<SIZE($8) ) Copy_Dims($$, $8);
  973. if( SIZE($8)<SIZE($10) ) Copy_Dims($$, $10);
  974. if( SIZE($10)<SIZE($12) ) Copy_Dims($$, $12);
  975. if( SIZE($12)<SIZE($14) ) Copy_Dims($$, $14);
  976. }
  977. }
  978. | GTIFILTER ')'
  979. { /* Use defaults for all elements */
  980. $$ = New_GTI( "", -99, "*START*", "*STOP*" );
  981. TEST($$); }
  982. | GTIFILTER STRING ')'
  983. { /* Use defaults for all except filename */
  984. $$ = New_GTI( $2, -99, "*START*", "*STOP*" );
  985. TEST($$); }
  986. | GTIFILTER STRING ',' expr ')'
  987. { $$ = New_GTI( $2, $4, "*START*", "*STOP*" );
  988. TEST($$); }
  989. | GTIFILTER STRING ',' expr ',' STRING ',' STRING ')'
  990. { $$ = New_GTI( $2, $4, $6, $8 );
  991. TEST($$); }
  992. | REGFILTER STRING ')'
  993. { /* Use defaults for all except filename */
  994. $$ = New_REG( $2, -99, -99, "" );
  995. TEST($$); }
  996. | REGFILTER STRING ',' expr ',' expr ')'
  997. { $$ = New_REG( $2, $4, $6, "" );
  998. TEST($$); }
  999. | REGFILTER STRING ',' expr ',' expr ',' STRING ')'
  1000. { $$ = New_REG( $2, $4, $6, $8 );
  1001. TEST($$); }
  1002. | bexpr '[' expr ']'
  1003. { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); }
  1004. | bexpr '[' expr ',' expr ']'
  1005. { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); }
  1006. | bexpr '[' expr ',' expr ',' expr ']'
  1007. { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); }
  1008. | bexpr '[' expr ',' expr ',' expr ',' expr ']'
  1009. { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); }
  1010. | bexpr '[' expr ',' expr ',' expr ',' expr ',' expr ']'
  1011. { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); }
  1012. | NOT bexpr
  1013. { $$ = New_Unary( BOOLEAN, NOT, $2 ); TEST($$); }
  1014. | '(' bexpr ')'
  1015. { $$ = $2; }
  1016. ;
  1017. sexpr: STRING
  1018. { $$ = New_Const( STRING, $1, strlen($1)+1 ); TEST($$);
  1019. SIZE($$) = strlen($1); }
  1020. | SCOLUMN
  1021. { $$ = New_Column( $1 ); TEST($$); }
  1022. | SCOLUMN '{' expr '}'
  1023. {
  1024. if( TYPE($3) != LONG
  1025. || OPER($3) != CONST_OP ) {
  1026. yyerror("Offset argument must be a constant integer");
  1027. YYERROR;
  1028. }
  1029. $$ = New_Offset( $1, $3 ); TEST($$);
  1030. }
  1031. | SNULLREF
  1032. { $$ = New_Func( STRING, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); }
  1033. | '(' sexpr ')'
  1034. { $$ = $2; }
  1035. | sexpr '+' sexpr
  1036. {
  1037. if (SIZE($1)+SIZE($3) >= MAX_STRLEN) {
  1038. yyerror("Combined string size exceeds " MAX_STRLEN_S " characters");
  1039. YYERROR;
  1040. }
  1041. $$ = New_BinOp( STRING, $1, '+', $3 ); TEST($$);
  1042. SIZE($$) = SIZE($1) + SIZE($3);
  1043. }
  1044. | bexpr '?' sexpr ':' sexpr
  1045. {
  1046. int outSize;
  1047. if( SIZE($1)!=1 ) {
  1048. yyerror("Cannot have a vector string column");
  1049. YYERROR;
  1050. }
  1051. /* Since the output can be calculated now, as a constant
  1052. scalar, we must precalculate the output size, in
  1053. order to avoid an overflow. */
  1054. outSize = SIZE($3);
  1055. if (SIZE($5) > outSize) outSize = SIZE($5);
  1056. $$ = New_FuncSize( 0, ifthenelse_fct, 3, $3, $5, $1,
  1057. 0, 0, 0, 0, outSize);
  1058. TEST($$);
  1059. if( SIZE($3)<SIZE($5) ) Copy_Dims($$, $5);
  1060. }
  1061. | FUNCTION sexpr ',' sexpr ')'
  1062. {
  1063. if (FSTRCMP($1,"DEFNULL(") == 0) {
  1064. int outSize;
  1065. /* Since the output can be calculated now, as a constant
  1066. scalar, we must precalculate the output size, in
  1067. order to avoid an overflow. */
  1068. outSize = SIZE($2);
  1069. if (SIZE($4) > outSize) outSize = SIZE($4);
  1070. $$ = New_FuncSize( 0, defnull_fct, 2, $2, $4, 0,
  1071. 0, 0, 0, 0, outSize );
  1072. TEST($$);
  1073. if( SIZE($4)>SIZE($2) ) SIZE($$) = SIZE($4);
  1074. } else {
  1075. yyerror("Function(string,string) not supported");
  1076. YYERROR;
  1077. }
  1078. }
  1079. | FUNCTION sexpr ',' expr ',' expr ')'
  1080. {
  1081. if (FSTRCMP($1,"STRMID(") == 0) {
  1082. int len;
  1083. if( TYPE($4) != LONG || SIZE($4) != 1 ||
  1084. TYPE($6) != LONG || SIZE($6) != 1) {
  1085. yyerror("When using STRMID(S,P,N), P and N must be integers (and not vector columns)");
  1086. YYERROR;
  1087. }
  1088. if (OPER($6) == CONST_OP) {
  1089. /* Constant value: use that directly */
  1090. len = (gParse.Nodes[$6].value.data.lng);
  1091. } else {
  1092. /* Variable value: use the maximum possible (from $2) */
  1093. len = SIZE($2);
  1094. }
  1095. if (len <= 0 || len >= MAX_STRLEN) {
  1096. yyerror("STRMID(S,P,N), N must be 1-" MAX_STRLEN_S);
  1097. YYERROR;
  1098. }
  1099. $$ = New_FuncSize( 0, strmid_fct, 3, $2, $4,$6,0,0,0,0,len);
  1100. TEST($$);
  1101. } else {
  1102. yyerror("Function(string,expr,expr) not supported");
  1103. YYERROR;
  1104. }
  1105. }
  1106. ;
  1107. %%
  1108. /*************************************************************************/
  1109. /* Start of "New" routines which build the expression Nodal structure */
  1110. /*************************************************************************/
  1111. static int Alloc_Node( void )
  1112. {
  1113. /* Use this for allocation to guarantee *Nodes */
  1114. Node *newNodePtr; /* survives on failure, making it still valid */
  1115. /* while working our way out of this error */
  1116. if( gParse.nNodes == gParse.nNodesAlloc ) {
  1117. if( gParse.Nodes ) {
  1118. gParse.nNodesAlloc += gParse.nNodesAlloc;
  1119. newNodePtr = (Node *)realloc( gParse.Nodes,
  1120. sizeof(Node)*gParse.nNodesAlloc );
  1121. } else {
  1122. gParse.nNodesAlloc = 100;
  1123. newNodePtr = (Node *)malloc ( sizeof(Node)*gParse.nNodesAlloc );
  1124. }
  1125. if( newNodePtr ) {
  1126. gParse.Nodes = newNodePtr;
  1127. } else {
  1128. gParse.status = MEMORY_ALLOCATION;
  1129. return( -1 );
  1130. }
  1131. }
  1132. return ( gParse.nNodes++ );
  1133. }
  1134. static void Free_Last_Node( void )
  1135. {
  1136. if( gParse.nNodes ) gParse.nNodes--;
  1137. }
  1138. static int New_Const( int returnType, void *value, long len )
  1139. {
  1140. Node *this;
  1141. int n;
  1142. n = Alloc_Node();
  1143. if( n>=0 ) {
  1144. this = gParse.Nodes + n;
  1145. this->operation = CONST_OP; /* Flag a constant */
  1146. this->DoOp = NULL;
  1147. this->nSubNodes = 0;
  1148. this->type = returnType;
  1149. memcpy( &(this->value.data), value, len );
  1150. this->value.undef = NULL;
  1151. this->value.nelem = 1;
  1152. this->value.naxis = 1;
  1153. this->value.naxes[0] = 1;
  1154. }
  1155. return(n);
  1156. }
  1157. static int New_Column( int ColNum )
  1158. {
  1159. Node *this;
  1160. int n, i;
  1161. n = Alloc_Node();
  1162. if( n>=0 ) {
  1163. this = gParse.Nodes + n;
  1164. this->operation = -ColNum;
  1165. this->DoOp = NULL;
  1166. this->nSubNodes = 0;
  1167. this->type = gParse.varData[ColNum].type;
  1168. this->value.nelem = gParse.varData[ColNum].nelem;
  1169. this->value.naxis = gParse.varData[ColNum].naxis;
  1170. for( i=0; i<gParse.varData[ColNum].naxis; i++ )
  1171. this->value.naxes[i] = gParse.varData[ColNum].naxes[i];
  1172. }
  1173. return(n);
  1174. }
  1175. static int New_Offset( int ColNum, int offsetNode )
  1176. {
  1177. Node *this;
  1178. int n, i, colNode;
  1179. colNode = New_Column( ColNum );
  1180. if( colNode<0 ) return(-1);
  1181. n = Alloc_Node();
  1182. if( n>=0 ) {
  1183. this = gParse.Nodes + n;
  1184. this->operation = '{';
  1185. this->DoOp = Do_Offset;
  1186. this->nSubNodes = 2;
  1187. this->SubNodes[0] = colNode;
  1188. this->SubNodes[1] = offsetNode;
  1189. this->type = gParse.varData[ColNum].type;
  1190. this->value.nelem = gParse.varData[ColNum].nelem;
  1191. this->value.naxis = gParse.varData[ColNum].naxis;
  1192. for( i=0; i<gParse.varData[ColNum].naxis; i++ )
  1193. this->value.naxes[i] = gParse.varData[ColNum].naxes[i];
  1194. }
  1195. return(n);
  1196. }
  1197. static int New_Unary( int returnType, int Op, int Node1 )
  1198. {
  1199. Node *this, *that;
  1200. int i,n;
  1201. if( Node1<0 ) return(-1);
  1202. that = gParse.Nodes + Node1;
  1203. if( !Op ) Op = returnType;
  1204. if( (Op==DOUBLE || Op==FLTCAST) && that->type==DOUBLE ) return( Node1 );
  1205. if( (Op==LONG || Op==INTCAST) && that->type==LONG ) return( Node1 );
  1206. if( (Op==BOOLEAN ) && that->type==BOOLEAN ) return( Node1 );
  1207. n = Alloc_Node();
  1208. if( n>=0 ) {
  1209. this = gParse.Nodes + n;
  1210. this->operation = Op;
  1211. this->DoOp = Do_Unary;
  1212. this->nSubNodes = 1;
  1213. this->SubNodes[0] = Node1;
  1214. this->type = returnType;
  1215. that = gParse.Nodes + Node1; /* Reset in case .Nodes mv'd */
  1216. this->value.nelem = that->value.nelem;
  1217. this->value.naxis = that->value.naxis;
  1218. for( i=0; i<that->value.naxis; i++ )
  1219. this->value.naxes[i] = that->value.naxes[i];
  1220. if( that->operation==CONST_OP ) this->DoOp( this );
  1221. }
  1222. return( n );
  1223. }
  1224. static int New_BinOp( int returnType, int Node1, int Op, int Node2 )
  1225. {
  1226. Node

Large files files are truncated, but you can click here to view the full file