PageRenderTime 89ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/cfitsio/eval.y

#
Happy | 5837 lines | 5275 code | 562 blank | 0 comment | 0 complexity | 05e094fffb8f04f7bfaeec5c1e661f58 MD5 | raw 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 *this,*that1,*that2;
  1227. int n,i,constant;
  1228. if( Node1<0 || Node2<0 ) return(-1);
  1229. n = Alloc_Node();
  1230. if( n>=0 ) {
  1231. this = gParse.Nodes + n;
  1232. this->operation = Op;
  1233. this->nSubNodes = 2;
  1234. this->SubNodes[0]= Node1;
  1235. this->SubNodes[1]= Node2;
  1236. this->type = returnType;
  1237. that1 = gParse.Nodes + Node1;
  1238. that2 = gParse.Nodes + Node2;
  1239. constant = (that1->operation==CONST_OP
  1240. && that2->operation==CONST_OP);
  1241. if( that1->type!=STRING && that1->type!=BITSTR )
  1242. if( !Test_Dims( Node1, Node2 ) ) {
  1243. Free_Last_Node();
  1244. yyerror("Array sizes/dims do not match for binary operator");
  1245. return(-1);
  1246. }
  1247. if( that1->value.nelem == 1 ) that1 = that2;
  1248. this->value.nelem = that1->value.nelem;
  1249. this->value.naxis = that1->value.naxis;
  1250. for( i=0; i<that1->value.naxis; i++ )
  1251. this->value.naxes[i] = that1->value.naxes[i];
  1252. if ( Op == ACCUM && that1->type == BITSTR ) {
  1253. /* ACCUM is rank-reducing on bit strings */
  1254. this->value.nelem = 1;
  1255. this->value.naxis = 1;
  1256. this->value.naxes[0] = 1;
  1257. }
  1258. /* Both subnodes should be of same time */
  1259. switch( that1->type ) {
  1260. case BITSTR: this->DoOp = Do_BinOp_bit; break;
  1261. case STRING: this->DoOp = Do_BinOp_str; break;
  1262. case BOOLEAN: this->DoOp = Do_BinOp_log; break;
  1263. case LONG: this->DoOp = Do_BinOp_lng; break;
  1264. case DOUBLE: this->DoOp = Do_BinOp_dbl; break;
  1265. }
  1266. if( constant ) this->DoOp( this );
  1267. }
  1268. return( n );
  1269. }
  1270. static int New_Func( int returnType, funcOp Op, int nNodes,
  1271. int Node1, int Node2, int Node3, int Node4,
  1272. int Node5, int Node6, int Node7 )
  1273. {
  1274. return New_FuncSize(returnType, Op, nNodes,
  1275. Node1, Node2, Node3, Node4,
  1276. Node5, Node6, Node7, 0);
  1277. }
  1278. static int New_FuncSize( int returnType, funcOp Op, int nNodes,
  1279. int Node1, int Node2, int Node3, int Node4,
  1280. int Node5, int Node6, int Node7, int Size )
  1281. /* If returnType==0 , use Node1's type and vector sizes as returnType, */
  1282. /* else return a single value of type returnType */
  1283. {
  1284. Node *this, *that;
  1285. int i,n,constant;
  1286. if( Node1<0 || Node2<0 || Node3<0 || Node4<0 ||
  1287. Node5<0 || Node6<0 || Node7<0 ) return(-1);
  1288. n = Alloc_Node();
  1289. if( n>=0 ) {
  1290. this = gParse.Nodes + n;
  1291. this->operation = (int)Op;
  1292. this->DoOp = Do_Func;
  1293. this->nSubNodes = nNodes;
  1294. this->SubNodes[0] = Node1;
  1295. this->SubNodes[1] = Node2;
  1296. this->SubNodes[2] = Node3;
  1297. this->SubNodes[3] = Node4;
  1298. this->SubNodes[4] = Node5;
  1299. this->SubNodes[5] = Node6;
  1300. this->SubNodes[6] = Node7;
  1301. i = constant = nNodes; /* Functions with zero params are not const */
  1302. if (Op == poirnd_fct) constant = 0; /* Nor is Poisson deviate */
  1303. while( i-- )
  1304. constant = ( constant && OPER(this->SubNodes[i]) == CONST_OP );
  1305. if( returnType ) {
  1306. this->type = returnType;
  1307. this->value.nelem = 1;
  1308. this->value.naxis = 1;
  1309. this->value.naxes[0] = 1;
  1310. } else {
  1311. that = gParse.Nodes + Node1;
  1312. this->type = that->type;
  1313. this->value.nelem = that->value.nelem;
  1314. this->value.naxis = that->value.naxis;
  1315. for( i=0; i<that->value.naxis; i++ )
  1316. this->value.naxes[i] = that->value.naxes[i];
  1317. }
  1318. /* Force explicit size before evaluating */
  1319. if (Size > 0) this->value.nelem = Size;
  1320. if( constant ) this->DoOp( this );
  1321. }
  1322. return( n );
  1323. }
  1324. static int New_Deref( int Var, int nDim,
  1325. int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 )
  1326. {
  1327. int n, idx, constant;
  1328. long elem=0;
  1329. Node *this, *theVar, *theDim[MAXDIMS];
  1330. if( Var<0 || Dim1<0 || Dim2<0 || Dim3<0 || Dim4<0 || Dim5<0 ) return(-1);
  1331. theVar = gParse.Nodes + Var;
  1332. if( theVar->operation==CONST_OP || theVar->value.nelem==1 ) {
  1333. yyerror("Cannot index a scalar value");
  1334. return(-1);
  1335. }
  1336. n = Alloc_Node();
  1337. if( n>=0 ) {
  1338. this = gParse.Nodes + n;
  1339. this->nSubNodes = nDim+1;
  1340. theVar = gParse.Nodes + (this->SubNodes[0]=Var);
  1341. theDim[0] = gParse.Nodes + (this->SubNodes[1]=Dim1);
  1342. theDim[1] = gParse.Nodes + (this->SubNodes[2]=Dim2);
  1343. theDim[2] = gParse.Nodes + (this->SubNodes[3]=Dim3);
  1344. theDim[3] = gParse.Nodes + (this->SubNodes[4]=Dim4);
  1345. theDim[4] = gParse.Nodes + (this->SubNodes[5]=Dim5);
  1346. constant = theVar->operation==CONST_OP;
  1347. for( idx=0; idx<nDim; idx++ )
  1348. constant = (constant && theDim[idx]->operation==CONST_OP);
  1349. for( idx=0; idx<nDim; idx++ )
  1350. if( theDim[idx]->value.nelem>1 ) {
  1351. Free_Last_Node();
  1352. yyerror("Cannot use an array as an index value");
  1353. return(-1);
  1354. } else if( theDim[idx]->type!=LONG ) {
  1355. Free_Last_Node();
  1356. yyerror("Index value must be an integer type");
  1357. return(-1);
  1358. }
  1359. this->operation = '[';
  1360. this->DoOp = Do_Deref;
  1361. this->type = theVar->type;
  1362. if( theVar->value.naxis == nDim ) { /* All dimensions specified */
  1363. this->value.nelem = 1;
  1364. this->value.naxis = 1;
  1365. this->value.naxes[0] = 1;
  1366. } else if( nDim==1 ) { /* Dereference only one dimension */
  1367. elem=1;
  1368. this->value.naxis = theVar->value.naxis-1;
  1369. for( idx=0; idx<this->value.naxis; idx++ ) {
  1370. elem *= ( this->value.naxes[idx] = theVar->value.naxes[idx] );
  1371. }
  1372. this->value.nelem = elem;
  1373. } else {
  1374. Free_Last_Node();
  1375. yyerror("Must specify just one or all indices for vector");
  1376. return(-1);
  1377. }
  1378. if( constant ) this->DoOp( this );
  1379. }
  1380. return(n);
  1381. }
  1382. extern int yyGetVariable( char *varName, YYSTYPE *varVal );
  1383. static int New_GTI( char *fname, int Node1, char *start, char *stop )
  1384. {
  1385. fitsfile *fptr;
  1386. Node *this, *that0, *that1;
  1387. int type,i,n, startCol, stopCol, Node0;
  1388. int hdutype, hdunum, evthdu, samefile, extvers, movetotype, tstat;
  1389. char extname[100];
  1390. long nrows;
  1391. double timeZeroI[2], timeZeroF[2], dt, timeSpan;
  1392. char xcol[20], xexpr[20];
  1393. YYSTYPE colVal;
  1394. if( Node1==-99 ) {
  1395. type = yyGetVariable( "TIME", &colVal );
  1396. if( type==COLUMN ) {
  1397. Node1 = New_Column( (int)colVal.lng );
  1398. } else {
  1399. yyerror("Could not build TIME column for GTIFILTER");
  1400. return(-1);
  1401. }
  1402. }
  1403. Node1 = New_Unary( DOUBLE, 0, Node1 );
  1404. Node0 = Alloc_Node(); /* This will hold the START/STOP times */
  1405. if( Node1<0 || Node0<0 ) return(-1);
  1406. /* Record current HDU number in case we need to move within this file */
  1407. fptr = gParse.def_fptr;
  1408. ffghdn( fptr, &evthdu );
  1409. /* Look for TIMEZERO keywords in current extension */
  1410. tstat = 0;
  1411. if( ffgkyd( fptr, "TIMEZERO", timeZeroI, NULL, &tstat ) ) {
  1412. tstat = 0;
  1413. if( ffgkyd( fptr, "TIMEZERI", timeZeroI, NULL, &tstat ) ) {
  1414. timeZeroI[0] = timeZeroF[0] = 0.0;
  1415. } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF, NULL, &tstat ) ) {
  1416. timeZeroF[0] = 0.0;
  1417. }
  1418. } else {
  1419. timeZeroF[0] = 0.0;
  1420. }
  1421. /* Resolve filename parameter */
  1422. switch( fname[0] ) {
  1423. case '\0':
  1424. samefile = 1;
  1425. hdunum = 1;
  1426. break;
  1427. case '[':
  1428. samefile = 1;
  1429. i = 1;
  1430. while( fname[i] != '\0' && fname[i] != ']' ) i++;
  1431. if( fname[i] ) {
  1432. fname[i] = '\0';
  1433. fname++;
  1434. ffexts( fname, &hdunum, extname, &extvers, &movetotype,
  1435. xcol, xexpr, &gParse.status );
  1436. if( *extname ) {
  1437. ffmnhd( fptr, movetotype, extname, extvers, &gParse.status );
  1438. ffghdn( fptr, &hdunum );
  1439. } else if( hdunum ) {
  1440. ffmahd( fptr, ++hdunum, &hdutype, &gParse.status );
  1441. } else if( !gParse.status ) {
  1442. yyerror("Cannot use primary array for GTI filter");
  1443. return( -1 );
  1444. }
  1445. } else {
  1446. yyerror("File extension specifier lacks closing ']'");
  1447. return( -1 );
  1448. }
  1449. break;
  1450. case '+':
  1451. samefile = 1;
  1452. hdunum = atoi( fname ) + 1;
  1453. if( hdunum>1 )
  1454. ffmahd( fptr, hdunum, &hdutype, &gParse.status );
  1455. else {
  1456. yyerror("Cannot use primary array for GTI filter");
  1457. return( -1 );
  1458. }
  1459. break;
  1460. default:
  1461. samefile = 0;
  1462. if( ! ffopen( &fptr, fname, READONLY, &gParse.status ) )
  1463. ffghdn( fptr, &hdunum );
  1464. break;
  1465. }
  1466. if( gParse.status ) return(-1);
  1467. /* If at primary, search for GTI extension */
  1468. if( hdunum==1 ) {
  1469. while( 1 ) {
  1470. hdunum++;
  1471. if( ffmahd( fptr, hdunum, &hdutype, &gParse.status ) ) break;
  1472. if( hdutype==IMAGE_HDU ) continue;
  1473. tstat = 0;
  1474. if( ffgkys( fptr, "EXTNAME", extname, NULL, &tstat ) ) continue;
  1475. ffupch( extname );
  1476. if( strstr( extname, "GTI" ) ) break;
  1477. }
  1478. if( gParse.status ) {
  1479. if( gParse.status==END_OF_FILE )
  1480. yyerror("GTI extension not found in this file");
  1481. return(-1);
  1482. }
  1483. }
  1484. /* Locate START/STOP Columns */
  1485. ffgcno( fptr, CASEINSEN, start, &startCol, &gParse.status );
  1486. ffgcno( fptr, CASEINSEN, stop, &stopCol, &gParse.status );
  1487. if( gParse.status ) return(-1);
  1488. /* Look for TIMEZERO keywords in GTI extension */
  1489. tstat = 0;
  1490. if( ffgkyd( fptr, "TIMEZERO", timeZeroI+1, NULL, &tstat ) ) {
  1491. tstat = 0;
  1492. if( ffgkyd( fptr, "TIMEZERI", timeZeroI+1, NULL, &tstat ) ) {
  1493. timeZeroI[1] = timeZeroF[1] = 0.0;
  1494. } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF+1, NULL, &tstat ) ) {
  1495. timeZeroF[1] = 0.0;
  1496. }
  1497. } else {
  1498. timeZeroF[1] = 0.0;
  1499. }
  1500. n = Alloc_Node();
  1501. if( n >= 0 ) {
  1502. this = gParse.Nodes + n;
  1503. this->nSubNodes = 2;
  1504. this->SubNodes[1] = Node1;
  1505. this->operation = (int)gtifilt_fct;
  1506. this->DoOp = Do_GTI;
  1507. this->type = BOOLEAN;
  1508. that1 = gParse.Nodes + Node1;
  1509. this->value.nelem = that1->value.nelem;
  1510. this->value.naxis = that1->value.naxis;
  1511. for( i=0; i < that1->value.naxis; i++ )
  1512. this->value.naxes[i] = that1->value.naxes[i];
  1513. /* Init START/STOP node to be treated as a "constant" */
  1514. this->SubNodes[0] = Node0;
  1515. that0 = gParse.Nodes + Node0;
  1516. that0->operation = CONST_OP;
  1517. that0->DoOp = NULL;
  1518. that0->value.data.ptr= NULL;
  1519. /* Read in START/STOP times */
  1520. if( ffgkyj( fptr, "NAXIS2", &nrows, NULL, &gParse.status ) )
  1521. return(-1);
  1522. that0->value.nelem = nrows;
  1523. if( nrows ) {
  1524. that0->value.data.dblptr = (double*)malloc( 2*nrows*sizeof(double) );
  1525. if( !that0->value.data.dblptr ) {
  1526. gParse.status = MEMORY_ALLOCATION;
  1527. return(-1);
  1528. }
  1529. ffgcvd( fptr, startCol, 1L, 1L, nrows, 0.0,
  1530. that0->value.data.dblptr, &i, &gParse.status );
  1531. ffgcvd( fptr, stopCol, 1L, 1L, nrows, 0.0,
  1532. that0->value.data.dblptr+nrows, &i, &gParse.status );
  1533. if( gParse.status ) {
  1534. free( that0->value.data.dblptr );
  1535. return(-1);
  1536. }
  1537. /* Test for fully time-ordered GTI... both START && STOP */
  1538. that0->type = 1; /* Assume yes */
  1539. i = nrows;
  1540. while( --i )
  1541. if( that0->value.data.dblptr[i-1]
  1542. >= that0->value.data.dblptr[i]
  1543. || that0->value.data.dblptr[i-1+nrows]
  1544. >= that0->value.data.dblptr[i+nrows] ) {
  1545. that0->type = 0;
  1546. break;
  1547. }
  1548. /* Handle TIMEZERO offset, if any */
  1549. dt = (timeZeroI[1] - timeZeroI[0]) + (timeZeroF[1] - timeZeroF[0]);
  1550. timeSpan = that0->value.data.dblptr[nrows+nrows-1]
  1551. - that0->value.data.dblptr[0];
  1552. if( fabs( dt / timeSpan ) > 1e-12 ) {
  1553. for( i=0; i<(nrows+nrows); i++ )
  1554. that0->value.data.dblptr[i] += dt;
  1555. }
  1556. }
  1557. if( OPER(Node1)==CONST_OP )
  1558. this->DoOp( this );
  1559. }
  1560. if( samefile )
  1561. ffmahd( fptr, evthdu, &hdutype, &gParse.status );
  1562. else
  1563. ffclos( fptr, &gParse.status );
  1564. return( n );
  1565. }
  1566. static int New_REG( char *fname, int NodeX, int NodeY, char *colNames )
  1567. {
  1568. Node *this, *that0;
  1569. int type, n, Node0;
  1570. int Xcol, Ycol, tstat;
  1571. WCSdata wcs;
  1572. SAORegion *Rgn;
  1573. char *cX, *cY;
  1574. YYSTYPE colVal;
  1575. if( NodeX==-99 ) {
  1576. type = yyGetVariable( "X", &colVal );
  1577. if( type==COLUMN ) {
  1578. NodeX = New_Column( (int)colVal.lng );
  1579. } else {
  1580. yyerror("Could not build X column for REGFILTER");
  1581. return(-1);
  1582. }
  1583. }
  1584. if( NodeY==-99 ) {
  1585. type = yyGetVariable( "Y", &colVal );
  1586. if( type==COLUMN ) {
  1587. NodeY = New_Column( (int)colVal.lng );
  1588. } else {
  1589. yyerror("Could not build Y column for REGFILTER");
  1590. return(-1);
  1591. }
  1592. }
  1593. NodeX = New_Unary( DOUBLE, 0, NodeX );
  1594. NodeY = New_Unary( DOUBLE, 0, NodeY );
  1595. Node0 = Alloc_Node(); /* This will hold the Region Data */
  1596. if( NodeX<0 || NodeY<0 || Node0<0 ) return(-1);
  1597. if( ! (Test_Dims( NodeX, NodeY ) ) ) {
  1598. yyerror("Dimensions of REGFILTER arguments are not compatible");
  1599. return (-1);
  1600. }
  1601. n = Alloc_Node();
  1602. if( n >= 0 ) {
  1603. this = gParse.Nodes + n;
  1604. this->nSubNodes = 3;
  1605. this->SubNodes[0] = Node0;
  1606. this->SubNodes[1] = NodeX;
  1607. this->SubNodes[2] = NodeY;
  1608. this->operation = (int)regfilt_fct;
  1609. this->DoOp = Do_REG;
  1610. this->type = BOOLEAN;
  1611. this->value.nelem = 1;
  1612. this->value.naxis = 1;
  1613. this->value.naxes[0] = 1;
  1614. Copy_Dims(n, NodeX);
  1615. if( SIZE(NodeX)<SIZE(NodeY) ) Copy_Dims(n, NodeY);
  1616. /* Init Region node to be treated as a "constant" */
  1617. that0 = gParse.Nodes + Node0;
  1618. that0->operation = CONST_OP;
  1619. that0->DoOp = NULL;
  1620. /* Identify what columns to use for WCS information */
  1621. Xcol = Ycol = 0;
  1622. if( *colNames ) {
  1623. /* Use the column names in this string for WCS info */
  1624. while( *colNames==' ' ) colNames++;
  1625. cX = cY = colNames;
  1626. while( *cY && *cY!=' ' && *cY!=',' ) cY++;
  1627. if( *cY )
  1628. *(cY++) = '\0';
  1629. while( *cY==' ' ) cY++;
  1630. if( !*cY ) {
  1631. yyerror("Could not extract valid pair of column names from REGFILTER");
  1632. Free_Last_Node();
  1633. return( -1 );
  1634. }
  1635. fits_get_colnum( gParse.def_fptr, CASEINSEN, cX, &Xcol,
  1636. &gParse.status );
  1637. fits_get_colnum( gParse.def_fptr, CASEINSEN, cY, &Ycol,
  1638. &gParse.status );
  1639. if( gParse.status ) {
  1640. yyerror("Could not locate columns indicated for WCS info");
  1641. Free_Last_Node();
  1642. return( -1 );
  1643. }
  1644. } else {
  1645. /* Try to find columns used in X/Y expressions */
  1646. Xcol = Locate_Col( gParse.Nodes + NodeX );
  1647. Ycol = Locate_Col( gParse.Nodes + NodeY );
  1648. if( Xcol<0 || Ycol<0 ) {
  1649. yyerror("Found multiple X/Y column references in REGFILTER");
  1650. Free_Last_Node();
  1651. return( -1 );
  1652. }
  1653. }
  1654. /* Now, get the WCS info, if it exists, from the indicated columns */
  1655. wcs.exists = 0;
  1656. if( Xcol>0 && Ycol>0 ) {
  1657. tstat = 0;
  1658. ffgtcs( gParse.def_fptr, Xcol, Ycol,
  1659. &wcs.xrefval, &wcs.yrefval,
  1660. &wcs.xrefpix, &wcs.yrefpix,
  1661. &wcs.xinc, &wcs.yinc,
  1662. &wcs.rot, wcs.type,
  1663. &tstat );
  1664. if( tstat==NO_WCS_KEY ) {
  1665. wcs.exists = 0;
  1666. } else if( tstat ) {
  1667. gParse.status = tstat;
  1668. Free_Last_Node();
  1669. return( -1 );
  1670. } else {
  1671. wcs.exists = 1;
  1672. }
  1673. }
  1674. /* Read in Region file */
  1675. fits_read_rgnfile( fname, &wcs, &Rgn, &gParse.status );
  1676. if( gParse.status ) {
  1677. Free_Last_Node();
  1678. return( -1 );
  1679. }
  1680. that0->value.data.ptr = Rgn;
  1681. if( OPER(NodeX)==CONST_OP && OPER(NodeY)==CONST_OP )
  1682. this->DoOp( this );
  1683. }
  1684. return( n );
  1685. }
  1686. static int New_Vector( int subNode )
  1687. {
  1688. Node *this, *that;
  1689. int n;
  1690. n = Alloc_Node();
  1691. if( n >= 0 ) {
  1692. this = gParse.Nodes + n;
  1693. that = gParse.Nodes + subNode;
  1694. this->type = that->type;
  1695. this->nSubNodes = 1;
  1696. this->SubNodes[0] = subNode;
  1697. this->operation = '{';
  1698. this->DoOp = Do_Vector;
  1699. }
  1700. return( n );
  1701. }
  1702. static int Close_Vec( int vecNode )
  1703. {
  1704. Node *this;
  1705. int n, nelem=0;
  1706. this = gParse.Nodes + vecNode;
  1707. for( n=0; n < this->nSubNodes; n++ ) {
  1708. if( TYPE( this->SubNodes[n] ) != this->type ) {
  1709. this->SubNodes[n] = New_Unary( this->type, 0, this->SubNodes[n] );
  1710. if( this->SubNodes[n]<0 ) return(-1);
  1711. }
  1712. nelem += SIZE(this->SubNodes[n]);
  1713. }
  1714. this->value.naxis = 1;
  1715. this->value.nelem = nelem;
  1716. this->value.naxes[0] = nelem;
  1717. return( vecNode );
  1718. }
  1719. static int Locate_Col( Node *this )
  1720. /* Locate the TABLE column number of any columns in "this" calculation. */
  1721. /* Return ZERO if none found, or negative if more than 1 found. */
  1722. {
  1723. Node *that;
  1724. int i, col=0, newCol, nfound=0;
  1725. if( this->nSubNodes==0
  1726. && this->operation<=0 && this->operation!=CONST_OP )
  1727. return gParse.colData[ - this->operation].colnum;
  1728. for( i=0; i<this->nSubNodes; i++ ) {
  1729. that = gParse.Nodes + this->SubNodes[i];
  1730. if( that->operation>0 ) {
  1731. newCol = Locate_Col( that );
  1732. if( newCol<=0 ) {
  1733. nfound += -newCol;
  1734. } else {
  1735. if( !nfound ) {
  1736. col = newCol;
  1737. nfound++;
  1738. } else if( col != newCol ) {
  1739. nfound++;
  1740. }
  1741. }
  1742. } else if( that->operation!=CONST_OP ) {
  1743. /* Found a Column */
  1744. newCol = gParse.colData[- that->operation].colnum;
  1745. if( !nfound ) {
  1746. col = newCol;
  1747. nfound++;
  1748. } else if( col != newCol ) {
  1749. nfound++;
  1750. }
  1751. }
  1752. }
  1753. if( nfound!=1 )
  1754. return( - nfound );
  1755. else
  1756. return( col );
  1757. }
  1758. static int Test_Dims( int Node1, int Node2 )
  1759. {
  1760. Node *that1, *that2;
  1761. int valid, i;
  1762. if( Node1<0 || Node2<0 ) return(0);
  1763. that1 = gParse.Nodes + Node1;
  1764. that2 = gParse.Nodes + Node2;
  1765. if( that1->value.nelem==1 || that2->value.nelem==1 )
  1766. valid = 1;
  1767. else if( that1->type==that2->type
  1768. && that1->value.nelem==that2->value.nelem
  1769. && that1->value.naxis==that2->value.naxis ) {
  1770. valid = 1;
  1771. for( i=0; i<that1->value.naxis; i++ ) {
  1772. if( that1->value.naxes[i]!=that2->value.naxes[i] )
  1773. valid = 0;
  1774. }
  1775. } else
  1776. valid = 0;
  1777. return( valid );
  1778. }
  1779. static void Copy_Dims( int Node1, int Node2 )
  1780. {
  1781. Node *that1, *that2;
  1782. int i;
  1783. if( Node1<0 || Node2<0 ) return;
  1784. that1 = gParse.Nodes + Node1;
  1785. that2 = gParse.Nodes + Node2;
  1786. that1->value.nelem = that2->value.nelem;
  1787. that1->value.naxis = that2->value.naxis;
  1788. for( i=0; i<that2->value.naxis; i++ )
  1789. that1->value.naxes[i] = that2->value.naxes[i];
  1790. }
  1791. /********************************************************************/
  1792. /* Routines for actually evaluating the expression start here */
  1793. /********************************************************************/
  1794. void Evaluate_Parser( long firstRow, long nRows )
  1795. /***********************************************************************/
  1796. /* Reset the parser for processing another batch of data... */
  1797. /* firstRow: Row number of the first element to evaluate */
  1798. /* nRows: Number of rows to be processed */
  1799. /* Initialize each COLUMN node so that its UNDEF and DATA pointers */
  1800. /* point to the appropriate column arrays. */
  1801. /* Finally, call Evaluate_Node for final node. */
  1802. /***********************************************************************/
  1803. {
  1804. int i, column;
  1805. long offset, rowOffset;
  1806. gParse.firstRow = firstRow;
  1807. gParse.nRows = nRows;
  1808. /* Reset Column Nodes' pointers to point to right data and UNDEF arrays */
  1809. rowOffset = firstRow - gParse.firstDataRow;
  1810. for( i=0; i<gParse.nNodes; i++ ) {
  1811. if( OPER(i) > 0 || OPER(i) == CONST_OP ) continue;
  1812. column = -OPER(i);
  1813. offset = gParse.varData[column].nelem * rowOffset;
  1814. gParse.Nodes[i].value.undef = gParse.varData[column].undef + offset;
  1815. switch( gParse.Nodes[i].type ) {
  1816. case BITSTR:
  1817. gParse.Nodes[i].value.data.strptr =
  1818. (char**)gParse.varData[column].data + rowOffset;
  1819. gParse.Nodes[i].value.undef = NULL;
  1820. break;
  1821. case STRING:
  1822. gParse.Nodes[i].value.data.strptr =
  1823. (char**)gParse.varData[column].data + rowOffset;
  1824. gParse.Nodes[i].value.undef = gParse.varData[column].undef + rowOffset;
  1825. break;
  1826. case BOOLEAN:
  1827. gParse.Nodes[i].value.data.logptr =
  1828. (char*)gParse.varData[column].data + offset;
  1829. break;
  1830. case LONG:
  1831. gParse.Nodes[i].value.data.lngptr =
  1832. (long*)gParse.varData[column].data + offset;
  1833. break;
  1834. case DOUBLE:
  1835. gParse.Nodes[i].value.data.dblptr =
  1836. (double*)gParse.varData[column].data + offset;
  1837. break;
  1838. }
  1839. }
  1840. Evaluate_Node( gParse.resultNode );
  1841. }
  1842. static void Evaluate_Node( int thisNode )
  1843. /**********************************************************************/
  1844. /* Recursively evaluate thisNode's subNodes, then call one of the */
  1845. /* Do_<Action> functions pointed to by thisNode's DoOp element. */
  1846. /**********************************************************************/
  1847. {
  1848. Node *this;
  1849. int i;
  1850. if( gParse.status ) return;
  1851. this = gParse.Nodes + thisNode;
  1852. if( this->operation>0 ) { /* <=0 indicate constants and columns */
  1853. i = this->nSubNodes;
  1854. while( i-- ) {
  1855. Evaluate_Node( this->SubNodes[i] );
  1856. if( gParse.status ) return;
  1857. }
  1858. this->DoOp( this );
  1859. }
  1860. }
  1861. static void Allocate_Ptrs( Node *this )
  1862. {
  1863. long elem, row, size;
  1864. if( this->type==BITSTR || this->type==STRING ) {
  1865. this->value.data.strptr = (char**)malloc( gParse.nRows
  1866. * sizeof(char*) );
  1867. if( this->value.data.strptr ) {
  1868. this->value.data.strptr[0] = (char*)malloc( gParse.nRows
  1869. * (this->value.nelem+2)
  1870. * sizeof(char) );
  1871. if( this->value.data.strptr[0] ) {
  1872. row = 0;
  1873. while( (++row)<gParse.nRows ) {
  1874. this->value.data.strptr[row] =
  1875. this->value.data.strptr[row-1] + this->value.nelem+1;
  1876. }
  1877. if( this->type==STRING ) {
  1878. this->value.undef = this->value.data.strptr[row-1]
  1879. + this->value.nelem+1;
  1880. } else {
  1881. this->value.undef = NULL; /* BITSTRs don't use undef array */
  1882. }
  1883. } else {
  1884. gParse.status = MEMORY_ALLOCATION;
  1885. free( this->value.data.strptr );
  1886. }
  1887. } else {
  1888. gParse.status = MEMORY_ALLOCATION;
  1889. }
  1890. } else {
  1891. elem = this->value.nelem * gParse.nRows;
  1892. switch( this->type ) {
  1893. case DOUBLE: size = sizeof( double ); break;
  1894. case LONG: size = sizeof( long ); break;
  1895. case BOOLEAN: size = sizeof( char ); break;
  1896. default: size = 1; break;
  1897. }
  1898. this->value.data.ptr = calloc(size+1, elem);
  1899. if( this->value.data.ptr==NULL ) {
  1900. gParse.status = MEMORY_ALLOCATION;
  1901. } else {
  1902. this->value.undef = (char *)this->value.data.ptr + elem*size;
  1903. }
  1904. }
  1905. }
  1906. static void Do_Unary( Node *this )
  1907. {
  1908. Node *that;
  1909. long elem;
  1910. that = gParse.Nodes + this->SubNodes[0];
  1911. if( that->operation==CONST_OP ) { /* Operating on a constant! */
  1912. switch( this->operation ) {
  1913. case DOUBLE:
  1914. case FLTCAST:
  1915. if( that->type==LONG )
  1916. this->value.data.dbl = (double)that->value.data.lng;
  1917. else if( that->type==BOOLEAN )
  1918. this->value.data.dbl = ( that->value.data.log ? 1.0 : 0.0 );
  1919. break;
  1920. case LONG:
  1921. case INTCAST:
  1922. if( that->type==DOUBLE )
  1923. this->value.data.lng = (long)that->value.data.dbl;
  1924. else if( that->type==BOOLEAN )
  1925. this->value.data.lng = ( that->value.data.log ? 1L : 0L );
  1926. break;
  1927. case BOOLEAN:
  1928. if( that->type==DOUBLE )
  1929. this->value.data.log = ( that->value.data.dbl != 0.0 );
  1930. else if( that->type==LONG )
  1931. this->value.data.log = ( that->value.data.lng != 0L );
  1932. break;
  1933. case UMINUS:
  1934. if( that->type==DOUBLE )
  1935. this->value.data.dbl = - that->value.data.dbl;
  1936. else if( that->type==LONG )
  1937. this->value.data.lng = - that->value.data.lng;
  1938. break;
  1939. case NOT:
  1940. if( that->type==BOOLEAN )
  1941. this->value.data.log = ( ! that->value.data.log );
  1942. else if( that->type==BITSTR )
  1943. bitnot( this->value.data.str, that->value.data.str );
  1944. break;
  1945. }
  1946. this->operation = CONST_OP;
  1947. } else {
  1948. Allocate_Ptrs( this );
  1949. if( !gParse.status ) {
  1950. if( this->type!=BITSTR ) {
  1951. elem = gParse.nRows;
  1952. if( this->type!=STRING )
  1953. elem *= this->value.nelem;
  1954. while( elem-- )
  1955. this->value.undef[elem] = that->value.undef[elem];
  1956. }
  1957. elem = gParse.nRows * this->value.nelem;
  1958. switch( this->operation ) {
  1959. case BOOLEAN:
  1960. if( that->type==DOUBLE )
  1961. while( elem-- )
  1962. this->value.data.logptr[elem] =
  1963. ( that->value.data.dblptr[elem] != 0.0 );
  1964. else if( that->type==LONG )
  1965. while( elem-- )
  1966. this->value.data.logptr[elem] =
  1967. ( that->value.data.lngptr[elem] != 0L );
  1968. break;
  1969. case DOUBLE:
  1970. case FLTCAST:
  1971. if( that->type==LONG )
  1972. while( elem-- )
  1973. this->value.data.dblptr[elem] =
  1974. (double)that->value.data.lngptr[elem];
  1975. else if( that->type==BOOLEAN )
  1976. while( elem-- )
  1977. this->value.data.dblptr[elem] =
  1978. ( that->value.data.logptr[elem] ? 1.0 : 0.0 );
  1979. break;
  1980. case LONG:
  1981. case INTCAST:
  1982. if( that->type==DOUBLE )
  1983. while( elem-- )
  1984. this->value.data.lngptr[elem] =
  1985. (long)that->value.data.dblptr[elem];
  1986. else if( that->type==BOOLEAN )
  1987. while( elem-- )
  1988. this->value.data.lngptr[elem] =
  1989. ( that->value.data.logptr[elem] ? 1L : 0L );
  1990. break;
  1991. case UMINUS:
  1992. if( that->type==DOUBLE ) {
  1993. while( elem-- )
  1994. this->value.data.dblptr[elem] =
  1995. - that->value.data.dblptr[elem];
  1996. } else if( that->type==LONG ) {
  1997. while( elem-- )
  1998. this->value.data.lngptr[elem] =
  1999. - that->value.data.lngptr[elem];
  2000. }
  2001. break;
  2002. case NOT:
  2003. if( that->type==BOOLEAN ) {
  2004. while( elem-- )
  2005. this->value.data.logptr[elem] =
  2006. ( ! that->value.data.logptr[elem] );
  2007. } else if( that->type==BITSTR ) {
  2008. elem = gParse.nRows;
  2009. while( elem-- )
  2010. bitnot( this->value.data.strptr[elem],
  2011. that->value.data.strptr[elem] );
  2012. }
  2013. break;
  2014. }
  2015. }
  2016. }
  2017. if( that->operation>0 ) {
  2018. free( that->value.data.ptr );
  2019. }
  2020. }
  2021. static void Do_Offset( Node *this )
  2022. {
  2023. Node *col;
  2024. long fRow, nRowOverlap, nRowReload, rowOffset;
  2025. long nelem, elem, offset, nRealElem;
  2026. int status;
  2027. col = gParse.Nodes + this->SubNodes[0];
  2028. rowOffset = gParse.Nodes[ this->SubNodes[1] ].value.data.lng;
  2029. Allocate_Ptrs( this );
  2030. fRow = gParse.firstRow + rowOffset;
  2031. if( this->type==STRING || this->type==BITSTR )
  2032. nRealElem = 1;
  2033. else
  2034. nRealElem = this->value.nelem;
  2035. nelem = nRealElem;
  2036. if( fRow < gParse.firstDataRow ) {
  2037. /* Must fill in data at start of array */
  2038. nRowReload = gParse.firstDataRow - fRow;
  2039. if( nRowReload > gParse.nRows ) nRowReload = gParse.nRows;
  2040. nRowOverlap = gParse.nRows - nRowReload;
  2041. offset = 0;
  2042. /* NULLify any values falling out of bounds */
  2043. while( fRow<1 && nRowReload>0 ) {
  2044. if( this->type == BITSTR ) {
  2045. nelem = this->value.nelem;
  2046. this->value.data.strptr[offset][ nelem ] = '\0';
  2047. while( nelem-- ) this->value.data.strptr[offset][nelem] = '0';
  2048. offset++;
  2049. } else {
  2050. while( nelem-- )
  2051. this->value.undef[offset++] = 1;
  2052. }
  2053. nelem = nRealElem;
  2054. fRow++;
  2055. nRowReload--;
  2056. }
  2057. } else if( fRow + gParse.nRows > gParse.firstDataRow + gParse.nDataRows ) {
  2058. /* Must fill in data at end of array */
  2059. nRowReload = (fRow+gParse.nRows) - (gParse.firstDataRow+gParse.nDataRows);
  2060. if( nRowReload>gParse.nRows ) {
  2061. nRowReload = gParse.nRows;
  2062. } else {
  2063. fRow = gParse.firstDataRow + gParse.nDataRows;
  2064. }
  2065. nRowOverlap = gParse.nRows - nRowReload;
  2066. offset = nRowOverlap * nelem;
  2067. /* NULLify any values falling out of bounds */
  2068. elem = gParse.nRows * nelem;
  2069. while( fRow+nRowReload>gParse.totalRows && nRowReload>0 ) {
  2070. if( this->type == BITSTR ) {
  2071. nelem = this->value.nelem;
  2072. elem--;
  2073. this->value.data.strptr[elem][ nelem ] = '\0';
  2074. while( nelem-- ) this->value.data.strptr[elem][nelem] = '0';
  2075. } else {
  2076. while( nelem-- )
  2077. this->value.undef[--elem] = 1;
  2078. }
  2079. nelem = nRealElem;
  2080. nRowReload--;
  2081. }
  2082. } else {
  2083. nRowReload = 0;
  2084. nRowOverlap = gParse.nRows;
  2085. offset = 0;
  2086. }
  2087. if( nRowReload>0 ) {
  2088. switch( this->type ) {
  2089. case BITSTR:
  2090. case STRING:
  2091. status = (*gParse.loadData)( -col->operation, fRow, nRowReload,
  2092. this->value.data.strptr+offset,
  2093. this->value.undef+offset );
  2094. break;
  2095. case BOOLEAN:
  2096. status = (*gParse.loadData)( -col->operation, fRow, nRowReload,
  2097. this->value.data.logptr+offset,
  2098. this->value.undef+offset );
  2099. break;
  2100. case LONG:
  2101. status = (*gParse.loadData)( -col->operation, fRow, nRowReload,
  2102. this->value.data.lngptr+offset,
  2103. this->value.undef+offset );
  2104. break;
  2105. case DOUBLE:
  2106. status = (*gParse.loadData)( -col->operation, fRow, nRowReload,
  2107. this->value.data.dblptr+offset,
  2108. this->value.undef+offset );
  2109. break;
  2110. }
  2111. }
  2112. /* Now copy over the overlapping region, if any */
  2113. if( nRowOverlap <= 0 ) return;
  2114. if( rowOffset>0 )
  2115. elem = nRowOverlap * nelem;
  2116. else
  2117. elem = gParse.nRows * nelem;
  2118. offset = nelem * rowOffset;
  2119. while( nRowOverlap-- && !gParse.status ) {
  2120. while( nelem-- && !gParse.status ) {
  2121. elem--;
  2122. if( this->type != BITSTR )
  2123. this->value.undef[elem] = col->value.undef[elem+offset];
  2124. switch( this->type ) {
  2125. case BITSTR:
  2126. strcpy( this->value.data.strptr[elem ],
  2127. col->value.data.strptr[elem+offset] );
  2128. break;
  2129. case STRING:
  2130. strcpy( this->value.data.strptr[elem ],
  2131. col->value.data.strptr[elem+offset] );
  2132. break;
  2133. case BOOLEAN:
  2134. this->value.data.logptr[elem] = col->value.data.logptr[elem+offset];
  2135. break;
  2136. case LONG:
  2137. this->value.data.lngptr[elem] = col->value.data.lngptr[elem+offset];
  2138. break;
  2139. case DOUBLE:
  2140. this->value.data.dblptr[elem] = col->value.data.dblptr[elem+offset];
  2141. break;
  2142. }
  2143. }
  2144. nelem = nRealElem;
  2145. }
  2146. }
  2147. static void Do_BinOp_bit( Node *this )
  2148. {
  2149. Node *that1, *that2;
  2150. char *sptr1=NULL, *sptr2=NULL;
  2151. int const1, const2;
  2152. long rows;
  2153. that1 = gParse.Nodes + this->SubNodes[0];
  2154. that2 = gParse.Nodes + this->SubNodes[1];
  2155. const1 = ( that1->operation==CONST_OP );
  2156. const2 = ( that2->operation==CONST_OP );
  2157. sptr1 = ( const1 ? that1->value.data.str : NULL );
  2158. sptr2 = ( const2 ? that2->value.data.str : NULL );
  2159. if( const1 && const2 ) {
  2160. switch( this->operation ) {
  2161. case NE:
  2162. this->value.data.log = !bitcmp( sptr1, sptr2 );
  2163. break;
  2164. case EQ:
  2165. this->value.data.log = bitcmp( sptr1, sptr2 );
  2166. break;
  2167. case GT:
  2168. case LT:
  2169. case LTE:
  2170. case GTE:
  2171. this->value.data.log = bitlgte( sptr1, this->operation, sptr2 );
  2172. break;
  2173. case '|':
  2174. bitor( this->value.data.str, sptr1, sptr2 );
  2175. break;
  2176. case '&':
  2177. bitand( this->value.data.str, sptr1, sptr2 );
  2178. break;
  2179. case '+':
  2180. strcpy( this->value.data.str, sptr1 );
  2181. strcat( this->value.data.str, sptr2 );
  2182. break;
  2183. case ACCUM:
  2184. this->value.data.lng = 0;
  2185. while( *sptr1 ) {
  2186. if ( *sptr1 == '1' ) this->value.data.lng ++;
  2187. sptr1 ++;
  2188. }
  2189. break;
  2190. }
  2191. this->operation = CONST_OP;
  2192. } else {
  2193. Allocate_Ptrs( this );
  2194. if( !gParse.status ) {
  2195. rows = gParse.nRows;
  2196. switch( this->operation ) {
  2197. /* BITSTR comparisons */
  2198. case NE:
  2199. case EQ:
  2200. case GT:
  2201. case LT:
  2202. case LTE:
  2203. case GTE:
  2204. while( rows-- ) {
  2205. if( !const1 )
  2206. sptr1 = that1->value.data.strptr[rows];
  2207. if( !const2 )
  2208. sptr2 = that2->value.data.strptr[rows];
  2209. switch( this->operation ) {
  2210. case NE: this->value.data.logptr[rows] =
  2211. !bitcmp( sptr1, sptr2 );
  2212. break;
  2213. case EQ: this->value.data.logptr[rows] =
  2214. bitcmp( sptr1, sptr2 );
  2215. break;
  2216. case GT:
  2217. case LT:
  2218. case LTE:
  2219. case GTE: this->value.data.logptr[rows] =
  2220. bitlgte( sptr1, this->operation, sptr2 );
  2221. break;
  2222. }
  2223. this->value.undef[rows] = 0;
  2224. }
  2225. break;
  2226. /* BITSTR AND/ORs ... no UNDEFS in or out */
  2227. case '|':
  2228. case '&':
  2229. case '+':
  2230. while( rows-- ) {
  2231. if( !const1 )
  2232. sptr1 = that1->value.data.strptr[rows];
  2233. if( !const2 )
  2234. sptr2 = that2->value.data.strptr[rows];
  2235. if( this->operation=='|' )
  2236. bitor( this->value.data.strptr[rows], sptr1, sptr2 );
  2237. else if( this->operation=='&' )
  2238. bitand( this->value.data.strptr[rows], sptr1, sptr2 );
  2239. else {
  2240. strcpy( this->value.data.strptr[rows], sptr1 );
  2241. strcat( this->value.data.strptr[rows], sptr2 );
  2242. }
  2243. }
  2244. break;
  2245. /* Accumulate 1 bits */
  2246. case ACCUM:
  2247. {
  2248. long i, previous, curr;
  2249. previous = that2->value.data.lng;
  2250. /* Cumulative sum of this chunk */
  2251. for (i=0; i<rows; i++) {
  2252. sptr1 = that1->value.data.strptr[i];
  2253. for (curr = 0; *sptr1; sptr1 ++) {
  2254. if ( *sptr1 == '1' ) curr ++;
  2255. }
  2256. previous += curr;
  2257. this->value.data.lngptr[i] = previous;
  2258. this->value.undef[i] = 0;
  2259. }
  2260. /* Store final cumulant for next pass */
  2261. that2->value.data.lng = previous;
  2262. }
  2263. }
  2264. }
  2265. }
  2266. if( that1->operation>0 ) {
  2267. free( that1->value.data.strptr[0] );
  2268. free( that1->value.data.strptr );
  2269. }
  2270. if( that2->operation>0 ) {
  2271. free( that2->value.data.strptr[0] );
  2272. free( that2->value.data.strptr );
  2273. }
  2274. }
  2275. static void Do_BinOp_str( Node *this )
  2276. {
  2277. Node *that1, *that2;
  2278. char *sptr1, *sptr2, null1=0, null2=0;
  2279. int const1, const2, val;
  2280. long rows;
  2281. that1 = gParse.Nodes + this->SubNodes[0];
  2282. that2 = gParse.Nodes + this->SubNodes[1];
  2283. const1 = ( that1->operation==CONST_OP );
  2284. const2 = ( that2->operation==CONST_OP );
  2285. sptr1 = ( const1 ? that1->value.data.str : NULL );
  2286. sptr2 = ( const2 ? that2->value.data.str : NULL );
  2287. if( const1 && const2 ) { /* Result is a constant */
  2288. switch( this->operation ) {
  2289. /* Compare Strings */
  2290. case NE:
  2291. case EQ:
  2292. val = ( FSTRCMP( sptr1, sptr2 ) == 0 );
  2293. this->value.data.log = ( this->operation==EQ ? val : !val );
  2294. break;
  2295. case GT:
  2296. this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) > 0 );
  2297. break;
  2298. case LT:
  2299. this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) < 0 );
  2300. break;
  2301. case GTE:
  2302. this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) >= 0 );
  2303. break;
  2304. case LTE:
  2305. this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) <= 0 );
  2306. break;
  2307. /* Concat Strings */
  2308. case '+':
  2309. strcpy( this->value.data.str, sptr1 );
  2310. strcat( this->value.data.str, sptr2 );
  2311. break;
  2312. }
  2313. this->operation = CONST_OP;
  2314. } else { /* Not a constant */
  2315. Allocate_Ptrs( this );
  2316. if( !gParse.status ) {
  2317. rows = gParse.nRows;
  2318. switch( this->operation ) {
  2319. /* Compare Strings */
  2320. case NE:
  2321. case EQ:
  2322. while( rows-- ) {
  2323. if( !const1 ) null1 = that1->value.undef[rows];
  2324. if( !const2 ) null2 = that2->value.undef[rows];
  2325. this->value.undef[rows] = (null1 || null2);
  2326. if( ! this->value.undef[rows] ) {
  2327. if( !const1 ) sptr1 = that1->value.data.strptr[rows];
  2328. if( !const2 ) sptr2 = that2->value.data.strptr[rows];
  2329. val = ( FSTRCMP( sptr1, sptr2 ) == 0 );
  2330. this->value.data.logptr[rows] =
  2331. ( this->operation==EQ ? val : !val );
  2332. }
  2333. }
  2334. break;
  2335. case GT:
  2336. case LT:
  2337. while( rows-- ) {
  2338. if( !const1 ) null1 = that1->value.undef[rows];
  2339. if( !const2 ) null2 = that2->value.undef[rows];
  2340. this->value.undef[rows] = (null1 || null2);
  2341. if( ! this->value.undef[rows] ) {
  2342. if( !const1 ) sptr1 = that1->value.data.strptr[rows];
  2343. if( !const2 ) sptr2 = that2->value.data.strptr[rows];
  2344. val = ( FSTRCMP( sptr1, sptr2 ) );
  2345. this->value.data.logptr[rows] =
  2346. ( this->operation==GT ? val>0 : val<0 );
  2347. }
  2348. }
  2349. break;
  2350. case GTE:
  2351. case LTE:
  2352. while( rows-- ) {
  2353. if( !const1 ) null1 = that1->value.undef[rows];
  2354. if( !const2 ) null2 = that2->value.undef[rows];
  2355. this->value.undef[rows] = (null1 || null2);
  2356. if( ! this->value.undef[rows] ) {
  2357. if( !const1 ) sptr1 = that1->value.data.strptr[rows];
  2358. if( !const2 ) sptr2 = that2->value.data.strptr[rows];
  2359. val = ( FSTRCMP( sptr1, sptr2 ) );
  2360. this->value.data.logptr[rows] =
  2361. ( this->operation==GTE ? val>=0 : val<=0 );
  2362. }
  2363. }
  2364. break;
  2365. /* Concat Strings */
  2366. case '+':
  2367. while( rows-- ) {
  2368. if( !const1 ) null1 = that1->value.undef[rows];
  2369. if( !const2 ) null2 = that2->value.undef[rows];
  2370. this->value.undef[rows] = (null1 || null2);
  2371. if( ! this->value.undef[rows] ) {
  2372. if( !const1 ) sptr1 = that1->value.data.strptr[rows];
  2373. if( !const2 ) sptr2 = that2->value.data.strptr[rows];
  2374. strcpy( this->value.data.strptr[rows], sptr1 );
  2375. strcat( this->value.data.strptr[rows], sptr2 );
  2376. }
  2377. }
  2378. break;
  2379. }
  2380. }
  2381. }
  2382. if( that1->operation>0 ) {
  2383. free( that1->value.data.strptr[0] );
  2384. free( that1->value.data.strptr );
  2385. }
  2386. if( that2->operation>0 ) {
  2387. free( that2->value.data.strptr[0] );
  2388. free( that2->value.data.strptr );
  2389. }
  2390. }
  2391. static void Do_BinOp_log( Node *this )
  2392. {
  2393. Node *that1, *that2;
  2394. int vector1, vector2;
  2395. char val1=0, val2=0, null1=0, null2=0;
  2396. long rows, nelem, elem;
  2397. that1 = gParse.Nodes + this->SubNodes[0];
  2398. that2 = gParse.Nodes + this->SubNodes[1];
  2399. vector1 = ( that1->operation!=CONST_OP );
  2400. if( vector1 )
  2401. vector1 = that1->value.nelem;
  2402. else {
  2403. val1 = that1->value.data.log;
  2404. }
  2405. vector2 = ( that2->operation!=CONST_OP );
  2406. if( vector2 )
  2407. vector2 = that2->value.nelem;
  2408. else {
  2409. val2 = that2->value.data.log;
  2410. }
  2411. if( !vector1 && !vector2 ) { /* Result is a constant */
  2412. switch( this->operation ) {
  2413. case OR:
  2414. this->value.data.log = (val1 || val2);
  2415. break;
  2416. case AND:
  2417. this->value.data.log = (val1 && val2);
  2418. break;
  2419. case EQ:
  2420. this->value.data.log = ( (val1 && val2) || (!val1 && !val2) );
  2421. break;
  2422. case NE:
  2423. this->value.data.log = ( (val1 && !val2) || (!val1 && val2) );
  2424. break;
  2425. case ACCUM:
  2426. this->value.data.lng = val1;
  2427. break;
  2428. }
  2429. this->operation=CONST_OP;
  2430. } else if (this->operation == ACCUM) {
  2431. long i, previous, curr;
  2432. rows = gParse.nRows;
  2433. nelem = this->value.nelem;
  2434. elem = this->value.nelem * rows;
  2435. Allocate_Ptrs( this );
  2436. if( !gParse.status ) {
  2437. previous = that2->value.data.lng;
  2438. /* Cumulative sum of this chunk */
  2439. for (i=0; i<elem; i++) {
  2440. if (!that1->value.undef[i]) {
  2441. curr = that1->value.data.logptr[i];
  2442. previous += curr;
  2443. }
  2444. this->value.data.lngptr[i] = previous;
  2445. this->value.undef[i] = 0;
  2446. }
  2447. /* Store final cumulant for next pass */
  2448. that2->value.data.lng = previous;
  2449. }
  2450. } else {
  2451. rows = gParse.nRows;
  2452. nelem = this->value.nelem;
  2453. elem = this->value.nelem * rows;
  2454. Allocate_Ptrs( this );
  2455. if( !gParse.status ) {
  2456. if (this->operation == ACCUM) {
  2457. long i, previous, curr;
  2458. previous = that2->value.data.lng;
  2459. /* Cumulative sum of this chunk */
  2460. for (i=0; i<elem; i++) {
  2461. if (!that1->value.undef[i]) {
  2462. curr = that1->value.data.logptr[i];
  2463. previous += curr;
  2464. }
  2465. this->value.data.lngptr[i] = previous;
  2466. this->value.undef[i] = 0;
  2467. }
  2468. /* Store final cumulant for next pass */
  2469. that2->value.data.lng = previous;
  2470. }
  2471. while( rows-- ) {
  2472. while( nelem-- ) {
  2473. elem--;
  2474. if( vector1>1 ) {
  2475. val1 = that1->value.data.logptr[elem];
  2476. null1 = that1->value.undef[elem];
  2477. } else if( vector1 ) {
  2478. val1 = that1->value.data.logptr[rows];
  2479. null1 = that1->value.undef[rows];
  2480. }
  2481. if( vector2>1 ) {
  2482. val2 = that2->value.data.logptr[elem];
  2483. null2 = that2->value.undef[elem];
  2484. } else if( vector2 ) {
  2485. val2 = that2->value.data.logptr[rows];
  2486. null2 = that2->value.undef[rows];
  2487. }
  2488. this->value.undef[elem] = (null1 || null2);
  2489. switch( this->operation ) {
  2490. case OR:
  2491. /* This is more complicated than others to suppress UNDEFs */
  2492. /* in those cases where the other argument is DEF && TRUE */
  2493. if( !null1 && !null2 ) {
  2494. this->value.data.logptr[elem] = (val1 || val2);
  2495. } else if( (null1 && !null2 && val2)
  2496. || ( !null1 && null2 && val1 ) ) {
  2497. this->value.data.logptr[elem] = 1;
  2498. this->value.undef[elem] = 0;
  2499. }
  2500. break;
  2501. case AND:
  2502. /* This is more complicated than others to suppress UNDEFs */
  2503. /* in those cases where the other argument is DEF && FALSE */
  2504. if( !null1 && !null2 ) {
  2505. this->value.data.logptr[elem] = (val1 && val2);
  2506. } else if( (null1 && !null2 && !val2)
  2507. || ( !null1 && null2 && !val1 ) ) {
  2508. this->value.data.logptr[elem] = 0;
  2509. this->value.undef[elem] = 0;
  2510. }
  2511. break;
  2512. case EQ:
  2513. this->value.data.logptr[elem] =
  2514. ( (val1 && val2) || (!val1 && !val2) );
  2515. break;
  2516. case NE:
  2517. this->value.data.logptr[elem] =
  2518. ( (val1 && !val2) || (!val1 && val2) );
  2519. break;
  2520. }
  2521. }
  2522. nelem = this->value.nelem;
  2523. }
  2524. }
  2525. }
  2526. if( that1->operation>0 ) {
  2527. free( that1->value.data.ptr );
  2528. }
  2529. if( that2->operation>0 ) {
  2530. free( that2->value.data.ptr );
  2531. }
  2532. }
  2533. static void Do_BinOp_lng( Node *this )
  2534. {
  2535. Node *that1, *that2;
  2536. int vector1, vector2;
  2537. long val1=0, val2=0;
  2538. char null1=0, null2=0;
  2539. long rows, nelem, elem;
  2540. that1 = gParse.Nodes + this->SubNodes[0];
  2541. that2 = gParse.Nodes + this->SubNodes[1];
  2542. vector1 = ( that1->operation!=CONST_OP );
  2543. if( vector1 )
  2544. vector1 = that1->value.nelem;
  2545. else {
  2546. val1 = that1->value.data.lng;
  2547. }
  2548. vector2 = ( that2->operation!=CONST_OP );
  2549. if( vector2 )
  2550. vector2 = that2->value.nelem;
  2551. else {
  2552. val2 = that2->value.data.lng;
  2553. }
  2554. if( !vector1 && !vector2 ) { /* Result is a constant */
  2555. switch( this->operation ) {
  2556. case '~': /* Treat as == for LONGS */
  2557. case EQ: this->value.data.log = (val1 == val2); break;
  2558. case NE: this->value.data.log = (val1 != val2); break;
  2559. case GT: this->value.data.log = (val1 > val2); break;
  2560. case LT: this->value.data.log = (val1 < val2); break;
  2561. case LTE: this->value.data.log = (val1 <= val2); break;
  2562. case GTE: this->value.data.log = (val1 >= val2); break;
  2563. case '+': this->value.data.lng = (val1 + val2); break;
  2564. case '-': this->value.data.lng = (val1 - val2); break;
  2565. case '*': this->value.data.lng = (val1 * val2); break;
  2566. case '%':
  2567. if( val2 ) this->value.data.lng = (val1 % val2);
  2568. else yyerror("Divide by Zero");
  2569. break;
  2570. case '/':
  2571. if( val2 ) this->value.data.lng = (val1 / val2);
  2572. else yyerror("Divide by Zero");
  2573. break;
  2574. case POWER:
  2575. this->value.data.lng = (long)pow((double)val1,(double)val2);
  2576. break;
  2577. case ACCUM:
  2578. this->value.data.lng = val1;
  2579. break;
  2580. case DIFF:
  2581. this->value.data.lng = 0;
  2582. break;
  2583. }
  2584. this->operation=CONST_OP;
  2585. } else if ((this->operation == ACCUM) || (this->operation == DIFF)) {
  2586. long i, previous, curr;
  2587. long undef;
  2588. rows = gParse.nRows;
  2589. nelem = this->value.nelem;
  2590. elem = this->value.nelem * rows;
  2591. Allocate_Ptrs( this );
  2592. if( !gParse.status ) {
  2593. previous = that2->value.data.lng;
  2594. undef = (long) that2->value.undef;
  2595. if (this->operation == ACCUM) {
  2596. /* Cumulative sum of this chunk */
  2597. for (i=0; i<elem; i++) {
  2598. if (!that1->value.undef[i]) {
  2599. curr = that1->value.data.lngptr[i];
  2600. previous += curr;
  2601. }
  2602. this->value.data.lngptr[i] = previous;
  2603. this->value.undef[i] = 0;
  2604. }
  2605. } else {
  2606. /* Sequential difference for this chunk */
  2607. for (i=0; i<elem; i++) {
  2608. curr = that1->value.data.lngptr[i];
  2609. if (that1->value.undef[i] || undef) {
  2610. /* Either this, or previous, value was undefined */
  2611. this->value.data.lngptr[i] = 0;
  2612. this->value.undef[i] = 1;
  2613. } else {
  2614. /* Both defined, we are okay! */
  2615. this->value.data.lngptr[i] = curr - previous;
  2616. this->value.undef[i] = 0;
  2617. }
  2618. previous = curr;
  2619. undef = that1->value.undef[i];
  2620. }
  2621. }
  2622. /* Store final cumulant for next pass */
  2623. that2->value.data.lng = previous;
  2624. that2->value.undef = (char *) undef; /* XXX evil, but no harm here */
  2625. }
  2626. } else {
  2627. rows = gParse.nRows;
  2628. nelem = this->value.nelem;
  2629. elem = this->value.nelem * rows;
  2630. Allocate_Ptrs( this );
  2631. while( rows-- && !gParse.status ) {
  2632. while( nelem-- && !gParse.status ) {
  2633. elem--;
  2634. if( vector1>1 ) {
  2635. val1 = that1->value.data.lngptr[elem];
  2636. null1 = that1->value.undef[elem];
  2637. } else if( vector1 ) {
  2638. val1 = that1->value.data.lngptr[rows];
  2639. null1 = that1->value.undef[rows];
  2640. }
  2641. if( vector2>1 ) {
  2642. val2 = that2->value.data.lngptr[elem];
  2643. null2 = that2->value.undef[elem];
  2644. } else if( vector2 ) {
  2645. val2 = that2->value.data.lngptr[rows];
  2646. null2 = that2->value.undef[rows];
  2647. }
  2648. this->value.undef[elem] = (null1 || null2);
  2649. switch( this->operation ) {
  2650. case '~': /* Treat as == for LONGS */
  2651. case EQ: this->value.data.logptr[elem] = (val1 == val2); break;
  2652. case NE: this->value.data.logptr[elem] = (val1 != val2); break;
  2653. case GT: this->value.data.logptr[elem] = (val1 > val2); break;
  2654. case LT: this->value.data.logptr[elem] = (val1 < val2); break;
  2655. case LTE: this->value.data.logptr[elem] = (val1 <= val2); break;
  2656. case GTE: this->value.data.logptr[elem] = (val1 >= val2); break;
  2657. case '+': this->value.data.lngptr[elem] = (val1 + val2); break;
  2658. case '-': this->value.data.lngptr[elem] = (val1 - val2); break;
  2659. case '*': this->value.data.lngptr[elem] = (val1 * val2); break;
  2660. case '%':
  2661. if( val2 ) this->value.data.lngptr[elem] = (val1 % val2);
  2662. else {
  2663. this->value.data.lngptr[elem] = 0;
  2664. this->value.undef[elem] = 1;
  2665. }
  2666. break;
  2667. case '/':
  2668. if( val2 ) this->value.data.lngptr[elem] = (val1 / val2);
  2669. else {
  2670. this->value.data.lngptr[elem] = 0;
  2671. this->value.undef[elem] = 1;
  2672. }
  2673. break;
  2674. case POWER:
  2675. this->value.data.lngptr[elem] = (long)pow((double)val1,(double)val2);
  2676. break;
  2677. }
  2678. }
  2679. nelem = this->value.nelem;
  2680. }
  2681. }
  2682. if( that1->operation>0 ) {
  2683. free( that1->value.data.ptr );
  2684. }
  2685. if( that2->operation>0 ) {
  2686. free( that2->value.data.ptr );
  2687. }
  2688. }
  2689. static void Do_BinOp_dbl( Node *this )
  2690. {
  2691. Node *that1, *that2;
  2692. int vector1, vector2;
  2693. double val1=0.0, val2=0.0;
  2694. char null1=0, null2=0;
  2695. long rows, nelem, elem;
  2696. that1 = gParse.Nodes + this->SubNodes[0];
  2697. that2 = gParse.Nodes + this->SubNodes[1];
  2698. vector1 = ( that1->operation!=CONST_OP );
  2699. if( vector1 )
  2700. vector1 = that1->value.nelem;
  2701. else {
  2702. val1 = that1->value.data.dbl;
  2703. }
  2704. vector2 = ( that2->operation!=CONST_OP );
  2705. if( vector2 )
  2706. vector2 = that2->value.nelem;
  2707. else {
  2708. val2 = that2->value.data.dbl;
  2709. }
  2710. if( !vector1 && !vector2 ) { /* Result is a constant */
  2711. switch( this->operation ) {
  2712. case '~': this->value.data.log = ( fabs(val1-val2) < APPROX ); break;
  2713. case EQ: this->value.data.log = (val1 == val2); break;
  2714. case NE: this->value.data.log = (val1 != val2); break;
  2715. case GT: this->value.data.log = (val1 > val2); break;
  2716. case LT: this->value.data.log = (val1 < val2); break;
  2717. case LTE: this->value.data.log = (val1 <= val2); break;
  2718. case GTE: this->value.data.log = (val1 >= val2); break;
  2719. case '+': this->value.data.dbl = (val1 + val2); break;
  2720. case '-': this->value.data.dbl = (val1 - val2); break;
  2721. case '*': this->value.data.dbl = (val1 * val2); break;
  2722. case '%':
  2723. if( val2 ) this->value.data.dbl = val1 - val2*((int)(val1/val2));
  2724. else yyerror("Divide by Zero");
  2725. break;
  2726. case '/':
  2727. if( val2 ) this->value.data.dbl = (val1 / val2);
  2728. else yyerror("Divide by Zero");
  2729. break;
  2730. case POWER:
  2731. this->value.data.dbl = (double)pow(val1,val2);
  2732. break;
  2733. case ACCUM:
  2734. this->value.data.dbl = val1;
  2735. break;
  2736. case DIFF:
  2737. this->value.data.dbl = 0;
  2738. break;
  2739. }
  2740. this->operation=CONST_OP;
  2741. } else if ((this->operation == ACCUM) || (this->operation == DIFF)) {
  2742. long i;
  2743. long undef;
  2744. double previous, curr;
  2745. rows = gParse.nRows;
  2746. nelem = this->value.nelem;
  2747. elem = this->value.nelem * rows;
  2748. Allocate_Ptrs( this );
  2749. if( !gParse.status ) {
  2750. previous = that2->value.data.dbl;
  2751. undef = (long) that2->value.undef;
  2752. if (this->operation == ACCUM) {
  2753. /* Cumulative sum of this chunk */
  2754. for (i=0; i<elem; i++) {
  2755. if (!that1->value.undef[i]) {
  2756. curr = that1->value.data.dblptr[i];
  2757. previous += curr;
  2758. }
  2759. this->value.data.dblptr[i] = previous;
  2760. this->value.undef[i] = 0;
  2761. }
  2762. } else {
  2763. /* Sequential difference for this chunk */
  2764. for (i=0; i<elem; i++) {
  2765. curr = that1->value.data.dblptr[i];
  2766. if (that1->value.undef[i] || undef) {
  2767. /* Either this, or previous, value was undefined */
  2768. this->value.data.dblptr[i] = 0;
  2769. this->value.undef[i] = 1;
  2770. } else {
  2771. /* Both defined, we are okay! */
  2772. this->value.data.dblptr[i] = curr - previous;
  2773. this->value.undef[i] = 0;
  2774. }
  2775. previous = curr;
  2776. undef = that1->value.undef[i];
  2777. }
  2778. }
  2779. /* Store final cumulant for next pass */
  2780. that2->value.data.dbl = previous;
  2781. that2->value.undef = (char *) undef; /* XXX evil, but no harm here */
  2782. }
  2783. } else {
  2784. rows = gParse.nRows;
  2785. nelem = this->value.nelem;
  2786. elem = this->value.nelem * rows;
  2787. Allocate_Ptrs( this );
  2788. while( rows-- && !gParse.status ) {
  2789. while( nelem-- && !gParse.status ) {
  2790. elem--;
  2791. if( vector1>1 ) {
  2792. val1 = that1->value.data.dblptr[elem];
  2793. null1 = that1->value.undef[elem];
  2794. } else if( vector1 ) {
  2795. val1 = that1->value.data.dblptr[rows];
  2796. null1 = that1->value.undef[rows];
  2797. }
  2798. if( vector2>1 ) {
  2799. val2 = that2->value.data.dblptr[elem];
  2800. null2 = that2->value.undef[elem];
  2801. } else if( vector2 ) {
  2802. val2 = that2->value.data.dblptr[rows];
  2803. null2 = that2->value.undef[rows];
  2804. }
  2805. this->value.undef[elem] = (null1 || null2);
  2806. switch( this->operation ) {
  2807. case '~': this->value.data.logptr[elem] =
  2808. ( fabs(val1-val2) < APPROX ); break;
  2809. case EQ: this->value.data.logptr[elem] = (val1 == val2); break;
  2810. case NE: this->value.data.logptr[elem] = (val1 != val2); break;
  2811. case GT: this->value.data.logptr[elem] = (val1 > val2); break;
  2812. case LT: this->value.data.logptr[elem] = (val1 < val2); break;
  2813. case LTE: this->value.data.logptr[elem] = (val1 <= val2); break;
  2814. case GTE: this->value.data.logptr[elem] = (val1 >= val2); break;
  2815. case '+': this->value.data.dblptr[elem] = (val1 + val2); break;
  2816. case '-': this->value.data.dblptr[elem] = (val1 - val2); break;
  2817. case '*': this->value.data.dblptr[elem] = (val1 * val2); break;
  2818. case '%':
  2819. if( val2 ) this->value.data.dblptr[elem] =
  2820. val1 - val2*((int)(val1/val2));
  2821. else {
  2822. this->value.data.dblptr[elem] = 0.0;
  2823. this->value.undef[elem] = 1;
  2824. }
  2825. break;
  2826. case '/':
  2827. if( val2 ) this->value.data.dblptr[elem] = (val1 / val2);
  2828. else {
  2829. this->value.data.dblptr[elem] = 0.0;
  2830. this->value.undef[elem] = 1;
  2831. }
  2832. break;
  2833. case POWER:
  2834. this->value.data.dblptr[elem] = (double)pow(val1,val2);
  2835. break;
  2836. }
  2837. }
  2838. nelem = this->value.nelem;
  2839. }
  2840. }
  2841. if( that1->operation>0 ) {
  2842. free( that1->value.data.ptr );
  2843. }
  2844. if( that2->operation>0 ) {
  2845. free( that2->value.data.ptr );
  2846. }
  2847. }
  2848. /*
  2849. * This Quickselect routine is based on the algorithm described in
  2850. * "Numerical recipes in C", Second Edition,
  2851. * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
  2852. * This code by Nicolas Devillard - 1998. Public domain.
  2853. * http://ndevilla.free.fr/median/median/src/quickselect.c
  2854. */
  2855. #define ELEM_SWAP(a,b) { register long t=(a);(a)=(b);(b)=t; }
  2856. /*
  2857. * qselect_median_lng - select the median value of a long array
  2858. *
  2859. * This routine selects the median value of the long integer array
  2860. * arr[]. If there are an even number of elements, the "lower median"
  2861. * is selected.
  2862. *
  2863. * The array arr[] is scrambled, so users must operate on a scratch
  2864. * array if they wish the values to be preserved.
  2865. *
  2866. * long arr[] - array of values
  2867. * int n - number of elements in arr
  2868. *
  2869. * RETURNS: the lower median value of arr[]
  2870. *
  2871. */
  2872. long qselect_median_lng(long arr[], int n)
  2873. {
  2874. int low, high ;
  2875. int median;
  2876. int middle, ll, hh;
  2877. low = 0 ; high = n-1 ; median = (low + high) / 2;
  2878. for (;;) {
  2879. if (high <= low) { /* One element only */
  2880. return arr[median];
  2881. }
  2882. if (high == low + 1) { /* Two elements only */
  2883. if (arr[low] > arr[high])
  2884. ELEM_SWAP(arr[low], arr[high]) ;
  2885. return arr[median];
  2886. }
  2887. /* Find median of low, middle and high items; swap into position low */
  2888. middle = (low + high) / 2;
  2889. if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ;
  2890. if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ;
  2891. if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ;
  2892. /* Swap low item (now in position middle) into position (low+1) */
  2893. ELEM_SWAP(arr[middle], arr[low+1]) ;
  2894. /* Nibble from each end towards middle, swapping items when stuck */
  2895. ll = low + 1;
  2896. hh = high;
  2897. for (;;) {
  2898. do ll++; while (arr[low] > arr[ll]) ;
  2899. do hh--; while (arr[hh] > arr[low]) ;
  2900. if (hh < ll)
  2901. break;
  2902. ELEM_SWAP(arr[ll], arr[hh]) ;
  2903. }
  2904. /* Swap middle item (in position low) back into correct position */
  2905. ELEM_SWAP(arr[low], arr[hh]) ;
  2906. /* Re-set active partition */
  2907. if (hh <= median)
  2908. low = ll;
  2909. if (hh >= median)
  2910. high = hh - 1;
  2911. }
  2912. }
  2913. #undef ELEM_SWAP
  2914. #define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
  2915. /*
  2916. * qselect_median_dbl - select the median value of a double array
  2917. *
  2918. * This routine selects the median value of the double array
  2919. * arr[]. If there are an even number of elements, the "lower median"
  2920. * is selected.
  2921. *
  2922. * The array arr[] is scrambled, so users must operate on a scratch
  2923. * array if they wish the values to be preserved.
  2924. *
  2925. * double arr[] - array of values
  2926. * int n - number of elements in arr
  2927. *
  2928. * RETURNS: the lower median value of arr[]
  2929. *
  2930. */
  2931. double qselect_median_dbl(double arr[], int n)
  2932. {
  2933. int low, high ;
  2934. int median;
  2935. int middle, ll, hh;
  2936. low = 0 ; high = n-1 ; median = (low + high) / 2;
  2937. for (;;) {
  2938. if (high <= low) { /* One element only */
  2939. return arr[median] ;
  2940. }
  2941. if (high == low + 1) { /* Two elements only */
  2942. if (arr[low] > arr[high])
  2943. ELEM_SWAP(arr[low], arr[high]) ;
  2944. return arr[median] ;
  2945. }
  2946. /* Find median of low, middle and high items; swap into position low */
  2947. middle = (low + high) / 2;
  2948. if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ;
  2949. if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ;
  2950. if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ;
  2951. /* Swap low item (now in position middle) into position (low+1) */
  2952. ELEM_SWAP(arr[middle], arr[low+1]) ;
  2953. /* Nibble from each end towards middle, swapping items when stuck */
  2954. ll = low + 1;
  2955. hh = high;
  2956. for (;;) {
  2957. do ll++; while (arr[low] > arr[ll]) ;
  2958. do hh--; while (arr[hh] > arr[low]) ;
  2959. if (hh < ll)
  2960. break;
  2961. ELEM_SWAP(arr[ll], arr[hh]) ;
  2962. }
  2963. /* Swap middle item (in position low) back into correct position */
  2964. ELEM_SWAP(arr[low], arr[hh]) ;
  2965. /* Re-set active partition */
  2966. if (hh <= median)
  2967. low = ll;
  2968. if (hh >= median)
  2969. high = hh - 1;
  2970. }
  2971. }
  2972. #undef ELEM_SWAP
  2973. /*
  2974. * angsep_calc - compute angular separation between celestial coordinates
  2975. *
  2976. * This routine computes the angular separation between to coordinates
  2977. * on the celestial sphere (i.e. RA and Dec). Note that all units are
  2978. * in DEGREES, unlike the other trig functions in the calculator.
  2979. *
  2980. * double ra1, dec1 - RA and Dec of the first position in degrees
  2981. * double ra2, dec2 - RA and Dec of the second position in degrees
  2982. *
  2983. * RETURNS: (double) angular separation in degrees
  2984. *
  2985. */
  2986. double angsep_calc(double ra1, double dec1, double ra2, double dec2)
  2987. {
  2988. double cd;
  2989. static double deg = 0;
  2990. double a, sdec, sra;
  2991. if (deg == 0) deg = ((double)4)*atan((double)1)/((double)180);
  2992. /* deg = 1.0; **** UNCOMMENT IF YOU WANT RADIANS */
  2993. /*
  2994. This (commented out) algorithm uses the Low of Cosines, which becomes
  2995. unstable for angles less than 0.1 arcsec.
  2996. cd = sin(dec1*deg)*sin(dec2*deg)
  2997. + cos(dec1*deg)*cos(dec2*deg)*cos((ra1-ra2)*deg);
  2998. if (cd < (-1)) cd = -1;
  2999. if (cd > (+1)) cd = +1;
  3000. return acos(cd)/deg;
  3001. */
  3002. /* The algorithm is the law of Haversines. This algorithm is
  3003. stable even when the points are close together. The normal
  3004. Law of Cosines fails for angles around 0.1 arcsec. */
  3005. sra = sin( (ra2 - ra1)*deg / 2 );
  3006. sdec = sin( (dec2 - dec1)*deg / 2);
  3007. a = sdec*sdec + cos(dec1*deg)*cos(dec2*deg)*sra*sra;
  3008. /* Sanity checking to avoid a range error in the sqrt()'s below */
  3009. if (a < 0) { a = 0; }
  3010. if (a > 1) { a = 1; }
  3011. return 2.0*atan2(sqrt(a), sqrt(1.0 - a)) / deg;
  3012. }
  3013. static double ran1()
  3014. {
  3015. static double dval = 0.0;
  3016. double rndVal;
  3017. if (dval == 0.0) {
  3018. if( rand()<32768 && rand()<32768 )
  3019. dval = 32768.0;
  3020. else
  3021. dval = 2147483648.0;
  3022. }
  3023. rndVal = (double)rand();
  3024. while( rndVal > dval ) dval *= 2.0;
  3025. return rndVal/dval;
  3026. }
  3027. /* Gaussian deviate routine from Numerical Recipes */
  3028. static double gasdev()
  3029. {
  3030. static int iset = 0;
  3031. static double gset;
  3032. double fac, rsq, v1, v2;
  3033. if (iset == 0) {
  3034. do {
  3035. v1 = 2.0*ran1()-1.0;
  3036. v2 = 2.0*ran1()-1.0;
  3037. rsq = v1*v1 + v2*v2;
  3038. } while (rsq >= 1.0 || rsq == 0.0);
  3039. fac = sqrt(-2.0*log(rsq)/rsq);
  3040. gset = v1*fac;
  3041. iset = 1;
  3042. return v2*fac;
  3043. } else {
  3044. iset = 0;
  3045. return gset;
  3046. }
  3047. }
  3048. /* lgamma function - from Numerical Recipes */
  3049. float gammaln(float xx)
  3050. /* Returns the value ln Gamma[(xx)] for xx > 0. */
  3051. {
  3052. /*
  3053. Internal arithmetic will be done in double precision, a nicety
  3054. that you can omit if five-figure accuracy is good enough. */
  3055. double x,y,tmp,ser;
  3056. static double cof[6]={76.18009172947146,-86.50532032941677,
  3057. 24.01409824083091,-1.231739572450155,
  3058. 0.1208650973866179e-2,-0.5395239384953e-5};
  3059. int j;
  3060. y=x=xx;
  3061. tmp=x+5.5;
  3062. tmp -= (x+0.5)*log(tmp);
  3063. ser=1.000000000190015;
  3064. for (j=0;j<=5;j++) ser += cof[j]/++y;
  3065. return (float) -tmp+log(2.5066282746310005*ser/x);
  3066. }
  3067. /* Poisson deviate - derived from Numerical Recipes */
  3068. static long poidev(double xm)
  3069. {
  3070. static double sq, alxm, g, oldm = -1.0;
  3071. static double pi = 0;
  3072. double em, t, y;
  3073. if (pi == 0) pi = ((double)4)*atan((double)1);
  3074. if (xm < 20.0) {
  3075. if (xm != oldm) {
  3076. oldm = xm;
  3077. g = exp(-xm);
  3078. }
  3079. em = -1;
  3080. t = 1.0;
  3081. do {
  3082. em += 1;
  3083. t *= ran1();
  3084. } while (t > g);
  3085. } else {
  3086. if (xm != oldm) {
  3087. oldm = xm;
  3088. sq = sqrt(2.0*xm);
  3089. alxm = log(xm);
  3090. g = xm*alxm-gammaln( (float) (xm+1.0));
  3091. }
  3092. do {
  3093. do {
  3094. y = tan(pi*ran1());
  3095. em = sq*y+xm;
  3096. } while (em < 0.0);
  3097. em = floor(em);
  3098. t = 0.9*(1.0+y*y)*exp(em*alxm-gammaln( (float) (em+1.0) )-g);
  3099. } while (ran1() > t);
  3100. }
  3101. /* Return integer version */
  3102. return (long int) floor(em+0.5);
  3103. }
  3104. static void Do_Func( Node *this )
  3105. {
  3106. Node *theParams[MAXSUBS];
  3107. int vector[MAXSUBS], allConst;
  3108. lval pVals[MAXSUBS];
  3109. char pNull[MAXSUBS];
  3110. long ival;
  3111. double dval;
  3112. int i, valInit;
  3113. long row, elem, nelem;
  3114. i = this->nSubNodes;
  3115. allConst = 1;
  3116. while( i-- ) {
  3117. theParams[i] = gParse.Nodes + this->SubNodes[i];
  3118. vector[i] = ( theParams[i]->operation!=CONST_OP );
  3119. if( vector[i] ) {
  3120. allConst = 0;
  3121. vector[i] = theParams[i]->value.nelem;
  3122. } else {
  3123. if( theParams[i]->type==DOUBLE ) {
  3124. pVals[i].data.dbl = theParams[i]->value.data.dbl;
  3125. } else if( theParams[i]->type==LONG ) {
  3126. pVals[i].data.lng = theParams[i]->value.data.lng;
  3127. } else if( theParams[i]->type==BOOLEAN ) {
  3128. pVals[i].data.log = theParams[i]->value.data.log;
  3129. } else
  3130. strcpy(pVals[i].data.str, theParams[i]->value.data.str);
  3131. pNull[i] = 0;
  3132. }
  3133. }
  3134. if( this->nSubNodes==0 ) allConst = 0; /* These do produce scalars */
  3135. /* Random numbers are *never* constant !! */
  3136. if( this->operation == poirnd_fct ) allConst = 0;
  3137. if( this->operation == gasrnd_fct ) allConst = 0;
  3138. if( this->operation == rnd_fct ) allConst = 0;
  3139. if( allConst ) {
  3140. switch( this->operation ) {
  3141. /* Non-Trig single-argument functions */
  3142. case sum_fct:
  3143. if( theParams[0]->type==BOOLEAN )
  3144. this->value.data.lng = ( pVals[0].data.log ? 1 : 0 );
  3145. else if( theParams[0]->type==LONG )
  3146. this->value.data.lng = pVals[0].data.lng;
  3147. else if( theParams[0]->type==DOUBLE )
  3148. this->value.data.dbl = pVals[0].data.dbl;
  3149. else if( theParams[0]->type==BITSTR )
  3150. strcpy(this->value.data.str, pVals[0].data.str);
  3151. break;
  3152. case average_fct:
  3153. if( theParams[0]->type==LONG )
  3154. this->value.data.dbl = pVals[0].data.lng;
  3155. else if( theParams[0]->type==DOUBLE )
  3156. this->value.data.dbl = pVals[0].data.dbl;
  3157. break;
  3158. case stddev_fct:
  3159. this->value.data.dbl = 0; /* Standard deviation of a constant = 0 */
  3160. break;
  3161. case median_fct:
  3162. if( theParams[0]->type==BOOLEAN )
  3163. this->value.data.lng = ( pVals[0].data.log ? 1 : 0 );
  3164. else if( theParams[0]->type==LONG )
  3165. this->value.data.lng = pVals[0].data.lng;
  3166. else
  3167. this->value.data.dbl = pVals[0].data.dbl;
  3168. break;
  3169. case poirnd_fct:
  3170. if( theParams[0]->type==DOUBLE )
  3171. this->value.data.lng = poidev(pVals[0].data.dbl);
  3172. else
  3173. this->value.data.lng = poidev(pVals[0].data.lng);
  3174. break;
  3175. case abs_fct:
  3176. if( theParams[0]->type==DOUBLE ) {
  3177. dval = pVals[0].data.dbl;
  3178. this->value.data.dbl = (dval>0.0 ? dval : -dval);
  3179. } else {
  3180. ival = pVals[0].data.lng;
  3181. this->value.data.lng = (ival> 0 ? ival : -ival);
  3182. }
  3183. break;
  3184. /* Special Null-Handling Functions */
  3185. case nonnull_fct:
  3186. this->value.data.lng = 1; /* Constants are always 1-element and defined */
  3187. break;
  3188. case isnull_fct: /* Constants are always defined */
  3189. this->value.data.log = 0;
  3190. break;
  3191. case defnull_fct:
  3192. if( this->type==BOOLEAN )
  3193. this->value.data.log = pVals[0].data.log;
  3194. else if( this->type==LONG )
  3195. this->value.data.lng = pVals[0].data.lng;
  3196. else if( this->type==DOUBLE )
  3197. this->value.data.dbl = pVals[0].data.dbl;
  3198. else if( this->type==STRING )
  3199. strcpy(this->value.data.str,pVals[0].data.str);
  3200. break;
  3201. /* Math functions with 1 double argument */
  3202. case sin_fct:
  3203. this->value.data.dbl = sin( pVals[0].data.dbl );
  3204. break;
  3205. case cos_fct:
  3206. this->value.data.dbl = cos( pVals[0].data.dbl );
  3207. break;
  3208. case tan_fct:
  3209. this->value.data.dbl = tan( pVals[0].data.dbl );
  3210. break;
  3211. case asin_fct:
  3212. dval = pVals[0].data.dbl;
  3213. if( dval<-1.0 || dval>1.0 )
  3214. yyerror("Out of range argument to arcsin");
  3215. else
  3216. this->value.data.dbl = asin( dval );
  3217. break;
  3218. case acos_fct:
  3219. dval = pVals[0].data.dbl;
  3220. if( dval<-1.0 || dval>1.0 )
  3221. yyerror("Out of range argument to arccos");
  3222. else
  3223. this->value.data.dbl = acos( dval );
  3224. break;
  3225. case atan_fct:
  3226. this->value.data.dbl = atan( pVals[0].data.dbl );
  3227. break;
  3228. case sinh_fct:
  3229. this->value.data.dbl = sinh( pVals[0].data.dbl );
  3230. break;
  3231. case cosh_fct:
  3232. this->value.data.dbl = cosh( pVals[0].data.dbl );
  3233. break;
  3234. case tanh_fct:
  3235. this->value.data.dbl = tanh( pVals[0].data.dbl );
  3236. break;
  3237. case exp_fct:
  3238. this->value.data.dbl = exp( pVals[0].data.dbl );
  3239. break;
  3240. case log_fct:
  3241. dval = pVals[0].data.dbl;
  3242. if( dval<=0.0 )
  3243. yyerror("Out of range argument to log");
  3244. else
  3245. this->value.data.dbl = log( dval );
  3246. break;
  3247. case log10_fct:
  3248. dval = pVals[0].data.dbl;
  3249. if( dval<=0.0 )
  3250. yyerror("Out of range argument to log10");
  3251. else
  3252. this->value.data.dbl = log10( dval );
  3253. break;
  3254. case sqrt_fct:
  3255. dval = pVals[0].data.dbl;
  3256. if( dval<0.0 )
  3257. yyerror("Out of range argument to sqrt");
  3258. else
  3259. this->value.data.dbl = sqrt( dval );
  3260. break;
  3261. case ceil_fct:
  3262. this->value.data.dbl = ceil( pVals[0].data.dbl );
  3263. break;
  3264. case floor_fct:
  3265. this->value.data.dbl = floor( pVals[0].data.dbl );
  3266. break;
  3267. case round_fct:
  3268. this->value.data.dbl = floor( pVals[0].data.dbl + 0.5 );
  3269. break;
  3270. /* Two-argument Trig Functions */
  3271. case atan2_fct:
  3272. this->value.data.dbl =
  3273. atan2( pVals[0].data.dbl, pVals[1].data.dbl );
  3274. break;
  3275. /* Four-argument ANGSEP function */
  3276. case angsep_fct:
  3277. this->value.data.dbl =
  3278. angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl,
  3279. pVals[2].data.dbl, pVals[3].data.dbl);
  3280. /* Min/Max functions taking 1 or 2 arguments */
  3281. case min1_fct:
  3282. /* No constant vectors! */
  3283. if( this->type == DOUBLE )
  3284. this->value.data.dbl = pVals[0].data.dbl;
  3285. else if( this->type == LONG )
  3286. this->value.data.lng = pVals[0].data.lng;
  3287. else if( this->type == BITSTR )
  3288. strcpy(this->value.data.str, pVals[0].data.str);
  3289. break;
  3290. case min2_fct:
  3291. if( this->type == DOUBLE )
  3292. this->value.data.dbl =
  3293. minvalue( pVals[0].data.dbl, pVals[1].data.dbl );
  3294. else if( this->type == LONG )
  3295. this->value.data.lng =
  3296. minvalue( pVals[0].data.lng, pVals[1].data.lng );
  3297. break;
  3298. case max1_fct:
  3299. /* No constant vectors! */
  3300. if( this->type == DOUBLE )
  3301. this->value.data.dbl = pVals[0].data.dbl;
  3302. else if( this->type == LONG )
  3303. this->value.data.lng = pVals[0].data.lng;
  3304. else if( this->type == BITSTR )
  3305. strcpy(this->value.data.str, pVals[0].data.str);
  3306. break;
  3307. case max2_fct:
  3308. if( this->type == DOUBLE )
  3309. this->value.data.dbl =
  3310. maxvalue( pVals[0].data.dbl, pVals[1].data.dbl );
  3311. else if( this->type == LONG )
  3312. this->value.data.lng =
  3313. maxvalue( pVals[0].data.lng, pVals[1].data.lng );
  3314. break;
  3315. /* Boolean SAO region Functions... scalar or vector dbls */
  3316. case near_fct:
  3317. this->value.data.log = bnear( pVals[0].data.dbl, pVals[1].data.dbl,
  3318. pVals[2].data.dbl );
  3319. break;
  3320. case circle_fct:
  3321. this->value.data.log = circle( pVals[0].data.dbl, pVals[1].data.dbl,
  3322. pVals[2].data.dbl, pVals[3].data.dbl,
  3323. pVals[4].data.dbl );
  3324. break;
  3325. case box_fct:
  3326. this->value.data.log = saobox( pVals[0].data.dbl, pVals[1].data.dbl,
  3327. pVals[2].data.dbl, pVals[3].data.dbl,
  3328. pVals[4].data.dbl, pVals[5].data.dbl,
  3329. pVals[6].data.dbl );
  3330. break;
  3331. case elps_fct:
  3332. this->value.data.log =
  3333. ellipse( pVals[0].data.dbl, pVals[1].data.dbl,
  3334. pVals[2].data.dbl, pVals[3].data.dbl,
  3335. pVals[4].data.dbl, pVals[5].data.dbl,
  3336. pVals[6].data.dbl );
  3337. break;
  3338. /* C Conditional expression: bool ? expr : expr */
  3339. case ifthenelse_fct:
  3340. switch( this->type ) {
  3341. case BOOLEAN:
  3342. this->value.data.log = ( pVals[2].data.log ?
  3343. pVals[0].data.log : pVals[1].data.log );
  3344. break;
  3345. case LONG:
  3346. this->value.data.lng = ( pVals[2].data.log ?
  3347. pVals[0].data.lng : pVals[1].data.lng );
  3348. break;
  3349. case DOUBLE:
  3350. this->value.data.dbl = ( pVals[2].data.log ?
  3351. pVals[0].data.dbl : pVals[1].data.dbl );
  3352. break;
  3353. case STRING:
  3354. strcpy(this->value.data.str, ( pVals[2].data.log ?
  3355. pVals[0].data.str :
  3356. pVals[1].data.str ) );
  3357. break;
  3358. }
  3359. break;
  3360. /* String functions */
  3361. case strmid_fct:
  3362. cstrmid(this->value.data.str, this->value.nelem,
  3363. pVals[0].data.str, pVals[0].nelem,
  3364. pVals[1].data.lng);
  3365. break;
  3366. case strpos_fct:
  3367. {
  3368. char *res = strstr(pVals[0].data.str, pVals[1].data.str);
  3369. if (res == NULL) {
  3370. this->value.data.lng = 0;
  3371. } else {
  3372. this->value.data.lng = (res - pVals[0].data.str) + 1;
  3373. }
  3374. break;
  3375. }
  3376. }
  3377. this->operation = CONST_OP;
  3378. } else {
  3379. Allocate_Ptrs( this );
  3380. row = gParse.nRows;
  3381. elem = row * this->value.nelem;
  3382. if( !gParse.status ) {
  3383. switch( this->operation ) {
  3384. /* Special functions with no arguments */
  3385. case row_fct:
  3386. while( row-- ) {
  3387. this->value.data.lngptr[row] = gParse.firstRow + row;
  3388. this->value.undef[row] = 0;
  3389. }
  3390. break;
  3391. case null_fct:
  3392. if( this->type==LONG ) {
  3393. while( row-- ) {
  3394. this->value.data.lngptr[row] = 0;
  3395. this->value.undef[row] = 1;
  3396. }
  3397. } else if( this->type==STRING ) {
  3398. while( row-- ) {
  3399. this->value.data.strptr[row][0] = '\0';
  3400. this->value.undef[row] = 1;
  3401. }
  3402. }
  3403. break;
  3404. case rnd_fct:
  3405. while( elem-- ) {
  3406. this->value.data.dblptr[elem] = ran1();
  3407. this->value.undef[elem] = 0;
  3408. }
  3409. break;
  3410. case gasrnd_fct:
  3411. while( elem-- ) {
  3412. this->value.data.dblptr[elem] = gasdev();
  3413. this->value.undef[elem] = 0;
  3414. }
  3415. break;
  3416. case poirnd_fct:
  3417. if( theParams[0]->type==DOUBLE ) {
  3418. if (theParams[0]->operation == CONST_OP) {
  3419. while( elem-- ) {
  3420. this->value.undef[elem] = (pVals[0].data.dbl < 0);
  3421. if (! this->value.undef[elem]) {
  3422. this->value.data.lngptr[elem] = poidev(pVals[0].data.dbl);
  3423. }
  3424. }
  3425. } else {
  3426. while( elem-- ) {
  3427. this->value.undef[elem] = theParams[0]->value.undef[elem];
  3428. if (theParams[0]->value.data.dblptr[elem] < 0)
  3429. this->value.undef[elem] = 1;
  3430. if (! this->value.undef[elem]) {
  3431. this->value.data.lngptr[elem] =
  3432. poidev(theParams[0]->value.data.dblptr[elem]);
  3433. }
  3434. } /* while */
  3435. } /* ! CONST_OP */
  3436. } else {
  3437. /* LONG */
  3438. if (theParams[0]->operation == CONST_OP) {
  3439. while( elem-- ) {
  3440. this->value.undef[elem] = (pVals[0].data.lng < 0);
  3441. if (! this->value.undef[elem]) {
  3442. this->value.data.lngptr[elem] = poidev(pVals[0].data.lng);
  3443. }
  3444. }
  3445. } else {
  3446. while( elem-- ) {
  3447. this->value.undef[elem] = theParams[0]->value.undef[elem];
  3448. if (theParams[0]->value.data.lngptr[elem] < 0)
  3449. this->value.undef[elem] = 1;
  3450. if (! this->value.undef[elem]) {
  3451. this->value.data.lngptr[elem] =
  3452. poidev(theParams[0]->value.data.lngptr[elem]);
  3453. }
  3454. } /* while */
  3455. } /* ! CONST_OP */
  3456. } /* END LONG */
  3457. break;
  3458. /* Non-Trig single-argument functions */
  3459. case sum_fct:
  3460. elem = row * theParams[0]->value.nelem;
  3461. if( theParams[0]->type==BOOLEAN ) {
  3462. while( row-- ) {
  3463. this->value.data.lngptr[row] = 0;
  3464. /* Default is UNDEF until a defined value is found */
  3465. this->value.undef[row] = 1;
  3466. nelem = theParams[0]->value.nelem;
  3467. while( nelem-- ) {
  3468. elem--;
  3469. if ( ! theParams[0]->value.undef[elem] ) {
  3470. this->value.data.lngptr[row] +=
  3471. ( theParams[0]->value.data.logptr[elem] ? 1 : 0 );
  3472. this->value.undef[row] = 0;
  3473. }
  3474. }
  3475. }
  3476. } else if( theParams[0]->type==LONG ) {
  3477. while( row-- ) {
  3478. this->value.data.lngptr[row] = 0;
  3479. /* Default is UNDEF until a defined value is found */
  3480. this->value.undef[row] = 1;
  3481. nelem = theParams[0]->value.nelem;
  3482. while( nelem-- ) {
  3483. elem--;
  3484. if ( ! theParams[0]->value.undef[elem] ) {
  3485. this->value.data.lngptr[row] +=
  3486. theParams[0]->value.data.lngptr[elem];
  3487. this->value.undef[row] = 0;
  3488. }
  3489. }
  3490. }
  3491. } else if( theParams[0]->type==DOUBLE ){
  3492. while( row-- ) {
  3493. this->value.data.dblptr[row] = 0.0;
  3494. /* Default is UNDEF until a defined value is found */
  3495. this->value.undef[row] = 1;
  3496. nelem = theParams[0]->value.nelem;
  3497. while( nelem-- ) {
  3498. elem--;
  3499. if ( ! theParams[0]->value.undef[elem] ) {
  3500. this->value.data.dblptr[row] +=
  3501. theParams[0]->value.data.dblptr[elem];
  3502. this->value.undef[row] = 0;
  3503. }
  3504. }
  3505. }
  3506. } else { /* BITSTR */
  3507. nelem = theParams[0]->value.nelem;
  3508. while( row-- ) {
  3509. char *sptr1 = theParams[0]->value.data.strptr[row];
  3510. this->value.data.lngptr[row] = 0;
  3511. this->value.undef[row] = 0;
  3512. while (*sptr1) {
  3513. if (*sptr1 == '1') this->value.data.lngptr[row] ++;
  3514. sptr1++;
  3515. }
  3516. }
  3517. }
  3518. break;
  3519. case average_fct:
  3520. elem = row * theParams[0]->value.nelem;
  3521. if( theParams[0]->type==LONG ) {
  3522. while( row-- ) {
  3523. int count = 0;
  3524. this->value.data.dblptr[row] = 0;
  3525. nelem = theParams[0]->value.nelem;
  3526. while( nelem-- ) {
  3527. elem--;
  3528. if (theParams[0]->value.undef[elem] == 0) {
  3529. this->value.data.dblptr[row] +=
  3530. theParams[0]->value.data.lngptr[elem];
  3531. count ++;
  3532. }
  3533. }
  3534. if (count == 0) {
  3535. this->value.undef[row] = 1;
  3536. } else {
  3537. this->value.undef[row] = 0;
  3538. this->value.data.dblptr[row] /= count;
  3539. }
  3540. }
  3541. } else if( theParams[0]->type==DOUBLE ){
  3542. while( row-- ) {
  3543. int count = 0;
  3544. this->value.data.dblptr[row] = 0;
  3545. nelem = theParams[0]->value.nelem;
  3546. while( nelem-- ) {
  3547. elem--;
  3548. if (theParams[0]->value.undef[elem] == 0) {
  3549. this->value.data.dblptr[row] +=
  3550. theParams[0]->value.data.dblptr[elem];
  3551. count ++;
  3552. }
  3553. }
  3554. if (count == 0) {
  3555. this->value.undef[row] = 1;
  3556. } else {
  3557. this->value.undef[row] = 0;
  3558. this->value.data.dblptr[row] /= count;
  3559. }
  3560. }
  3561. }
  3562. break;
  3563. case stddev_fct:
  3564. elem = row * theParams[0]->value.nelem;
  3565. if( theParams[0]->type==LONG ) {
  3566. /* Compute the mean value */
  3567. while( row-- ) {
  3568. int count = 0;
  3569. double sum = 0, sum2 = 0;
  3570. nelem = theParams[0]->value.nelem;
  3571. while( nelem-- ) {
  3572. elem--;
  3573. if (theParams[0]->value.undef[elem] == 0) {
  3574. sum += theParams[0]->value.data.lngptr[elem];
  3575. count ++;
  3576. }
  3577. }
  3578. if (count > 1) {
  3579. sum /= count;
  3580. /* Compute the sum of squared deviations */
  3581. nelem = theParams[0]->value.nelem;
  3582. elem += nelem; /* Reset elem for second pass */
  3583. while( nelem-- ) {
  3584. elem--;
  3585. if (theParams[0]->value.undef[elem] == 0) {
  3586. double dx = (theParams[0]->value.data.lngptr[elem] - sum);
  3587. sum2 += (dx*dx);
  3588. }
  3589. }
  3590. sum2 /= (double)count-1;
  3591. this->value.undef[row] = 0;
  3592. this->value.data.dblptr[row] = sqrt(sum2);
  3593. } else {
  3594. this->value.undef[row] = 0; /* STDDEV => 0 */
  3595. this->value.data.dblptr[row] = 0;
  3596. }
  3597. }
  3598. } else if( theParams[0]->type==DOUBLE ){
  3599. /* Compute the mean value */
  3600. while( row-- ) {
  3601. int count = 0;
  3602. double sum = 0, sum2 = 0;
  3603. nelem = theParams[0]->value.nelem;
  3604. while( nelem-- ) {
  3605. elem--;
  3606. if (theParams[0]->value.undef[elem] == 0) {
  3607. sum += theParams[0]->value.data.dblptr[elem];
  3608. count ++;
  3609. }
  3610. }
  3611. if (count > 1) {
  3612. sum /= count;
  3613. /* Compute the sum of squared deviations */
  3614. nelem = theParams[0]->value.nelem;
  3615. elem += nelem; /* Reset elem for second pass */
  3616. while( nelem-- ) {
  3617. elem--;
  3618. if (theParams[0]->value.undef[elem] == 0) {
  3619. double dx = (theParams[0]->value.data.dblptr[elem] - sum);
  3620. sum2 += (dx*dx);
  3621. }
  3622. }
  3623. sum2 /= (double)count-1;
  3624. this->value.undef[row] = 0;
  3625. this->value.data.dblptr[row] = sqrt(sum2);
  3626. } else {
  3627. this->value.undef[row] = 0; /* STDDEV => 0 */
  3628. this->value.data.dblptr[row] = 0;
  3629. }
  3630. }
  3631. }
  3632. break;
  3633. case median_fct:
  3634. elem = row * theParams[0]->value.nelem;
  3635. nelem = theParams[0]->value.nelem;
  3636. if( theParams[0]->type==LONG ) {
  3637. long *dptr = theParams[0]->value.data.lngptr;
  3638. char *uptr = theParams[0]->value.undef;
  3639. long *mptr = (long *) malloc(sizeof(long)*nelem);
  3640. int irow;
  3641. /* Allocate temporary storage for this row, since the
  3642. quickselect function will scramble the contents */
  3643. if (mptr == 0) {
  3644. yyerror("Could not allocate temporary memory in median function");
  3645. free( this->value.data.ptr );
  3646. break;
  3647. }
  3648. for (irow=0; irow<row; irow++) {
  3649. long *p = mptr;
  3650. int nelem1 = nelem;
  3651. int count = 0;
  3652. while ( nelem1-- ) {
  3653. if (*uptr == 0) {
  3654. *p++ = *dptr; /* Only advance the dest pointer if we copied */
  3655. }
  3656. dptr ++; /* Advance the source pointer ... */
  3657. uptr ++; /* ... and source "undef" pointer */
  3658. }
  3659. nelem1 = (p - mptr); /* Number of accepted data points */
  3660. if (nelem1 > 0) {
  3661. this->value.undef[irow] = 0;
  3662. this->value.data.lngptr[irow] = qselect_median_lng(mptr, nelem1);
  3663. } else {
  3664. this->value.undef[irow] = 1;
  3665. this->value.data.lngptr[irow] = 0;
  3666. }
  3667. }
  3668. free(mptr);
  3669. } else {
  3670. double *dptr = theParams[0]->value.data.dblptr;
  3671. char *uptr = theParams[0]->value.undef;
  3672. double *mptr = (double *) malloc(sizeof(double)*nelem);
  3673. int irow;
  3674. /* Allocate temporary storage for this row, since the
  3675. quickselect function will scramble the contents */
  3676. if (mptr == 0) {
  3677. yyerror("Could not allocate temporary memory in median function");
  3678. free( this->value.data.ptr );
  3679. break;
  3680. }
  3681. for (irow=0; irow<row; irow++) {
  3682. double *p = mptr;
  3683. int nelem1 = nelem;
  3684. while ( nelem1-- ) {
  3685. if (*uptr == 0) {
  3686. *p++ = *dptr; /* Only advance the dest pointer if we copied */
  3687. }
  3688. dptr ++; /* Advance the source pointer ... */
  3689. uptr ++; /* ... and source "undef" pointer */
  3690. }
  3691. nelem1 = (p - mptr); /* Number of accepted data points */
  3692. if (nelem1 > 0) {
  3693. this->value.undef[irow] = 0;
  3694. this->value.data.dblptr[irow] = qselect_median_dbl(mptr, nelem1);
  3695. } else {
  3696. this->value.undef[irow] = 1;
  3697. this->value.data.dblptr[irow] = 0;
  3698. }
  3699. }
  3700. free(mptr);
  3701. }
  3702. break;
  3703. case abs_fct:
  3704. if( theParams[0]->type==DOUBLE )
  3705. while( elem-- ) {
  3706. dval = theParams[0]->value.data.dblptr[elem];
  3707. this->value.data.dblptr[elem] = (dval>0.0 ? dval : -dval);
  3708. this->value.undef[elem] = theParams[0]->value.undef[elem];
  3709. }
  3710. else
  3711. while( elem-- ) {
  3712. ival = theParams[0]->value.data.lngptr[elem];
  3713. this->value.data.lngptr[elem] = (ival> 0 ? ival : -ival);
  3714. this->value.undef[elem] = theParams[0]->value.undef[elem];
  3715. }
  3716. break;
  3717. /* Special Null-Handling Functions */
  3718. case nonnull_fct:
  3719. nelem = theParams[0]->value.nelem;
  3720. if ( theParams[0]->type==STRING ) nelem = 1;
  3721. elem = row * nelem;
  3722. while( row-- ) {
  3723. int nelem1 = nelem;
  3724. this->value.undef[row] = 0; /* Initialize to 0 (defined) */
  3725. this->value.data.lngptr[row] = 0;
  3726. while( nelem1-- ) {
  3727. elem --;
  3728. if ( theParams[0]->value.undef[elem] == 0 ) this->value.data.lngptr[row] ++;
  3729. }
  3730. }
  3731. break;
  3732. case isnull_fct:
  3733. if( theParams[0]->type==STRING ) elem = row;
  3734. while( elem-- ) {
  3735. this->value.data.logptr[elem] = theParams[0]->value.undef[elem];
  3736. this->value.undef[elem] = 0;
  3737. }
  3738. break;
  3739. case defnull_fct:
  3740. switch( this->type ) {
  3741. case BOOLEAN:
  3742. while( row-- ) {
  3743. nelem = this->value.nelem;
  3744. while( nelem-- ) {
  3745. elem--;
  3746. i=2; while( i-- )
  3747. if( vector[i]>1 ) {
  3748. pNull[i] = theParams[i]->value.undef[elem];
  3749. pVals[i].data.log =
  3750. theParams[i]->value.data.logptr[elem];
  3751. } else if( vector[i] ) {
  3752. pNull[i] = theParams[i]->value.undef[row];
  3753. pVals[i].data.log =
  3754. theParams[i]->value.data.logptr[row];
  3755. }
  3756. if( pNull[0] ) {
  3757. this->value.undef[elem] = pNull[1];
  3758. this->value.data.logptr[elem] = pVals[1].data.log;
  3759. } else {
  3760. this->value.undef[elem] = 0;
  3761. this->value.data.logptr[elem] = pVals[0].data.log;
  3762. }
  3763. }
  3764. }
  3765. break;
  3766. case LONG:
  3767. while( row-- ) {
  3768. nelem = this->value.nelem;
  3769. while( nelem-- ) {
  3770. elem--;
  3771. i=2; while( i-- )
  3772. if( vector[i]>1 ) {
  3773. pNull[i] = theParams[i]->value.undef[elem];
  3774. pVals[i].data.lng =
  3775. theParams[i]->value.data.lngptr[elem];
  3776. } else if( vector[i] ) {
  3777. pNull[i] = theParams[i]->value.undef[row];
  3778. pVals[i].data.lng =
  3779. theParams[i]->value.data.lngptr[row];
  3780. }
  3781. if( pNull[0] ) {
  3782. this->value.undef[elem] = pNull[1];
  3783. this->value.data.lngptr[elem] = pVals[1].data.lng;
  3784. } else {
  3785. this->value.undef[elem] = 0;
  3786. this->value.data.lngptr[elem] = pVals[0].data.lng;
  3787. }
  3788. }
  3789. }
  3790. break;
  3791. case DOUBLE:
  3792. while( row-- ) {
  3793. nelem = this->value.nelem;
  3794. while( nelem-- ) {
  3795. elem--;
  3796. i=2; while( i-- )
  3797. if( vector[i]>1 ) {
  3798. pNull[i] = theParams[i]->value.undef[elem];
  3799. pVals[i].data.dbl =
  3800. theParams[i]->value.data.dblptr[elem];
  3801. } else if( vector[i] ) {
  3802. pNull[i] = theParams[i]->value.undef[row];
  3803. pVals[i].data.dbl =
  3804. theParams[i]->value.data.dblptr[row];
  3805. }
  3806. if( pNull[0] ) {
  3807. this->value.undef[elem] = pNull[1];
  3808. this->value.data.dblptr[elem] = pVals[1].data.dbl;
  3809. } else {
  3810. this->value.undef[elem] = 0;
  3811. this->value.data.dblptr[elem] = pVals[0].data.dbl;
  3812. }
  3813. }
  3814. }
  3815. break;
  3816. case STRING:
  3817. while( row-- ) {
  3818. i=2; while( i-- )
  3819. if( vector[i] ) {
  3820. pNull[i] = theParams[i]->value.undef[row];
  3821. strcpy(pVals[i].data.str,
  3822. theParams[i]->value.data.strptr[row]);
  3823. }
  3824. if( pNull[0] ) {
  3825. this->value.undef[row] = pNull[1];
  3826. strcpy(this->value.data.strptr[row],pVals[1].data.str);
  3827. } else {
  3828. this->value.undef[elem] = 0;
  3829. strcpy(this->value.data.strptr[row],pVals[0].data.str);
  3830. }
  3831. }
  3832. }
  3833. break;
  3834. /* Math functions with 1 double argument */
  3835. case sin_fct:
  3836. while( elem-- )
  3837. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3838. this->value.data.dblptr[elem] =
  3839. sin( theParams[0]->value.data.dblptr[elem] );
  3840. }
  3841. break;
  3842. case cos_fct:
  3843. while( elem-- )
  3844. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3845. this->value.data.dblptr[elem] =
  3846. cos( theParams[0]->value.data.dblptr[elem] );
  3847. }
  3848. break;
  3849. case tan_fct:
  3850. while( elem-- )
  3851. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3852. this->value.data.dblptr[elem] =
  3853. tan( theParams[0]->value.data.dblptr[elem] );
  3854. }
  3855. break;
  3856. case asin_fct:
  3857. while( elem-- )
  3858. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3859. dval = theParams[0]->value.data.dblptr[elem];
  3860. if( dval<-1.0 || dval>1.0 ) {
  3861. this->value.data.dblptr[elem] = 0.0;
  3862. this->value.undef[elem] = 1;
  3863. } else
  3864. this->value.data.dblptr[elem] = asin( dval );
  3865. }
  3866. break;
  3867. case acos_fct:
  3868. while( elem-- )
  3869. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3870. dval = theParams[0]->value.data.dblptr[elem];
  3871. if( dval<-1.0 || dval>1.0 ) {
  3872. this->value.data.dblptr[elem] = 0.0;
  3873. this->value.undef[elem] = 1;
  3874. } else
  3875. this->value.data.dblptr[elem] = acos( dval );
  3876. }
  3877. break;
  3878. case atan_fct:
  3879. while( elem-- )
  3880. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3881. dval = theParams[0]->value.data.dblptr[elem];
  3882. this->value.data.dblptr[elem] = atan( dval );
  3883. }
  3884. break;
  3885. case sinh_fct:
  3886. while( elem-- )
  3887. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3888. this->value.data.dblptr[elem] =
  3889. sinh( theParams[0]->value.data.dblptr[elem] );
  3890. }
  3891. break;
  3892. case cosh_fct:
  3893. while( elem-- )
  3894. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3895. this->value.data.dblptr[elem] =
  3896. cosh( theParams[0]->value.data.dblptr[elem] );
  3897. }
  3898. break;
  3899. case tanh_fct:
  3900. while( elem-- )
  3901. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3902. this->value.data.dblptr[elem] =
  3903. tanh( theParams[0]->value.data.dblptr[elem] );
  3904. }
  3905. break;
  3906. case exp_fct:
  3907. while( elem-- )
  3908. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3909. dval = theParams[0]->value.data.dblptr[elem];
  3910. this->value.data.dblptr[elem] = exp( dval );
  3911. }
  3912. break;
  3913. case log_fct:
  3914. while( elem-- )
  3915. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3916. dval = theParams[0]->value.data.dblptr[elem];
  3917. if( dval<=0.0 ) {
  3918. this->value.data.dblptr[elem] = 0.0;
  3919. this->value.undef[elem] = 1;
  3920. } else
  3921. this->value.data.dblptr[elem] = log( dval );
  3922. }
  3923. break;
  3924. case log10_fct:
  3925. while( elem-- )
  3926. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3927. dval = theParams[0]->value.data.dblptr[elem];
  3928. if( dval<=0.0 ) {
  3929. this->value.data.dblptr[elem] = 0.0;
  3930. this->value.undef[elem] = 1;
  3931. } else
  3932. this->value.data.dblptr[elem] = log10( dval );
  3933. }
  3934. break;
  3935. case sqrt_fct:
  3936. while( elem-- )
  3937. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3938. dval = theParams[0]->value.data.dblptr[elem];
  3939. if( dval<0.0 ) {
  3940. this->value.data.dblptr[elem] = 0.0;
  3941. this->value.undef[elem] = 1;
  3942. } else
  3943. this->value.data.dblptr[elem] = sqrt( dval );
  3944. }
  3945. break;
  3946. case ceil_fct:
  3947. while( elem-- )
  3948. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3949. this->value.data.dblptr[elem] =
  3950. ceil( theParams[0]->value.data.dblptr[elem] );
  3951. }
  3952. break;
  3953. case floor_fct:
  3954. while( elem-- )
  3955. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3956. this->value.data.dblptr[elem] =
  3957. floor( theParams[0]->value.data.dblptr[elem] );
  3958. }
  3959. break;
  3960. case round_fct:
  3961. while( elem-- )
  3962. if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) {
  3963. this->value.data.dblptr[elem] =
  3964. floor( theParams[0]->value.data.dblptr[elem] + 0.5);
  3965. }
  3966. break;
  3967. /* Two-argument Trig Functions */
  3968. case atan2_fct:
  3969. while( row-- ) {
  3970. nelem = this->value.nelem;
  3971. while( nelem-- ) {
  3972. elem--;
  3973. i=2; while( i-- )
  3974. if( vector[i]>1 ) {
  3975. pVals[i].data.dbl =
  3976. theParams[i]->value.data.dblptr[elem];
  3977. pNull[i] = theParams[i]->value.undef[elem];
  3978. } else if( vector[i] ) {
  3979. pVals[i].data.dbl =
  3980. theParams[i]->value.data.dblptr[row];
  3981. pNull[i] = theParams[i]->value.undef[row];
  3982. }
  3983. if( !(this->value.undef[elem] = (pNull[0] || pNull[1]) ) )
  3984. this->value.data.dblptr[elem] =
  3985. atan2( pVals[0].data.dbl, pVals[1].data.dbl );
  3986. }
  3987. }
  3988. break;
  3989. /* Four-argument ANGSEP Function */
  3990. case angsep_fct:
  3991. while( row-- ) {
  3992. nelem = this->value.nelem;
  3993. while( nelem-- ) {
  3994. elem--;
  3995. i=4; while( i-- )
  3996. if( vector[i]>1 ) {
  3997. pVals[i].data.dbl =
  3998. theParams[i]->value.data.dblptr[elem];
  3999. pNull[i] = theParams[i]->value.undef[elem];
  4000. } else if( vector[i] ) {
  4001. pVals[i].data.dbl =
  4002. theParams[i]->value.data.dblptr[row];
  4003. pNull[i] = theParams[i]->value.undef[row];
  4004. }
  4005. if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
  4006. pNull[2] || pNull[3]) ) )
  4007. this->value.data.dblptr[elem] =
  4008. angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl,
  4009. pVals[2].data.dbl, pVals[3].data.dbl);
  4010. }
  4011. }
  4012. break;
  4013. /* Min/Max functions taking 1 or 2 arguments */
  4014. case min1_fct:
  4015. elem = row * theParams[0]->value.nelem;
  4016. if( this->type==LONG ) {
  4017. long minVal=0;
  4018. while( row-- ) {
  4019. valInit = 1;
  4020. this->value.undef[row] = 1;
  4021. nelem = theParams[0]->value.nelem;
  4022. while( nelem-- ) {
  4023. elem--;
  4024. if ( !theParams[0]->value.undef[elem] ) {
  4025. if ( valInit ) {
  4026. valInit = 0;
  4027. minVal = theParams[0]->value.data.lngptr[elem];
  4028. } else {
  4029. minVal = minvalue( minVal,
  4030. theParams[0]->value.data.lngptr[elem] );
  4031. }
  4032. this->value.undef[row] = 0;
  4033. }
  4034. }
  4035. this->value.data.lngptr[row] = minVal;
  4036. }
  4037. } else if( this->type==DOUBLE ) {
  4038. double minVal=0.0;
  4039. while( row-- ) {
  4040. valInit = 1;
  4041. this->value.undef[row] = 1;
  4042. nelem = theParams[0]->value.nelem;
  4043. while( nelem-- ) {
  4044. elem--;
  4045. if ( !theParams[0]->value.undef[elem] ) {
  4046. if ( valInit ) {
  4047. valInit = 0;
  4048. minVal = theParams[0]->value.data.dblptr[elem];
  4049. } else {
  4050. minVal = minvalue( minVal,
  4051. theParams[0]->value.data.dblptr[elem] );
  4052. }
  4053. this->value.undef[row] = 0;
  4054. }
  4055. }
  4056. this->value.data.dblptr[row] = minVal;
  4057. }
  4058. } else if( this->type==BITSTR ) {
  4059. char minVal;
  4060. while( row-- ) {
  4061. char *sptr1 = theParams[0]->value.data.strptr[row];
  4062. minVal = '1';
  4063. while (*sptr1) {
  4064. if (*sptr1 == '0') minVal = '0';
  4065. sptr1++;
  4066. }
  4067. this->value.data.strptr[row][0] = minVal;
  4068. this->value.data.strptr[row][1] = 0; /* Null terminate */
  4069. }
  4070. }
  4071. break;
  4072. case min2_fct:
  4073. if( this->type==LONG ) {
  4074. while( row-- ) {
  4075. nelem = this->value.nelem;
  4076. while( nelem-- ) {
  4077. elem--;
  4078. i=2; while( i-- )
  4079. if( vector[i]>1 ) {
  4080. pVals[i].data.lng =
  4081. theParams[i]->value.data.lngptr[elem];
  4082. pNull[i] = theParams[i]->value.undef[elem];
  4083. } else if( vector[i] ) {
  4084. pVals[i].data.lng =
  4085. theParams[i]->value.data.lngptr[row];
  4086. pNull[i] = theParams[i]->value.undef[row];
  4087. }
  4088. if( pNull[0] && pNull[1] ) {
  4089. this->value.undef[elem] = 1;
  4090. this->value.data.lngptr[elem] = 0;
  4091. } else if (pNull[0]) {
  4092. this->value.undef[elem] = 0;
  4093. this->value.data.lngptr[elem] = pVals[1].data.lng;
  4094. } else if (pNull[1]) {
  4095. this->value.undef[elem] = 0;
  4096. this->value.data.lngptr[elem] = pVals[0].data.lng;
  4097. } else {
  4098. this->value.undef[elem] = 0;
  4099. this->value.data.lngptr[elem] =
  4100. minvalue( pVals[0].data.lng, pVals[1].data.lng );
  4101. }
  4102. }
  4103. }
  4104. } else if( this->type==DOUBLE ) {
  4105. while( row-- ) {
  4106. nelem = this->value.nelem;
  4107. while( nelem-- ) {
  4108. elem--;
  4109. i=2; while( i-- )
  4110. if( vector[i]>1 ) {
  4111. pVals[i].data.dbl =
  4112. theParams[i]->value.data.dblptr[elem];
  4113. pNull[i] = theParams[i]->value.undef[elem];
  4114. } else if( vector[i] ) {
  4115. pVals[i].data.dbl =
  4116. theParams[i]->value.data.dblptr[row];
  4117. pNull[i] = theParams[i]->value.undef[row];
  4118. }
  4119. if( pNull[0] && pNull[1] ) {
  4120. this->value.undef[elem] = 1;
  4121. this->value.data.dblptr[elem] = 0;
  4122. } else if (pNull[0]) {
  4123. this->value.undef[elem] = 0;
  4124. this->value.data.dblptr[elem] = pVals[1].data.dbl;
  4125. } else if (pNull[1]) {
  4126. this->value.undef[elem] = 0;
  4127. this->value.data.dblptr[elem] = pVals[0].data.dbl;
  4128. } else {
  4129. this->value.undef[elem] = 0;
  4130. this->value.data.dblptr[elem] =
  4131. minvalue( pVals[0].data.dbl, pVals[1].data.dbl );
  4132. }
  4133. }
  4134. }
  4135. }
  4136. break;
  4137. case max1_fct:
  4138. elem = row * theParams[0]->value.nelem;
  4139. if( this->type==LONG ) {
  4140. long maxVal=0;
  4141. while( row-- ) {
  4142. valInit = 1;
  4143. this->value.undef[row] = 1;
  4144. nelem = theParams[0]->value.nelem;
  4145. while( nelem-- ) {
  4146. elem--;
  4147. if ( !theParams[0]->value.undef[elem] ) {
  4148. if ( valInit ) {
  4149. valInit = 0;
  4150. maxVal = theParams[0]->value.data.lngptr[elem];
  4151. } else {
  4152. maxVal = maxvalue( maxVal,
  4153. theParams[0]->value.data.lngptr[elem] );
  4154. }
  4155. this->value.undef[row] = 0;
  4156. }
  4157. }
  4158. this->value.data.lngptr[row] = maxVal;
  4159. }
  4160. } else if( this->type==DOUBLE ) {
  4161. double maxVal=0.0;
  4162. while( row-- ) {
  4163. valInit = 1;
  4164. this->value.undef[row] = 1;
  4165. nelem = theParams[0]->value.nelem;
  4166. while( nelem-- ) {
  4167. elem--;
  4168. if ( !theParams[0]->value.undef[elem] ) {
  4169. if ( valInit ) {
  4170. valInit = 0;
  4171. maxVal = theParams[0]->value.data.dblptr[elem];
  4172. } else {
  4173. maxVal = maxvalue( maxVal,
  4174. theParams[0]->value.data.dblptr[elem] );
  4175. }
  4176. this->value.undef[row] = 0;
  4177. }
  4178. }
  4179. this->value.data.dblptr[row] = maxVal;
  4180. }
  4181. } else if( this->type==BITSTR ) {
  4182. char maxVal;
  4183. while( row-- ) {
  4184. char *sptr1 = theParams[0]->value.data.strptr[row];
  4185. maxVal = '0';
  4186. while (*sptr1) {
  4187. if (*sptr1 == '1') maxVal = '1';
  4188. sptr1++;
  4189. }
  4190. this->value.data.strptr[row][0] = maxVal;
  4191. this->value.data.strptr[row][1] = 0; /* Null terminate */
  4192. }
  4193. }
  4194. break;
  4195. case max2_fct:
  4196. if( this->type==LONG ) {
  4197. while( row-- ) {
  4198. nelem = this->value.nelem;
  4199. while( nelem-- ) {
  4200. elem--;
  4201. i=2; while( i-- )
  4202. if( vector[i]>1 ) {
  4203. pVals[i].data.lng =
  4204. theParams[i]->value.data.lngptr[elem];
  4205. pNull[i] = theParams[i]->value.undef[elem];
  4206. } else if( vector[i] ) {
  4207. pVals[i].data.lng =
  4208. theParams[i]->value.data.lngptr[row];
  4209. pNull[i] = theParams[i]->value.undef[row];
  4210. }
  4211. if( pNull[0] && pNull[1] ) {
  4212. this->value.undef[elem] = 1;
  4213. this->value.data.lngptr[elem] = 0;
  4214. } else if (pNull[0]) {
  4215. this->value.undef[elem] = 0;
  4216. this->value.data.lngptr[elem] = pVals[1].data.lng;
  4217. } else if (pNull[1]) {
  4218. this->value.undef[elem] = 0;
  4219. this->value.data.lngptr[elem] = pVals[0].data.lng;
  4220. } else {
  4221. this->value.undef[elem] = 0;
  4222. this->value.data.lngptr[elem] =
  4223. maxvalue( pVals[0].data.lng, pVals[1].data.lng );
  4224. }
  4225. }
  4226. }
  4227. } else if( this->type==DOUBLE ) {
  4228. while( row-- ) {
  4229. nelem = this->value.nelem;
  4230. while( nelem-- ) {
  4231. elem--;
  4232. i=2; while( i-- )
  4233. if( vector[i]>1 ) {
  4234. pVals[i].data.dbl =
  4235. theParams[i]->value.data.dblptr[elem];
  4236. pNull[i] = theParams[i]->value.undef[elem];
  4237. } else if( vector[i] ) {
  4238. pVals[i].data.dbl =
  4239. theParams[i]->value.data.dblptr[row];
  4240. pNull[i] = theParams[i]->value.undef[row];
  4241. }
  4242. if( pNull[0] && pNull[1] ) {
  4243. this->value.undef[elem] = 1;
  4244. this->value.data.dblptr[elem] = 0;
  4245. } else if (pNull[0]) {
  4246. this->value.undef[elem] = 0;
  4247. this->value.data.dblptr[elem] = pVals[1].data.dbl;
  4248. } else if (pNull[1]) {
  4249. this->value.undef[elem] = 0;
  4250. this->value.data.dblptr[elem] = pVals[0].data.dbl;
  4251. } else {
  4252. this->value.undef[elem] = 0;
  4253. this->value.data.dblptr[elem] =
  4254. maxvalue( pVals[0].data.dbl, pVals[1].data.dbl );
  4255. }
  4256. }
  4257. }
  4258. }
  4259. break;
  4260. /* Boolean SAO region Functions... scalar or vector dbls */
  4261. case near_fct:
  4262. while( row-- ) {
  4263. nelem = this->value.nelem;
  4264. while( nelem-- ) {
  4265. elem--;
  4266. i=3; while( i-- )
  4267. if( vector[i]>1 ) {
  4268. pVals[i].data.dbl =
  4269. theParams[i]->value.data.dblptr[elem];
  4270. pNull[i] = theParams[i]->value.undef[elem];
  4271. } else if( vector[i] ) {
  4272. pVals[i].data.dbl =
  4273. theParams[i]->value.data.dblptr[row];
  4274. pNull[i] = theParams[i]->value.undef[row];
  4275. }
  4276. if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
  4277. pNull[2]) ) )
  4278. this->value.data.logptr[elem] =
  4279. bnear( pVals[0].data.dbl, pVals[1].data.dbl,
  4280. pVals[2].data.dbl );
  4281. }
  4282. }
  4283. break;
  4284. case circle_fct:
  4285. while( row-- ) {
  4286. nelem = this->value.nelem;
  4287. while( nelem-- ) {
  4288. elem--;
  4289. i=5; while( i-- )
  4290. if( vector[i]>1 ) {
  4291. pVals[i].data.dbl =
  4292. theParams[i]->value.data.dblptr[elem];
  4293. pNull[i] = theParams[i]->value.undef[elem];
  4294. } else if( vector[i] ) {
  4295. pVals[i].data.dbl =
  4296. theParams[i]->value.data.dblptr[row];
  4297. pNull[i] = theParams[i]->value.undef[row];
  4298. }
  4299. if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
  4300. pNull[2] || pNull[3] ||
  4301. pNull[4]) ) )
  4302. this->value.data.logptr[elem] =
  4303. circle( pVals[0].data.dbl, pVals[1].data.dbl,
  4304. pVals[2].data.dbl, pVals[3].data.dbl,
  4305. pVals[4].data.dbl );
  4306. }
  4307. }
  4308. break;
  4309. case box_fct:
  4310. while( row-- ) {
  4311. nelem = this->value.nelem;
  4312. while( nelem-- ) {
  4313. elem--;
  4314. i=7; while( i-- )
  4315. if( vector[i]>1 ) {
  4316. pVals[i].data.dbl =
  4317. theParams[i]->value.data.dblptr[elem];
  4318. pNull[i] = theParams[i]->value.undef[elem];
  4319. } else if( vector[i] ) {
  4320. pVals[i].data.dbl =
  4321. theParams[i]->value.data.dblptr[row];
  4322. pNull[i] = theParams[i]->value.undef[row];
  4323. }
  4324. if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
  4325. pNull[2] || pNull[3] ||
  4326. pNull[4] || pNull[5] ||
  4327. pNull[6] ) ) )
  4328. this->value.data.logptr[elem] =
  4329. saobox( pVals[0].data.dbl, pVals[1].data.dbl,
  4330. pVals[2].data.dbl, pVals[3].data.dbl,
  4331. pVals[4].data.dbl, pVals[5].data.dbl,
  4332. pVals[6].data.dbl );
  4333. }
  4334. }
  4335. break;
  4336. case elps_fct:
  4337. while( row-- ) {
  4338. nelem = this->value.nelem;
  4339. while( nelem-- ) {
  4340. elem--;
  4341. i=7; while( i-- )
  4342. if( vector[i]>1 ) {
  4343. pVals[i].data.dbl =
  4344. theParams[i]->value.data.dblptr[elem];
  4345. pNull[i] = theParams[i]->value.undef[elem];
  4346. } else if( vector[i] ) {
  4347. pVals[i].data.dbl =
  4348. theParams[i]->value.data.dblptr[row];
  4349. pNull[i] = theParams[i]->value.undef[row];
  4350. }
  4351. if( !(this->value.undef[elem] = (pNull[0] || pNull[1] ||
  4352. pNull[2] || pNull[3] ||
  4353. pNull[4] || pNull[5] ||
  4354. pNull[6] ) ) )
  4355. this->value.data.logptr[elem] =
  4356. ellipse( pVals[0].data.dbl, pVals[1].data.dbl,
  4357. pVals[2].data.dbl, pVals[3].data.dbl,
  4358. pVals[4].data.dbl, pVals[5].data.dbl,
  4359. pVals[6].data.dbl );
  4360. }
  4361. }
  4362. break;
  4363. /* C Conditional expression: bool ? expr : expr */
  4364. case ifthenelse_fct:
  4365. switch( this->type ) {
  4366. case BOOLEAN:
  4367. while( row-- ) {
  4368. nelem = this->value.nelem;
  4369. while( nelem-- ) {
  4370. elem--;
  4371. if( vector[2]>1 ) {
  4372. pVals[2].data.log =
  4373. theParams[2]->value.data.logptr[elem];
  4374. pNull[2] = theParams[2]->value.undef[elem];
  4375. } else if( vector[2] ) {
  4376. pVals[2].data.log =
  4377. theParams[2]->value.data.logptr[row];
  4378. pNull[2] = theParams[2]->value.undef[row];
  4379. }
  4380. i=2; while( i-- )
  4381. if( vector[i]>1 ) {
  4382. pVals[i].data.log =
  4383. theParams[i]->value.data.logptr[elem];
  4384. pNull[i] = theParams[i]->value.undef[elem];
  4385. } else if( vector[i] ) {
  4386. pVals[i].data.log =
  4387. theParams[i]->value.data.logptr[row];
  4388. pNull[i] = theParams[i]->value.undef[row];
  4389. }
  4390. if( !(this->value.undef[elem] = pNull[2]) ) {
  4391. if( pVals[2].data.log ) {
  4392. this->value.data.logptr[elem] = pVals[0].data.log;
  4393. this->value.undef[elem] = pNull[0];
  4394. } else {
  4395. this->value.data.logptr[elem] = pVals[1].data.log;
  4396. this->value.undef[elem] = pNull[1];
  4397. }
  4398. }
  4399. }
  4400. }
  4401. break;
  4402. case LONG:
  4403. while( row-- ) {
  4404. nelem = this->value.nelem;
  4405. while( nelem-- ) {
  4406. elem--;
  4407. if( vector[2]>1 ) {
  4408. pVals[2].data.log =
  4409. theParams[2]->value.data.logptr[elem];
  4410. pNull[2] = theParams[2]->value.undef[elem];
  4411. } else if( vector[2] ) {
  4412. pVals[2].data.log =
  4413. theParams[2]->value.data.logptr[row];
  4414. pNull[2] = theParams[2]->value.undef[row];
  4415. }
  4416. i=2; while( i-- )
  4417. if( vector[i]>1 ) {
  4418. pVals[i].data.lng =
  4419. theParams[i]->value.data.lngptr[elem];
  4420. pNull[i] = theParams[i]->value.undef[elem];
  4421. } else if( vector[i] ) {
  4422. pVals[i].data.lng =
  4423. theParams[i]->value.data.lngptr[row];
  4424. pNull[i] = theParams[i]->value.undef[row];
  4425. }
  4426. if( !(this->value.undef[elem] = pNull[2]) ) {
  4427. if( pVals[2].data.log ) {
  4428. this->value.data.lngptr[elem] = pVals[0].data.lng;
  4429. this->value.undef[elem] = pNull[0];
  4430. } else {
  4431. this->value.data.lngptr[elem] = pVals[1].data.lng;
  4432. this->value.undef[elem] = pNull[1];
  4433. }
  4434. }
  4435. }
  4436. }
  4437. break;
  4438. case DOUBLE:
  4439. while( row-- ) {
  4440. nelem = this->value.nelem;
  4441. while( nelem-- ) {
  4442. elem--;
  4443. if( vector[2]>1 ) {
  4444. pVals[2].data.log =
  4445. theParams[2]->value.data.logptr[elem];
  4446. pNull[2] = theParams[2]->value.undef[elem];
  4447. } else if( vector[2] ) {
  4448. pVals[2].data.log =
  4449. theParams[2]->value.data.logptr[row];
  4450. pNull[2] = theParams[2]->value.undef[row];
  4451. }
  4452. i=2; while( i-- )
  4453. if( vector[i]>1 ) {
  4454. pVals[i].data.dbl =
  4455. theParams[i]->value.data.dblptr[elem];
  4456. pNull[i] = theParams[i]->value.undef[elem];
  4457. } else if( vector[i] ) {
  4458. pVals[i].data.dbl =
  4459. theParams[i]->value.data.dblptr[row];
  4460. pNull[i] = theParams[i]->value.undef[row];
  4461. }
  4462. if( !(this->value.undef[elem] = pNull[2]) ) {
  4463. if( pVals[2].data.log ) {
  4464. this->value.data.dblptr[elem] = pVals[0].data.dbl;
  4465. this->value.undef[elem] = pNull[0];
  4466. } else {
  4467. this->value.data.dblptr[elem] = pVals[1].data.dbl;
  4468. this->value.undef[elem] = pNull[1];
  4469. }
  4470. }
  4471. }
  4472. }
  4473. break;
  4474. case STRING:
  4475. while( row-- ) {
  4476. if( vector[2] ) {
  4477. pVals[2].data.log = theParams[2]->value.data.logptr[row];
  4478. pNull[2] = theParams[2]->value.undef[row];
  4479. }
  4480. i=2; while( i-- )
  4481. if( vector[i] ) {
  4482. strcpy( pVals[i].data.str,
  4483. theParams[i]->value.data.strptr[row] );
  4484. pNull[i] = theParams[i]->value.undef[row];
  4485. }
  4486. if( !(this->value.undef[row] = pNull[2]) ) {
  4487. if( pVals[2].data.log ) {
  4488. strcpy( this->value.data.strptr[row],
  4489. pVals[0].data.str );
  4490. this->value.undef[row] = pNull[0];
  4491. } else {
  4492. strcpy( this->value.data.strptr[row],
  4493. pVals[1].data.str );
  4494. this->value.undef[row] = pNull[1];
  4495. }
  4496. } else {
  4497. this->value.data.strptr[row][0] = '\0';
  4498. }
  4499. }
  4500. break;
  4501. }
  4502. break;
  4503. /* String functions */
  4504. case strmid_fct:
  4505. {
  4506. int strconst = theParams[0]->operation == CONST_OP;
  4507. int posconst = theParams[1]->operation == CONST_OP;
  4508. int lenconst = theParams[2]->operation == CONST_OP;
  4509. int dest_len = this->value.nelem;
  4510. int src_len = theParams[0]->value.nelem;
  4511. while (row--) {
  4512. int pos;
  4513. int len;
  4514. char *str;
  4515. int undef = 0;
  4516. if (posconst) {
  4517. pos = theParams[1]->value.data.lng;
  4518. } else {
  4519. pos = theParams[1]->value.data.lngptr[row];
  4520. if (theParams[1]->value.undef[row]) undef = 1;
  4521. }
  4522. if (strconst) {
  4523. str = theParams[0]->value.data.str;
  4524. if (src_len == 0) src_len = strlen(str);
  4525. } else {
  4526. str = theParams[0]->value.data.strptr[row];
  4527. if (theParams[0]->value.undef[row]) undef = 1;
  4528. }
  4529. if (lenconst) {
  4530. len = dest_len;
  4531. } else {
  4532. len = theParams[2]->value.data.lngptr[row];
  4533. if (theParams[2]->value.undef[row]) undef = 1;
  4534. }
  4535. this->value.data.strptr[row][0] = '\0';
  4536. if (pos == 0) undef = 1;
  4537. if (! undef ) {
  4538. if (cstrmid(this->value.data.strptr[row], len,
  4539. str, src_len, pos) < 0) break;
  4540. }
  4541. this->value.undef[row] = undef;
  4542. }
  4543. }
  4544. break;
  4545. /* String functions */
  4546. case strpos_fct:
  4547. {
  4548. int const1 = theParams[0]->operation == CONST_OP;
  4549. int const2 = theParams[1]->operation == CONST_OP;
  4550. while (row--) {
  4551. char *str1, *str2;
  4552. int undef = 0;
  4553. if (const1) {
  4554. str1 = theParams[0]->value.data.str;
  4555. } else {
  4556. str1 = theParams[0]->value.data.strptr[row];
  4557. if (theParams[0]->value.undef[row]) undef = 1;
  4558. }
  4559. if (const2) {
  4560. str2 = theParams[1]->value.data.str;
  4561. } else {
  4562. str2 = theParams[1]->value.data.strptr[row];
  4563. if (theParams[1]->value.undef[row]) undef = 1;
  4564. }
  4565. this->value.data.lngptr[row] = 0;
  4566. if (! undef ) {
  4567. char *res = strstr(str1, str2);
  4568. if (res == NULL) {
  4569. undef = 1;
  4570. this->value.data.lngptr[row] = 0;
  4571. } else {
  4572. this->value.data.lngptr[row] = (res - str1) + 1;
  4573. }
  4574. }
  4575. this->value.undef[row] = undef;
  4576. }
  4577. }
  4578. break;
  4579. } /* End switch(this->operation) */
  4580. } /* End if (!gParse.status) */
  4581. } /* End non-constant operations */
  4582. i = this->nSubNodes;
  4583. while( i-- ) {
  4584. if( theParams[i]->operation>0 ) {
  4585. /* Currently only numeric params allowed */
  4586. free( theParams[i]->value.data.ptr );
  4587. }
  4588. }
  4589. }
  4590. static void Do_Deref( Node *this )
  4591. {
  4592. Node *theVar, *theDims[MAXDIMS];
  4593. int isConst[MAXDIMS], allConst;
  4594. long dimVals[MAXDIMS];
  4595. int i, nDims;
  4596. long row, elem, dsize;
  4597. theVar = gParse.Nodes + this->SubNodes[0];
  4598. i = nDims = this->nSubNodes-1;
  4599. allConst = 1;
  4600. while( i-- ) {
  4601. theDims[i] = gParse.Nodes + this->SubNodes[i+1];
  4602. isConst[i] = ( theDims[i]->operation==CONST_OP );
  4603. if( isConst[i] )
  4604. dimVals[i] = theDims[i]->value.data.lng;
  4605. else
  4606. allConst = 0;
  4607. }
  4608. if( this->type==DOUBLE ) {
  4609. dsize = sizeof( double );
  4610. } else if( this->type==LONG ) {
  4611. dsize = sizeof( long );
  4612. } else if( this->type==BOOLEAN ) {
  4613. dsize = sizeof( char );
  4614. } else
  4615. dsize = 0;
  4616. Allocate_Ptrs( this );
  4617. if( !gParse.status ) {
  4618. if( allConst && theVar->value.naxis==nDims ) {
  4619. /* Dereference completely using constant indices */
  4620. elem = 0;
  4621. i = nDims;
  4622. while( i-- ) {
  4623. if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break;
  4624. elem = theVar->value.naxes[i]*elem + dimVals[i]-1;
  4625. }
  4626. if( i<0 ) {
  4627. for( row=0; row<gParse.nRows; row++ ) {
  4628. if( this->type==STRING )
  4629. this->value.undef[row] = theVar->value.undef[row];
  4630. else if( this->type==BITSTR )
  4631. this->value.undef; /* Dummy - BITSTRs do not have undefs */
  4632. else
  4633. this->value.undef[row] = theVar->value.undef[elem];
  4634. if( this->type==DOUBLE )
  4635. this->value.data.dblptr[row] =
  4636. theVar->value.data.dblptr[elem];
  4637. else if( this->type==LONG )
  4638. this->value.data.lngptr[row] =
  4639. theVar->value.data.lngptr[elem];
  4640. else if( this->type==BOOLEAN )
  4641. this->value.data.logptr[row] =
  4642. theVar->value.data.logptr[elem];
  4643. else {
  4644. /* XXX Note, the below expression uses knowledge of
  4645. the layout of the string format, namely (nelem+1)
  4646. characters per string, followed by (nelem+1)
  4647. "undef" values. */
  4648. this->value.data.strptr[row][0] =
  4649. theVar->value.data.strptr[0][elem+row];
  4650. this->value.data.strptr[row][1] = 0; /* Null terminate */
  4651. }
  4652. elem += theVar->value.nelem;
  4653. }
  4654. } else {
  4655. yyerror("Index out of range");
  4656. free( this->value.data.ptr );
  4657. }
  4658. } else if( allConst && nDims==1 ) {
  4659. /* Reduce dimensions by 1, using a constant index */
  4660. if( dimVals[0] < 1 ||
  4661. dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) {
  4662. yyerror("Index out of range");
  4663. free( this->value.data.ptr );
  4664. } else if ( this->type == BITSTR || this->type == STRING ) {
  4665. elem = this->value.nelem * (dimVals[0]-1);
  4666. for( row=0; row<gParse.nRows; row++ ) {
  4667. if (this->value.undef)
  4668. this->value.undef[row] = theVar->value.undef[row];
  4669. memcpy( (char*)this->value.data.strptr[0]
  4670. + row*sizeof(char)*(this->value.nelem+1),
  4671. (char*)theVar->value.data.strptr[0] + elem*sizeof(char),
  4672. this->value.nelem * sizeof(char) );
  4673. /* Null terminate */
  4674. this->value.data.strptr[row][this->value.nelem] = 0;
  4675. elem += theVar->value.nelem+1;
  4676. }
  4677. } else {
  4678. elem = this->value.nelem * (dimVals[0]-1);
  4679. for( row=0; row<gParse.nRows; row++ ) {
  4680. memcpy( this->value.undef + row*this->value.nelem,
  4681. theVar->value.undef + elem,
  4682. this->value.nelem * sizeof(char) );
  4683. memcpy( (char*)this->value.data.ptr
  4684. + row*dsize*this->value.nelem,
  4685. (char*)theVar->value.data.ptr + elem*dsize,
  4686. this->value.nelem * dsize );
  4687. elem += theVar->value.nelem;
  4688. }
  4689. }
  4690. } else if( theVar->value.naxis==nDims ) {
  4691. /* Dereference completely using an expression for the indices */
  4692. for( row=0; row<gParse.nRows; row++ ) {
  4693. for( i=0; i<nDims; i++ ) {
  4694. if( !isConst[i] ) {
  4695. if( theDims[i]->value.undef[row] ) {
  4696. yyerror("Null encountered as vector index");
  4697. free( this->value.data.ptr );
  4698. break;
  4699. } else
  4700. dimVals[i] = theDims[i]->value.data.lngptr[row];
  4701. }
  4702. }
  4703. if( gParse.status ) break;
  4704. elem = 0;
  4705. i = nDims;
  4706. while( i-- ) {
  4707. if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break;
  4708. elem = theVar->value.naxes[i]*elem + dimVals[i]-1;
  4709. }
  4710. if( i<0 ) {
  4711. elem += row*theVar->value.nelem;
  4712. if( this->type==STRING )
  4713. this->value.undef[row] = theVar->value.undef[row];
  4714. else if( this->type==BITSTR )
  4715. this->value.undef; /* Dummy - BITSTRs do not have undefs */
  4716. else
  4717. this->value.undef[row] = theVar->value.undef[elem];
  4718. if( this->type==DOUBLE )
  4719. this->value.data.dblptr[row] =
  4720. theVar->value.data.dblptr[elem];
  4721. else if( this->type==LONG )
  4722. this->value.data.lngptr[row] =
  4723. theVar->value.data.lngptr[elem];
  4724. else if( this->type==BOOLEAN )
  4725. this->value.data.logptr[row] =
  4726. theVar->value.data.logptr[elem];
  4727. else {
  4728. /* XXX Note, the below expression uses knowledge of
  4729. the layout of the string format, namely (nelem+1)
  4730. characters per string, followed by (nelem+1)
  4731. "undef" values. */
  4732. this->value.data.strptr[row][0] =
  4733. theVar->value.data.strptr[0][elem+row];
  4734. this->value.data.strptr[row][1] = 0; /* Null terminate */
  4735. }
  4736. } else {
  4737. yyerror("Index out of range");
  4738. free( this->value.data.ptr );
  4739. }
  4740. }
  4741. } else {
  4742. /* Reduce dimensions by 1, using a nonconstant expression */
  4743. for( row=0; row<gParse.nRows; row++ ) {
  4744. /* Index cannot be a constant */
  4745. if( theDims[0]->value.undef[row] ) {
  4746. yyerror("Null encountered as vector index");
  4747. free( this->value.data.ptr );
  4748. break;
  4749. } else
  4750. dimVals[0] = theDims[0]->value.data.lngptr[row];
  4751. if( dimVals[0] < 1 ||
  4752. dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) {
  4753. yyerror("Index out of range");
  4754. free( this->value.data.ptr );
  4755. } else if ( this->type == BITSTR || this->type == STRING ) {
  4756. elem = this->value.nelem * (dimVals[0]-1);
  4757. elem += row*(theVar->value.nelem+1);
  4758. if (this->value.undef)
  4759. this->value.undef[row] = theVar->value.undef[row];
  4760. memcpy( (char*)this->value.data.strptr[0]
  4761. + row*sizeof(char)*(this->value.nelem+1),
  4762. (char*)theVar->value.data.strptr[0] + elem*sizeof(char),
  4763. this->value.nelem * sizeof(char) );
  4764. /* Null terminate */
  4765. this->value.data.strptr[row][this->value.nelem] = 0;
  4766. } else {
  4767. elem = this->value.nelem * (dimVals[0]-1);
  4768. elem += row*theVar->value.nelem;
  4769. memcpy( this->value.undef + row*this->value.nelem,
  4770. theVar->value.undef + elem,
  4771. this->value.nelem * sizeof(char) );
  4772. memcpy( (char*)this->value.data.ptr
  4773. + row*dsize*this->value.nelem,
  4774. (char*)theVar->value.data.ptr + elem*dsize,
  4775. this->value.nelem * dsize );
  4776. }
  4777. }
  4778. }
  4779. }
  4780. if( theVar->operation>0 ) {
  4781. if (theVar->type == STRING || theVar->type == BITSTR)
  4782. free(theVar->value.data.strptr[0] );
  4783. else
  4784. free( theVar->value.data.ptr );
  4785. }
  4786. for( i=0; i<nDims; i++ )
  4787. if( theDims[i]->operation>0 ) {
  4788. free( theDims[i]->value.data.ptr );
  4789. }
  4790. }
  4791. static void Do_GTI( Node *this )
  4792. {
  4793. Node *theExpr, *theTimes;
  4794. double *start, *stop, *times;
  4795. long elem, nGTI, gti;
  4796. int ordered;
  4797. theTimes = gParse.Nodes + this->SubNodes[0];
  4798. theExpr = gParse.Nodes + this->SubNodes[1];
  4799. nGTI = theTimes->value.nelem;
  4800. start = theTimes->value.data.dblptr;
  4801. stop = theTimes->value.data.dblptr + nGTI;
  4802. ordered = theTimes->type;
  4803. if( theExpr->operation==CONST_OP ) {
  4804. this->value.data.log =
  4805. (Search_GTI( theExpr->value.data.dbl, nGTI, start, stop, ordered )>=0);
  4806. this->operation = CONST_OP;
  4807. } else {
  4808. Allocate_Ptrs( this );
  4809. times = theExpr->value.data.dblptr;
  4810. if( !gParse.status ) {
  4811. elem = gParse.nRows * this->value.nelem;
  4812. if( nGTI ) {
  4813. gti = -1;
  4814. while( elem-- ) {
  4815. if( (this->value.undef[elem] = theExpr->value.undef[elem]) )
  4816. continue;
  4817. /* Before searching entire GTI, check the GTI found last time */
  4818. if( gti<0 || times[elem]<start[gti] || times[elem]>stop[gti] ) {
  4819. gti = Search_GTI( times[elem], nGTI, start, stop, ordered );
  4820. }
  4821. this->value.data.logptr[elem] = ( gti>=0 );
  4822. }
  4823. } else
  4824. while( elem-- ) {
  4825. this->value.data.logptr[elem] = 0;
  4826. this->value.undef[elem] = 0;
  4827. }
  4828. }
  4829. }
  4830. if( theExpr->operation>0 )
  4831. free( theExpr->value.data.ptr );
  4832. }
  4833. static long Search_GTI( double evtTime, long nGTI, double *start,
  4834. double *stop, int ordered )
  4835. {
  4836. long gti, step;
  4837. if( ordered && nGTI>15 ) { /* If time-ordered and lots of GTIs, */
  4838. /* use "FAST" Binary search algorithm */
  4839. if( evtTime>=start[0] && evtTime<=stop[nGTI-1] ) {
  4840. gti = step = (nGTI >> 1);
  4841. while(1) {
  4842. if( step>1L ) step >>= 1;
  4843. if( evtTime>stop[gti] ) {
  4844. if( evtTime>=start[gti+1] )
  4845. gti += step;
  4846. else {
  4847. gti = -1L;
  4848. break;
  4849. }
  4850. } else if( evtTime<start[gti] ) {
  4851. if( evtTime<=stop[gti-1] )
  4852. gti -= step;
  4853. else {
  4854. gti = -1L;
  4855. break;
  4856. }
  4857. } else {
  4858. break;
  4859. }
  4860. }
  4861. } else
  4862. gti = -1L;
  4863. } else { /* Use "SLOW" linear search */
  4864. gti = nGTI;
  4865. while( gti-- )
  4866. if( evtTime>=start[gti] && evtTime<=stop[gti] )
  4867. break;
  4868. }
  4869. return( gti );
  4870. }
  4871. static void Do_REG( Node *this )
  4872. {
  4873. Node *theRegion, *theX, *theY;
  4874. double Xval=0.0, Yval=0.0;
  4875. char Xnull=0, Ynull=0;
  4876. int Xvector, Yvector;
  4877. long nelem, elem, rows;
  4878. theRegion = gParse.Nodes + this->SubNodes[0];
  4879. theX = gParse.Nodes + this->SubNodes[1];
  4880. theY = gParse.Nodes + this->SubNodes[2];
  4881. Xvector = ( theX->operation!=CONST_OP );
  4882. if( Xvector )
  4883. Xvector = theX->value.nelem;
  4884. else {
  4885. Xval = theX->value.data.dbl;
  4886. }
  4887. Yvector = ( theY->operation!=CONST_OP );
  4888. if( Yvector )
  4889. Yvector = theY->value.nelem;
  4890. else {
  4891. Yval = theY->value.data.dbl;
  4892. }
  4893. if( !Xvector && !Yvector ) {
  4894. this->value.data.log =
  4895. ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr )
  4896. != 0 );
  4897. this->operation = CONST_OP;
  4898. } else {
  4899. Allocate_Ptrs( this );
  4900. if( !gParse.status ) {
  4901. rows = gParse.nRows;
  4902. nelem = this->value.nelem;
  4903. elem = rows*nelem;
  4904. while( rows-- ) {
  4905. while( nelem-- ) {
  4906. elem--;
  4907. if( Xvector>1 ) {
  4908. Xval = theX->value.data.dblptr[elem];
  4909. Xnull = theX->value.undef[elem];
  4910. } else if( Xvector ) {
  4911. Xval = theX->value.data.dblptr[rows];
  4912. Xnull = theX->value.undef[rows];
  4913. }
  4914. if( Yvector>1 ) {
  4915. Yval = theY->value.data.dblptr[elem];
  4916. Ynull = theY->value.undef[elem];
  4917. } else if( Yvector ) {
  4918. Yval = theY->value.data.dblptr[rows];
  4919. Ynull = theY->value.undef[rows];
  4920. }
  4921. this->value.undef[elem] = ( Xnull || Ynull );
  4922. if( this->value.undef[elem] )
  4923. continue;
  4924. this->value.data.logptr[elem] =
  4925. ( fits_in_region( Xval, Yval,
  4926. (SAORegion *)theRegion->value.data.ptr )
  4927. != 0 );
  4928. }
  4929. nelem = this->value.nelem;
  4930. }
  4931. }
  4932. }
  4933. if( theX->operation>0 )
  4934. free( theX->value.data.ptr );
  4935. if( theY->operation>0 )
  4936. free( theY->value.data.ptr );
  4937. }
  4938. static void Do_Vector( Node *this )
  4939. {
  4940. Node *that;
  4941. long row, elem, idx, jdx, offset=0;
  4942. int node;
  4943. Allocate_Ptrs( this );
  4944. if( !gParse.status ) {
  4945. for( node=0; node<this->nSubNodes; node++ ) {
  4946. that = gParse.Nodes + this->SubNodes[node];
  4947. if( that->operation == CONST_OP ) {
  4948. idx = gParse.nRows*this->value.nelem + offset;
  4949. while( (idx-=this->value.nelem)>=0 ) {
  4950. this->value.undef[idx] = 0;
  4951. switch( this->type ) {
  4952. case BOOLEAN:
  4953. this->value.data.logptr[idx] = that->value.data.log;
  4954. break;
  4955. case LONG:
  4956. this->value.data.lngptr[idx] = that->value.data.lng;
  4957. break;
  4958. case DOUBLE:
  4959. this->value.data.dblptr[idx] = that->value.data.dbl;
  4960. break;
  4961. }
  4962. }
  4963. } else {
  4964. row = gParse.nRows;
  4965. idx = row * that->value.nelem;
  4966. while( row-- ) {
  4967. elem = that->value.nelem;
  4968. jdx = row*this->value.nelem + offset;
  4969. while( elem-- ) {
  4970. this->value.undef[jdx+elem] =
  4971. that->value.undef[--idx];
  4972. switch( this->type ) {
  4973. case BOOLEAN:
  4974. this->value.data.logptr[jdx+elem] =
  4975. that->value.data.logptr[idx];
  4976. break;
  4977. case LONG:
  4978. this->value.data.lngptr[jdx+elem] =
  4979. that->value.data.lngptr[idx];
  4980. break;
  4981. case DOUBLE:
  4982. this->value.data.dblptr[jdx+elem] =
  4983. that->value.data.dblptr[idx];
  4984. break;
  4985. }
  4986. }
  4987. }
  4988. }
  4989. offset += that->value.nelem;
  4990. }
  4991. }
  4992. for( node=0; node < this->nSubNodes; node++ )
  4993. if( OPER(this->SubNodes[node])>0 )
  4994. free( gParse.Nodes[this->SubNodes[node]].value.data.ptr );
  4995. }
  4996. /*****************************************************************************/
  4997. /* Utility routines which perform the calculations on bits and SAO regions */
  4998. /*****************************************************************************/
  4999. static char bitlgte(char *bits1, int oper, char *bits2)
  5000. {
  5001. int val1, val2, nextbit;
  5002. char result;
  5003. int i, l1, l2, length, ldiff;
  5004. char stream[256];
  5005. char chr1, chr2;
  5006. l1 = strlen(bits1);
  5007. l2 = strlen(bits2);
  5008. if (l1 < l2)
  5009. {
  5010. length = l2;
  5011. ldiff = l2 - l1;
  5012. i=0;
  5013. while( ldiff-- ) stream[i++] = '0';
  5014. while( l1-- ) stream[i++] = *(bits1++);
  5015. stream[i] = '\0';
  5016. bits1 = stream;
  5017. }
  5018. else if (l2 < l1)
  5019. {
  5020. length = l1;
  5021. ldiff = l1 - l2;
  5022. i=0;
  5023. while( ldiff-- ) stream[i++] = '0';
  5024. while( l2-- ) stream[i++] = *(bits2++);
  5025. stream[i] = '\0';
  5026. bits2 = stream;
  5027. }
  5028. else
  5029. length = l1;
  5030. val1 = val2 = 0;
  5031. nextbit = 1;
  5032. while( length-- )
  5033. {
  5034. chr1 = bits1[length];
  5035. chr2 = bits2[length];
  5036. if ((chr1 != 'x')&&(chr1 != 'X')&&(chr2 != 'x')&&(chr2 != 'X'))
  5037. {
  5038. if (chr1 == '1') val1 += nextbit;
  5039. if (chr2 == '1') val2 += nextbit;
  5040. nextbit *= 2;
  5041. }
  5042. }
  5043. result = 0;
  5044. switch (oper)
  5045. {
  5046. case LT:
  5047. if (val1 < val2) result = 1;
  5048. break;
  5049. case LTE:
  5050. if (val1 <= val2) result = 1;
  5051. break;
  5052. case GT:
  5053. if (val1 > val2) result = 1;
  5054. break;
  5055. case GTE:
  5056. if (val1 >= val2) result = 1;
  5057. break;
  5058. }
  5059. return (result);
  5060. }
  5061. static void bitand(char *result,char *bitstrm1,char *bitstrm2)
  5062. {
  5063. int i, l1, l2, ldiff;
  5064. char stream[256];
  5065. char chr1, chr2;
  5066. l1 = strlen(bitstrm1);
  5067. l2 = strlen(bitstrm2);
  5068. if (l1 < l2)
  5069. {
  5070. ldiff = l2 - l1;
  5071. i=0;
  5072. while( ldiff-- ) stream[i++] = '0';
  5073. while( l1-- ) stream[i++] = *(bitstrm1++);
  5074. stream[i] = '\0';
  5075. bitstrm1 = stream;
  5076. }
  5077. else if (l2 < l1)
  5078. {
  5079. ldiff = l1 - l2;
  5080. i=0;
  5081. while( ldiff-- ) stream[i++] = '0';
  5082. while( l2-- ) stream[i++] = *(bitstrm2++);
  5083. stream[i] = '\0';
  5084. bitstrm2 = stream;
  5085. }
  5086. while ( (chr1 = *(bitstrm1++)) )
  5087. {
  5088. chr2 = *(bitstrm2++);
  5089. if ((chr1 == 'x') || (chr2 == 'x'))
  5090. *result = 'x';
  5091. else if ((chr1 == '1') && (chr2 == '1'))
  5092. *result = '1';
  5093. else
  5094. *result = '0';
  5095. result++;
  5096. }
  5097. *result = '\0';
  5098. }
  5099. static void bitor(char *result,char *bitstrm1,char *bitstrm2)
  5100. {
  5101. int i, l1, l2, ldiff;
  5102. char stream[256];
  5103. char chr1, chr2;
  5104. l1 = strlen(bitstrm1);
  5105. l2 = strlen(bitstrm2);
  5106. if (l1 < l2)
  5107. {
  5108. ldiff = l2 - l1;
  5109. i=0;
  5110. while( ldiff-- ) stream[i++] = '0';
  5111. while( l1-- ) stream[i++] = *(bitstrm1++);
  5112. stream[i] = '\0';
  5113. bitstrm1 = stream;
  5114. }
  5115. else if (l2 < l1)
  5116. {
  5117. ldiff = l1 - l2;
  5118. i=0;
  5119. while( ldiff-- ) stream[i++] = '0';
  5120. while( l2-- ) stream[i++] = *(bitstrm2++);
  5121. stream[i] = '\0';
  5122. bitstrm2 = stream;
  5123. }
  5124. while ( (chr1 = *(bitstrm1++)) )
  5125. {
  5126. chr2 = *(bitstrm2++);
  5127. if ((chr1 == '1') || (chr2 == '1'))
  5128. *result = '1';
  5129. else if ((chr1 == '0') || (chr2 == '0'))
  5130. *result = '0';
  5131. else
  5132. *result = 'x';
  5133. result++;
  5134. }
  5135. *result = '\0';
  5136. }
  5137. static void bitnot(char *result,char *bits)
  5138. {
  5139. int length;
  5140. char chr;
  5141. length = strlen(bits);
  5142. while( length-- ) {
  5143. chr = *(bits++);
  5144. *(result++) = ( chr=='1' ? '0' : ( chr=='0' ? '1' : chr ) );
  5145. }
  5146. *result = '\0';
  5147. }
  5148. static char bitcmp(char *bitstrm1, char *bitstrm2)
  5149. {
  5150. int i, l1, l2, ldiff;
  5151. char stream[256];
  5152. char chr1, chr2;
  5153. l1 = strlen(bitstrm1);
  5154. l2 = strlen(bitstrm2);
  5155. if (l1 < l2)
  5156. {
  5157. ldiff = l2 - l1;
  5158. i=0;
  5159. while( ldiff-- ) stream[i++] = '0';
  5160. while( l1-- ) stream[i++] = *(bitstrm1++);
  5161. stream[i] = '\0';
  5162. bitstrm1 = stream;
  5163. }
  5164. else if (l2 < l1)
  5165. {
  5166. ldiff = l1 - l2;
  5167. i=0;
  5168. while( ldiff-- ) stream[i++] = '0';
  5169. while( l2-- ) stream[i++] = *(bitstrm2++);
  5170. stream[i] = '\0';
  5171. bitstrm2 = stream;
  5172. }
  5173. while( (chr1 = *(bitstrm1++)) )
  5174. {
  5175. chr2 = *(bitstrm2++);
  5176. if ( ((chr1 == '0') && (chr2 == '1'))
  5177. || ((chr1 == '1') && (chr2 == '0')) )
  5178. return( 0 );
  5179. }
  5180. return( 1 );
  5181. }
  5182. static char bnear(double x, double y, double tolerance)
  5183. {
  5184. if (fabs(x - y) < tolerance)
  5185. return ( 1 );
  5186. else
  5187. return ( 0 );
  5188. }
  5189. static char saobox(double xcen, double ycen, double xwid, double ywid,
  5190. double rot, double xcol, double ycol)
  5191. {
  5192. double x,y,xprime,yprime,xmin,xmax,ymin,ymax,theta;
  5193. theta = (rot / 180.0) * myPI;
  5194. xprime = xcol - xcen;
  5195. yprime = ycol - ycen;
  5196. x = xprime * cos(theta) + yprime * sin(theta);
  5197. y = -xprime * sin(theta) + yprime * cos(theta);
  5198. xmin = - 0.5 * xwid; xmax = 0.5 * xwid;
  5199. ymin = - 0.5 * ywid; ymax = 0.5 * ywid;
  5200. if ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax))
  5201. return ( 1 );
  5202. else
  5203. return ( 0 );
  5204. }
  5205. static char circle(double xcen, double ycen, double rad,
  5206. double xcol, double ycol)
  5207. {
  5208. double r2,dx,dy,dlen;
  5209. dx = xcol - xcen;
  5210. dy = ycol - ycen;
  5211. dx *= dx; dy *= dy;
  5212. dlen = dx + dy;
  5213. r2 = rad * rad;
  5214. if (dlen <= r2)
  5215. return ( 1 );
  5216. else
  5217. return ( 0 );
  5218. }
  5219. static char ellipse(double xcen, double ycen, double xrad, double yrad,
  5220. double rot, double xcol, double ycol)
  5221. {
  5222. double x,y,xprime,yprime,dx,dy,dlen,theta;
  5223. theta = (rot / 180.0) * myPI;
  5224. xprime = xcol - xcen;
  5225. yprime = ycol - ycen;
  5226. x = xprime * cos(theta) + yprime * sin(theta);
  5227. y = -xprime * sin(theta) + yprime * cos(theta);
  5228. dx = x / xrad; dy = y / yrad;
  5229. dx *= dx; dy *= dy;
  5230. dlen = dx + dy;
  5231. if (dlen <= 1.0)
  5232. return ( 1 );
  5233. else
  5234. return ( 0 );
  5235. }
  5236. /*
  5237. * Extract substring
  5238. */
  5239. int cstrmid(char *dest_str, int dest_len,
  5240. char *src_str, int src_len,
  5241. int pos)
  5242. {
  5243. /* char fill_char = ' '; */
  5244. char fill_char = '\0';
  5245. if (src_len == 0) { src_len = strlen(src_str); } /* .. if constant */
  5246. /* Fill destination with blanks */
  5247. if (pos < 0) {
  5248. yyerror("STRMID(S,P,N) P must be 0 or greater");
  5249. return -1;
  5250. }
  5251. if (pos > src_len || pos == 0) {
  5252. /* pos==0: blank string requested */
  5253. memset(dest_str, fill_char, dest_len);
  5254. } else if (pos+dest_len > src_len) {
  5255. /* Copy a subset */
  5256. int nsub = src_len-pos+1;
  5257. int npad = dest_len - nsub;
  5258. memcpy(dest_str, src_str+pos-1, nsub);
  5259. /* Fill remaining string with blanks */
  5260. memset(dest_str+nsub, fill_char, npad);
  5261. } else {
  5262. /* Full string copy */
  5263. memcpy(dest_str, src_str+pos-1, dest_len);
  5264. }
  5265. dest_str[dest_len] = '\0'; /* Null-terminate */
  5266. return 0;
  5267. }
  5268. static void yyerror(char *s)
  5269. {
  5270. char msg[80];
  5271. if( !gParse.status ) gParse.status = PARSE_SYNTAX_ERR;
  5272. strncpy(msg, s, 80);
  5273. msg[79] = '\0';
  5274. ffpmsg(msg);
  5275. }