summaryrefslogtreecommitdiffstats
path: root/funtools/funview.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-25 20:57:49 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-25 20:57:49 (GMT)
commitd1c4bf158203c4e8ec29fdeb83fd311e36320885 (patch)
tree15874534e282f67505ce4af5ba805a1ff70ec43e /funtools/funview.c
parente19a18e035dc4d0e8e215f9b452bb9ef6f58b9d7 (diff)
parent339420dd5dd874c41f6bab5808291fb4036dd022 (diff)
downloadblt-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.c632
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;
+}