diff options
Diffstat (limited to 'funtools/tabcalc.c')
-rw-r--r-- | funtools/tabcalc.c | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/funtools/tabcalc.c b/funtools/tabcalc.c new file mode 100644 index 0000000..c3e0b4d --- /dev/null +++ b/funtools/tabcalc.c @@ -0,0 +1,296 @@ +/* + * + * This program was generated automatically by the funcalc program, + * by running the tabcalc.c template through the funcalc.l lexical analyzer. + * On this system, it was (or can be) built a command such as: + * + * $COMMAND + * + */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <funtools.h> +#include <word.h> +#include <NaN.h> + +extern char *optarg; +extern int optind; + +/* define the types of event records we have to handle */ +#define REC_CUR 1 +#define REC_PREV 2 +#define REC_NEXT 4 + +#define ARGC __nxarg +#define ARGV(n) ((__xargs && (n>=0) && (n<__nxarg)) ? __xargs[n] : NULL) + +#define I __i +#define NROW __nrow +#define WRITE_ROW FunTableRowPut(ofun, (char *)cur, 1, __i, NULL) + +/* default number of rows to read at a time */ +#define MAXROW 8192 +int __maxrow=MAXROW; + +/* floating check for equality */ +#ifndef feq +#define feq(x,y) (fabs((double)x-(double)y)<=(double)1.0E-15) +/* avoid divide by zero */ +#ifndef div +#define div(a,b) (feq(b,0)?(getnand()):(a/b)) +#endif +#endif + +typedef struct rowstruct{ +$MEMBERS +int __ncol; +} *Row, RowRec; + +/* global definitions and init calls go here */ +$GLOBAL + +/* main program */ +int main (int argc, char **argv) +{ + int __c, __i; + int __get, __got, __total, __rectype, __args; + int __saved=0; + int __del=0; + int __nxarg=0; + int __ip=0; + int __nrow=-1; + int __rawsize=0; + char *__s; + char *__cols=NULL; + char *__argstr=NULL; + char *__rawsave=NULL; + char *__rawbuf=NULL; + char **__xargs=NULL; + char __tbuf[SZ_LINE]; + Row __rowbuf, __rowrptr, __rowsptr, __roweptr; + Row cur, prev, next; + Fun fun, ofun; + off_t __opos; + $AUTO + + /* local definitions, followed by init calls, go here */ + $LOCAL + + /* exit on gio errors */ + if( !getenv("GERROR") ) + setgerror(2); + + /* avoid shared library problems by using "process" type for filtering */ + putenv("FILTER_PTYPE=process"); + + /* process switch arguments */ + while ((__c = getopt(argc, argv, "a:d")) != -1){ + switch(__c){ + case 'a': + __argstr = xstrdup(optarg); + break; + case 'd': + __del = 1; + break; + } + } + + /* check for required arguments */ + __args = argc - optind; + /* make sure we have minimal arguments */ + if( __args < $ARGS ){ + if( $ARGS == 1 ) + fprintf(stderr, "usage: %s iname\n", argv[0]); + else + fprintf(stderr, "usage: %s iname oname [cols]\n", argv[0]); + goto error; + } + + /* set passed arguments in __xargs array */ + if( __argstr && *__argstr ){ + __xargs = calloc(SZ_LINE, sizeof(char *)); + while( word(__argstr, __tbuf, &__ip) ){ + if( __nxarg >= SZ_LINE ){ + gerror(stderr, "too many args passed via -a\n"); + goto error; + } + __xargs[__nxarg++] = xstrdup(__tbuf); + } + } + + /* set rectype: determine whether we need prev,next records */ + __rectype=$RECTYPE; + + /* get maxrow,if user-specified */ + if( (__s=(char *)getenv("FUN_MAXROW")) != NULL ) + __maxrow = atoi(__s); + /* make sure max row is large enough to handle prev, next */ + if( __rectype & (REC_PREV|REC_NEXT) ) + __maxrow = MAX(3,__maxrow); + else + __maxrow = MAX(1,__maxrow); + /* this is what we read each time */ + __get = __maxrow; + + /* open input file */ + if( !(fun = FunOpen(argv[optind+0], "rc", NULL)) ){ + gerror(stderr, "could not FunOpen input file: %s\n", argv[optind+0]); + goto error; + } + + /* open the output FITS image, inheriting params from input */ + if( $ARGS > 1 ){ + if( !(ofun = FunOpen(argv[optind+1], "w", fun)) ){ + gerror(stderr, "could not FunOpen output file: %s\n", argv[optind+1]); + goto error; + } + } + + /* select columns */ + FunColumnSelect(fun, sizeof(RowRec), "merge=$MERGE", + $SELECT + "$N", "1J", "r", FUN_OFFSET(Row, __ncol), + NULL); + + /* activate specified columns -- these will be written to the output file */ + if( __args >= 3 ) __cols = argv[optind+2]; + FunColumnActivate(fun, __cols, NULL); + + /* allocate space for __rowbuf -- we will manage this buffer ourselves */ + /* NB: we need 2 extra rows for prev and next */ + __rowbuf = (Row)xcalloc(__maxrow+2, sizeof(RowRec)); + + /* get size of raw data record and allocate a raw record */ + FunInfoGet(fun, FUN_RAWSIZE, &__rawsize, 0); + __rawsave = (char *)xcalloc(1, __rawsize); + + /* no record read yet */ + __total = 0; + + /* any user-defined calls before we enter the row loop go here */ + $BEFORE + + /* main loop -- get rows and process */ + while( 1 ){ + if( !(__rectype & (REC_PREV|REC_NEXT)) ){ + /* offset of next record to process */ + __rowsptr = __rowbuf; + __rowrptr = __rowbuf; + } + /* need prev record */ + else if( __rectype & REC_PREV ){ + /* no records yet: read new batch of records into start of __rowbuf */ + if( __total == 0 ){ + __rowsptr = __rowbuf+1; + __rowrptr = __rowbuf; + } + /* read last processed record into start of __rowbuf, process others */ + else{ + if( __rectype & REC_NEXT ){ + memcpy(__rowbuf, __rowrptr+(__got-2), sizeof(RowRec)*2); + __rowsptr = __rowbuf+1; + __rowrptr = __rowbuf+2; + /* save raw data for this unprocessed record */ + FunInfoGet(fun, FUN_RAWBUF, &__rawbuf, 0); + memcpy(__rawsave, __rawbuf+((__got-1)*__rawsize), __rawsize); + } + else{ + memcpy(__rowbuf, __rowrptr+(__got-1), sizeof(RowRec)); + __rowsptr = __rowbuf+1; + __rowrptr = __rowbuf+1; + } + } + } + /* if we did not process last record, seek to it now and start there */ + else if( __rectype & REC_NEXT ){ + /* no records yet: read new batch of records into start of __rowbuf */ + if( __total == 0 ){ + __rowsptr = __rowbuf; + __rowrptr = __rowbuf; + } + /* read last processed record into first new record, process others */ + else{ + memcpy(__rowbuf, __rowrptr+(__got-1), sizeof(RowRec)); + __rowsptr = __rowbuf; + __rowrptr = __rowbuf+1; + /* save raw data for this unprocessed record */ + FunInfoGet(fun, FUN_RAWBUF, &__rawbuf, 0); + memcpy(__rawsave, __rawbuf+((__got-1)*__rawsize), __rawsize); + } + } + + /* read new rows */ + if( !FunTableRowGet(fun, __rowrptr, __get, NULL, &__got) || !__got ) + break; + + /* last record to process */ + __roweptr = __rowrptr + __got; + /* if we need access to next record, don't process the last one we read */ + if( __rectype & REC_NEXT ){ + __roweptr--; + } + + /* make sure there are rows to process */ + if( (__roweptr-__rowsptr) <= 0 ) break; + + /* process all rows */ + for(cur=__rowsptr, __i=__rowsptr-__rowrptr; cur<__roweptr; cur++, __i++){ + /* save raw buffer and switch rawbuf from previous */ + if( __i == -1 ){ + FunInfoGet(fun, FUN_RAWBUF, &__rawbuf, 0); + FunInfoPut(fun, FUN_RAWBUF, &__rawsave, 0); + __i = 0; + __saved = 1; + } + /* restore raw buffer */ + else if( __saved ){ + FunInfoPut(fun, FUN_RAWBUF, &__rawbuf, 0); + __i = 0; + __saved = 0; + } + /* finished another row */ + NROW++; + /* set up pointer to prev and next as needed */ + if( __rectype & REC_PREV ) prev = cur - 1; + if( __rectype & REC_NEXT ) next = cur + 1; + /* execute the expression */ + $EXPR + /* write out this row with the new column */ + if( $ARGS > 1 ) WRITE_ROW; + } + /* update total */ + __total += __got; + } + + /* any user-defined calls after we finish the row loop go here */ + $AFTER + + /* free row data */ + if( __rowbuf ) xfree(__rowbuf); + if( __rawsave ) xfree(__rawsave); + + /* free arg strings */ + if( __xargs ){ + for(__i=0; __i<__nxarg; __i++){ + if( __xargs[__i] ) xfree(__xargs[__i]); + } + xfree(__xargs); + } + + /* clean up -- close output before input to perform flush automatically */ + if( $ARGS > 1 ) + FunClose(ofun); + FunClose(fun); + + /* delete program if necessary */ + if( __del ) unlink(argv[0]); + return(0); + +error: + /* delete program if necessary */ + if( __del ) unlink(argv[0]); + return(1); +} |