diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-25 20:57:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-25 20:57:49 (GMT) |
commit | d1c4bf158203c4e8ec29fdeb83fd311e36320885 (patch) | |
tree | 15874534e282f67505ce4af5ba805a1ff70ec43e /funtools/funview.c | |
parent | e19a18e035dc4d0e8e215f9b452bb9ef6f58b9d7 (diff) | |
parent | 339420dd5dd874c41f6bab5808291fb4036dd022 (diff) | |
download | blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.zip blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.tar.gz blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.tar.bz2 |
Merge commit '339420dd5dd874c41f6bab5808291fb4036dd022' as 'funtools'
Diffstat (limited to 'funtools/funview.c')
-rw-r--r-- | funtools/funview.c | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/funtools/funview.c b/funtools/funview.c new file mode 100644 index 0000000..a03bad3 --- /dev/null +++ b/funtools/funview.c @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2005 Smithsonian Astrophysical Observatory + */ + +#include <funtoolsP.h> + +/* + * + * private routines + * + */ + +/* default data base files */ +#define FUN_VIEWFILE ".funtools.vu" +#define FUN_VIEWHOME "$HOME/.funtools.vu" + +/* default text options for database open */ +#define FUN_VIEWEXT "[1,TEXT(alen=1024)]" + +/* default is to allow multiple matches */ +#define FUN_VIEW_MATCH_DEFAULT 1 + +/* if a list is specified, do we also match templates? */ +#define FUN_VIEW_DOROW_DEFAULT 1 + +/* types of matches */ +#define MATCH_VIEW 1 +#define MATCH_FILE 2 +#define MATCH_VTMP 4 +#define MATCH_FTMP 8 + +/* this should match what is in fun_viewopen's alen above */ +#define SZ_VIEW 1024 + +/* parser characteristics struct */ +typedef struct _rowstruct{ + int type; + char view[SZ_VIEW]; + char file[SZ_VIEW]; + char fmt[SZ_VIEW]; + char cols[SZ_VIEW]; + char filt[SZ_VIEW]; +} *Row, RowRec; + +typedef struct _viewstruct{ + char *vname; + char *vroot; + int nlist; + int maxlist; + char **vlist; + Fun ifun; + Fun vfun; + int nrow; + int maxrow; + Row *rows; + Row file, filt, cols, fmt; + Row trow; +} *View, ViewRec; + +#ifdef ANSI_FUNC +static int +pathcmp(char *s1, char *s2) +#else +static int +pathcmp(s1, s2) + char *s1; + char *s2; +#endif +{ + char tbuf1[SZ_LINE]; + char tbuf2[SZ_LINE]; + char tbuf1a[SZ_LINE]; + char tbuf2a[SZ_LINE]; + + /* resolve pathnames and expand environment variables */ + ExpandEnv(s1, tbuf1, SZ_LINE); + ExpandEnv(s2, tbuf2, SZ_LINE); + ResolvePath(tbuf1, tbuf1a, SZ_LINE); + ResolvePath(tbuf2, tbuf2a, SZ_LINE); + + /* now compare strings */ + return strcmp(tbuf1a, tbuf2a); +} + +#ifdef ANSI_FUNC +static int +ViewFree(View view) +#else +static int ViewFree(view) + View view; +#endif +{ + int i; + + /* sanity check */ + if( !view ) return 0; + + /* free up resources */ + if( view->vfun ) FunClose(view->vfun); + if( view->vname ) xfree(view->vname); + if( view->vroot ) xfree(view->vroot); + if( view->trow ) xfree(view->trow); + if( view->rows ){ + for(i=0; i<view->nrow; i++){ + if( view->rows[i] ) xfree(view->rows[i]); + } + xfree(view->rows); + } + if( view->vlist ){ + for(i=0; i<view->nlist; i++){ + if( view->vlist[i] ) xfree(view->vlist[i]); + } + xfree(view->vlist); + } + xfree(view); + return 1; +} + +#ifdef ANSI_FUNC +static View +ViewNew(Fun fun, char *vname, char *vptr, char *vlist, char *dbname, int dbmax) +#else +static View +ViewNew(fun, vname, vptr, vlist, dbname, dbmax) + Fun fun; + char *vname; + char *vptr; + char *vlist; + char *dbname; + int dbmax; +#endif +{ + int ip=0; + char *s, *t; + char *rmode="r"; + char *fmode="rV"; + char *params=NULL; + char tbuf[SZ_LINE]; + char dtype[SZ_LINE]; + View view=NULL; + + /* look for view file in the usual places */ + if( (s=(char *)getenv("FUN_VIEWFILE")) && (t=Access(s, rmode)) ){ + xfree(t); + goto gotv; + } + else if( (t=Access(FUN_VIEWFILE, rmode)) ){ + xfree(t); + s = FUN_VIEWFILE; + goto gotv; + } + else if( (t=Access(FUN_VIEWHOME, rmode)) ){ + xfree(t); + s = FUN_VIEWHOME; + goto gotv; + } + else{ + return NULL; + } + +gotv: + /* allocate the view struct */ + if( !(view=(View)xcalloc(1, sizeof(ViewRec))) ){ + gerror(stderr, "can't allocate view database struct\n"); + return NULL; + } + /* allocate temp row */ + if( !(view->trow=(Row)xcalloc(1, sizeof(RowRec))) ){ + gerror(stderr, "can't allocate view temp row struct\n"); + ViewFree(view); + return NULL; + } + + /* add default text options to the filename, if needed */ + if( strchr(s, '[') ){ + strncpy(tbuf, s, SZ_LINE); + } + else{ + snprintf(tbuf, SZ_LINE, "%s%s", s, FUN_VIEWEXT); + } + + /* open the file */ + if( !(view->vfun=FunOpen(tbuf, fmode, NULL)) ){ + gerror(stderr, "can't open view database file: %s\n", s); + ViewFree(view); + return NULL; + } + + /* select columns from view database */ + snprintf(dtype, SZ_LINE-1, "%dA", SZ_VIEW); + FunColumnSelect(view->vfun, sizeof(RowRec), params, + "view", dtype, rmode, FUN_OFFSET(Row, view), + "file", dtype, rmode, FUN_OFFSET(Row, file), + "format", dtype, rmode, FUN_OFFSET(Row, fmt), + "columns", dtype, rmode, FUN_OFFSET(Row, cols), + "filter", dtype, rmode, FUN_OFFSET(Row, filt), + NULL); + + /* save original view string */ + view->vname = xstrdup(vname); + + /* save view name without any bracket extension */ + view->vroot = xstrdup(vptr); + if( (s=strchr(view->vroot, '[')) ) *s = '\0'; + + /* save original input Fun handle */ + view->ifun = fun; + + /* save vlist as separate strings */ + if( vlist ){ + newdtable(","); + while( word(vlist, tbuf, &ip) ){ + if( view->nlist >= view->maxlist ){ + view->maxlist += SZ_VIEW; + if( view->vlist ) + view->vlist = (char **)xrealloc(view->vlist, + view->maxlist*sizeof(char **)); + else + view->vlist = (char **)xmalloc(view->maxlist*sizeof(char **)); + } + /* add this record to the array of matches */ + view->vlist[view->nlist++] = xstrdup(tbuf); + } + freedtable(); + } + + /* temp row, in case template is matched as a file => use input file name */ + strncpy(view->trow->file, vptr, SZ_VIEW-1); + if( (s=strrchr(view->trow->file, '[')) ){ + /* remove extension from file (we'll put it back later, if necessary) */ + *s = '\0'; + } + /* return name of database used, if necessary */ + if( dbname ){ + FunInfoGet(view->vfun, FUN_FNAME, &s, 0); + strncpy(dbname, s, dbmax-1); + } + + /* return the good news */ + return view; +} + +#ifdef ANSI_FUNC +static int +ViewMatchRow(View view, Row row) +#else +static int +ViewMatchRow(view, row) + View view; + Row row; +#endif +{ + char *root=NULL; + + /* sanity check */ + if( !row || !view->vroot || !*view->vroot ) return 0; + + /* root is file without path */ + if( (root=strrchr(row->file, '/')) ) + root++; + else + root=row->file; + + /* look for various types of match */ + if( *row->view && !strcmp(view->vroot, row->view) ) + row->type |= MATCH_VIEW; + /* if not a vew, perhaps a view template */ + else if( *row->view && tmatch(view->vroot, row->view) ) + row->type |= MATCH_VTMP; + /* check for file, with and without path */ + if( (*row->file &&!pathcmp(view->vroot, row->file)) || + (root && *root && !strcmp(view->vroot, root))) + row->type |= MATCH_FILE; + /* if not a file, perhaps a file template */ + else if( root && *root && tmatch(view->vroot, root) ) + row->type |= MATCH_FTMP; + + /* return the results */ + return row->type; +} + +#ifdef ANSI_FUNC +static int +ViewSaveRow(View view, Row row) +#else +static int +ViewSaveRow(view, row) + View view; + Row row; +#endif +{ + /* make sure we have enough space */ + if( view->nrow >= view->maxrow ){ + view->maxrow += SZ_VIEW; + if( view->rows ) + view->rows = (Row *)xrealloc(view->rows, view->maxrow*sizeof(Row)); + else + view->rows = (Row *)xmalloc(view->maxrow*sizeof(Row)); + } + /* add this record to the array of matches */ + view->rows[view->nrow++] = row; + return view->nrow; +} + +#ifdef ANSI_FUNC +static int +ViewMatchList(View view, Row row, int dorow) +#else +static int +ViewMatchList(view, row, dorow) + View view; + Row row; + int dorow; +#endif +{ + int i; + + /* sanity check */ + if( !row || !view->vlist ) return 0; + + /* look though all view strings in the list */ + for(i=0; i<view->nlist; i++){ + /* does list view match row view? */ + if( !strcmp(view->vlist[i], row->view) ){ + row->type |= MATCH_VIEW; + break; + } + } + + /* also check row matches, if necessary */ + if( dorow ) ViewMatchRow(view, row); + + /* return the results */ + return row->type; +} + +#ifdef ANSI_FUNC +static int +ViewProcessMatches(View view, char *fname, int fmax) +#else +static int +ViewProcessMatches(view, fname, fmax) + View view; + char *fname; + int fmax; +#endif +{ + int i; + int nv=0; + int nf=0; + int nvt=0; + int nft=0; + int fgot=-1; + int tgot=-1; + int domulti=FUN_VIEW_MATCH_DEFAULT; + char *s=NULL; + + /* sanity check */ + if( !view ) return 0; + + /* do we match a single row or use multiple row to complete the spec? */ + if( (s=getenv("FUN_VIEWMATCH")) ){ + if( !strncmp(s, "m", 1) ){ + domulti = 1; + } + else if( !strncmp(s, "s", 1) ){ + domulti = 0; + } + } + + /* collect separate parts of fname using increasingly general matching */ + if( view->nrow ){ + /* get match counts */ + for(i=0; i<view->nrow; i++){ + if( view->rows[i]->type & MATCH_VIEW ) + nv++; + if( view->rows[i]->type & MATCH_VTMP ) + nvt++; + if( view->rows[i]->type & MATCH_FILE ) + nf++; + if( view->rows[i]->type & MATCH_FTMP ) + nft++; + } + /* view matches are the most desirable */ + if( nv ){ + for(i=0; i<view->nrow; i++){ + if( view->rows[i]->type & MATCH_VIEW ){ + /* if we are using a list, we always take the original filename */ + if( view->nlist ) + view->file = view->trow; + else if( !view->file && *view->rows[i]->file ) + view->file = view->rows[i]; + if( !view->filt && *view->rows[i]->filt ) + view->filt = view->rows[i]; + if( !view->cols && *view->rows[i]->cols ) + view->cols = view->rows[i]; + if( !view->fmt && *view->rows[i]->fmt ) + view->fmt = view->rows[i]; + tgot = i; + /* we only use one, unless we are running off a list */ + if( !view->nlist ) break; + } + } + } + /* if no view matches, try file matches */ + else if( nf ){ + for(i=0; i<view->nrow; i++){ + if( view->rows[i]->type & MATCH_FILE ){ + if( !view->file && *view->rows[i]->file ) + view->file = view->rows[i]; + if( !view->filt && *view->rows[i]->filt ) + view->filt = view->rows[i]; + if( !view->cols && *view->rows[i]->cols ) + view->cols = view->rows[i]; + if( !view->fmt && *view->rows[i]->fmt ) + view->fmt = view->rows[i]; + fgot = i; + break; + } + } + } + /* if we got a match, only do templates if multiple matches is true */ + if( (tgot==-1 && fgot==-1) || domulti ){ + for(i=0; i<view->nrow; i++){ + if( tgot == i ) continue; + if( view->rows[i]->type & MATCH_VTMP ){ + /* use the input file name in this case */ + if( !view->file && *view->rows[i]->file ) + view->file = view->trow; + if( !view->filt && *view->rows[i]->filt ) + view->filt = view->rows[i]; + if( !view->cols && *view->rows[i]->cols ) + view->cols = view->rows[i]; + if( !view->fmt && *view->rows[i]->fmt ) + view->fmt = view->rows[i]; + /* mark use of view template so we don't do file templates */ + tgot = i; + /* stop at one if not domulti */ + if( !domulti ) break; + } + } + } + /* if we got a match, only do templates if multiple matches is true */ + if( (tgot==-1 && fgot==-1) || domulti ){ + for(i=0; i<view->nrow; i++){ + if( fgot == i ) continue; + if( view->rows[i]->type & MATCH_FTMP ){ + /* use the input file name in this case */ + if( !view->file && *view->rows[i]->file ) + view->file = view->trow; + if( !view->filt && *view->rows[i]->filt ) + view->filt = view->rows[i]; + if( !view->cols && *view->rows[i]->cols ) + view->cols = view->rows[i]; + if( !view->fmt && *view->rows[i]->fmt ) + view->fmt = view->rows[i]; + /* stop at one if not domulti */ + if( !domulti ) break; + } + } + } + + /* now we can make up the fname from the pieces we have found */ + if( view->file && *view->file->file ){ + /* see if original input had an extension */ + if( (s=strchr(view->vname, '[')) ){ + /* if we can guess that original was a filter, don't add new one */ + if( strstr(s,"ann") || + strstr(s,"box") || + strstr(s,"cir") || + strstr(s,"ell") || + strstr(s,"lin") || + strstr(s,"pan") || + strstr(s,"pie") || + strstr(s,"poi") || + strstr(s,"qtp") || + strstr(s,"pol") || + strstr(s,"fie") || + strstr(s,"bpa") || + strstr(s,"cpa") || + strstr(s,"epa") || + /* guess at some sort of filter operation */ + strpbrk(s, "!&|~=<>+-/%^") ){ + snprintf(fname, fmax, "%s%s", view->file->file, s); + } + /* otherwise add original + new filter, if we have one */ + else{ + if( view->filt && *view->filt->filt ){ + snprintf(fname, fmax, "%s%s[%s]", + view->file->file, s, view->filt->filt); + } + /* just add original */ + else{ + snprintf(fname, fmax, "%s%s", view->file->file, s); + } + } + } + /* no original filter */ + else{ + /* otherwise new filter, if we have one */ + if( view->filt && *view->filt->filt ){ + snprintf(fname, fmax, "%s[%s]", view->file->file, view->filt->filt); + } + /* just the file name */ + else{ + snprintf(fname, fmax, "%s", view->file->file); + } + } + /* save other view info */ + if( view->ifun ){ + if( view->cols && *view->cols->cols ) + view->ifun->vcols = xstrdup(view->cols->cols); + if( view->fmt && *view->fmt->fmt ) + view->ifun->vfmt = xstrdup(view->fmt->fmt); + } + } + return 1; + } + else{ + return 0; + } +} + +/* + * + * public routines + * + */ + +/* + * + * FunView -- translate view into a filename + view params + * + */ +#ifdef ANSI_FUNC +int +FunView(Fun fun, char *vname, char *vmode, char *fname, int fmax) +#else +int +FunView(fun, vname, vmode, fname, fmax) + Fun fun; + char *vname; + char *vmode; + char *fname; + int fmax; +#endif +{ + int nev=0; + int got=0; + int dorow=FUN_VIEW_DOROW_DEFAULT; + char *s=NULL; + char *vptr=NULL; + char vlist[SZ_LINE]; + Row row=NULL; + View view=NULL; + + /* sanity checks */ + if( !fname || !fmax ) return 0; + *fname = '\0'; + if( !vname || !*vname ) return 0; + + /* assume we don't have a view */ + strncpy(fname, vname, fmax-1); + fname[fmax-1] = '\0'; + + /* sanity check -- this prevents infinite recusion below */ + if( !fun || (vmode && strchr(vmode, 'V')) ) return 0; + + /* see if a view ("v:...") was specified */ + memset(vlist, 0, SZ_LINE); + vptr = vname; + if( !*vptr || (*vptr != 'v') ) return 0; + vptr++; + if( !*vptr || (*vptr != ':') ) return 0; + vptr++; + if( !*vptr ) return 0; + /* v::vid1,vid2...:file... */ + if( (*vptr == ':') || (*vptr == '+') || (*vptr == '-') ){ + if( *vptr == '+' ) dorow = 1; + else if( *vptr == '-' ) dorow = 0; + vptr++; + /* must have a closing ':' */ + if( !*vptr || !(s = strchr(vptr, ':')) ) return 0; + /* copy the list */ + strncpy(vlist, vptr, MIN(s-vptr,SZ_LINE-1)); + /* bump past the ':' */ + vptr = s+1; + } + if( !*vptr ) return 0; + + /* now assume we don't match and want to use the supplied filename */ + strncpy(fname, vptr, fmax-1); + fname[fmax-1] = '\0'; + + /* open view file */ + if( !(view=ViewNew(fun, vname, vptr, vlist, NULL, 0)) ) goto done; + + /* read rows from view database */ + while( (row=FunTableRowGet(view->vfun, NULL, 1, NULL, &nev)) && nev ){ + /* look for a match */ + if( view->vlist ){ + if( ViewMatchList(view, row, dorow) ){ + ViewSaveRow(view, row); + /* clear row */ + row = NULL; + } + } + else{ + if( ViewMatchRow(view, row) ){ + ViewSaveRow(view, row); + /* clear row */ + row = NULL; + } + } + /* free record if it was not saved (and cleared) */ + if( row ){ + xfree(row); + row = NULL; + } + } + + /* process view information and generate a new file name */ + got = ViewProcessMatches(view, fname, fmax); + +done: + /* clean up */ + ViewFree(view); + if( row ) xfree(row); + + /* return the news */ + return got; +} |