diff options
Diffstat (limited to 'pkg/utilities/nttools/keyselect')
-rw-r--r-- | pkg/utilities/nttools/keyselect/expr.x | 193 | ||||
-rw-r--r-- | pkg/utilities/nttools/keyselect/keyselect.com | 9 | ||||
-rw-r--r-- | pkg/utilities/nttools/keyselect/keyselect.h | 17 | ||||
-rw-r--r-- | pkg/utilities/nttools/keyselect/keyselect.x | 122 | ||||
-rw-r--r-- | pkg/utilities/nttools/keyselect/keyword.x | 253 | ||||
-rw-r--r-- | pkg/utilities/nttools/keyselect/list.x | 215 | ||||
-rw-r--r-- | pkg/utilities/nttools/keyselect/mkpkg | 15 | ||||
-rw-r--r-- | pkg/utilities/nttools/keyselect/tab.x | 353 |
8 files changed, 1177 insertions, 0 deletions
diff --git a/pkg/utilities/nttools/keyselect/expr.x b/pkg/utilities/nttools/keyselect/expr.x new file mode 100644 index 00000000..fa7e5d31 --- /dev/null +++ b/pkg/utilities/nttools/keyselect/expr.x @@ -0,0 +1,193 @@ +include <evexpr.h> +include "keyselect.h" + +#* HISTORY * +#* B.Simon 12-Mar-1992 Original +#* Phil Hodge 4-Mar-2002 Free memory allocated by evexpr. + +# EVAL_EXPR -- Evaluate a boolean expression using image header keywords + +bool procedure eval_expr (im, expr) + +pointer im # i: image descriptor +char expr[ARB] # i: boolean expression +#-- +include "keyselect.com" + +pointer op, sp, errmsg + +string badtype "Expression is not of boolean type" +string badname "Warning: header keyword %s not found in %s\n" + +int errget() +pointer evexpr(), locpr() +extern fun_expr, var_expr + +begin + call smark (sp) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + img = im + iferr { + op = evexpr (expr, locpr(var_expr), locpr (fun_expr)) + + } then { + if (errget(Memc[errmsg], SZ_LINE) == ERR_SYNTAX) { + call xer_reset + call error (ERR_SYNTAX, Memc[errmsg]) + + } else { + call xer_reset + call eprintf ("Warning: %s\n") + call pargstr (Memc[errmsg]) + call mfree (op, TY_STRUCT) + + return (false) + } + } + + if (O_TYPE(op) != TY_BOOL) + call error (ERR_SYNTAX, badtype) + + call xev_freeop (op) + call mfree (op, TY_STRUCT) + call sfree (sp) + return (O_VALB(op)) +end + +# FMT_EXPR -- Format an expression to make it easier to parse + +procedure fmt_expr (expr) + +char expr[ARB] # i: expression +#-- +int ic, jc + +begin + # Find first non-white character + + for (ic = 1; expr[ic] != EOS; ic = ic + 1) { + if (expr[ic] > ' ') + break + } + + # Copy remaining characters, replacing newlines with blanks + + jc = 1 + for ( ; expr[ic] != EOS; ic = ic + 1) { + if (expr[ic] == '\n') { + expr[jc] = ' ' + } else if (jc < ic) { + expr[jc] = expr[ic] + } + jc = jc + 1 + } + + expr[jc] = EOS +end + +# FUN_EXPR -- Evaluate non-standard functions used in expression + +procedure fun_expr (func, argptr, nargs, op) + +char func[ARB] # i: function name +pointer argptr[ARB] # i: pointers to function arguments +int nargs # i: number of function arguments +pointer op # o: structure containing function value +#-- +include "keyselect.com" + +int arg +pointer sp, errmsg + +string flist "find" +string badfun "Unknown function name (%s)" +string badtyp "Invalid argument type for %s" + +int word_match(), imaccf() + +begin + call smark (sp) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + switch (word_match (func, flist)) { + case 0: # unrecognized function name + call sprintf (Memc[errmsg], SZ_LINE, badfun) + call pargstr (func) + call error (ERR_SYNTAX, Memc[errmsg]) + + case 1: # find keyword in header ? + call xev_initop (op, 0, TY_BOOL) + O_VALB(op) = true + + do arg = 1, nargs { + if (O_TYPE(argptr[arg]) != TY_CHAR) { + call sprintf (Memc[errmsg], SZ_LINE, badtyp) + call pargstr (func) + call error (ERR_SYNTAX, Memc[errmsg]) + } + + if (imaccf (img, O_VALC(argptr[arg])) == NO) + O_VALB(op) = false + } + } + + call sfree (sp) +end + +# VAR_EXPR -- Retrieve keyword used in expression + +procedure var_expr (name, op) + +char name[ARB] # i: keyword name +pointer op # o: structure containing value of variable +#-- +include "keyselect.com" + +int ic, dtype, type, length, junk +pointer sp, value + +string badname "Expression cannot be evaluated because keyword not found" + +bool streq() +int ctoi(), ctor() + +begin + call smark(sp) + call salloc (value, SZ_BIGCOL, TY_CHAR) + + # Retrieve keyword value from image header + + call get_keyword (img, name, dtype, Memc[value], SZ_BIGCOL) + + # Allocate structure to hold value + + if (dtype == 0) { + call error (ERR_NOFIND, badname) + } else if (dtype < 0) { + type = TY_CHAR + length = - dtype + } else { + type = dtype + length = 0 + } + + call xev_initop (op, length, type) + + # Copy value to structure + + switch (type) { + case TY_BOOL: + O_VALB(op) = streq (Memc[value], "yes") + case TY_CHAR: + call strcpy (Memc[value], O_VALC(op), length) + case TY_SHORT,TY_INT,TY_LONG: + ic = 1 + junk = ctoi (Memc[value], ic, O_VALI(op)) + case TY_REAL,TY_DOUBLE: + ic = 1 + junk = ctor (Memc[value], ic, O_VALR(op)) + } + + call sfree(sp) +end diff --git a/pkg/utilities/nttools/keyselect/keyselect.com b/pkg/utilities/nttools/keyselect/keyselect.com new file mode 100644 index 00000000..fc0e63b5 --- /dev/null +++ b/pkg/utilities/nttools/keyselect/keyselect.com @@ -0,0 +1,9 @@ +# KEYSELECT.COM -- Global variables used by keyselect + +#* HISTORY * +#* B.Simon 12-Mar-92 Original + +common /global/ hasgroup, img + +bool hasgroup # true if image has group parameters +pointer img # image descriptor diff --git a/pkg/utilities/nttools/keyselect/keyselect.h b/pkg/utilities/nttools/keyselect/keyselect.h new file mode 100644 index 00000000..ef001849 --- /dev/null +++ b/pkg/utilities/nttools/keyselect/keyselect.h @@ -0,0 +1,17 @@ +# KEYSELECT.H -- Global constants used by keyselect + +#* HISTORY * +#* B.Simon 12-Mar-92 Original + +define SZ_STRCOL 19 +define SZ_BIGCOL 63 + +define ERR_SYNTAX 1 +define ERR_NOFIND 2 + +define ASSIGN_CHAR '=' +define CONCAT_CHAR ':' +define SEP_CHAR ',' + +define IS_SEP ($1 <= ' ' || $1 == ',') + diff --git a/pkg/utilities/nttools/keyselect/keyselect.x b/pkg/utilities/nttools/keyselect/keyselect.x new file mode 100644 index 00000000..2bc8a72e --- /dev/null +++ b/pkg/utilities/nttools/keyselect/keyselect.x @@ -0,0 +1,122 @@ +# KEYSELECT -- Copy selected image header keywords to sdas table + +#* HISTORY * +#* B.Simon 12-Mar-1992 Original +# Phil Hodge 8-Apr-1999 Call tbfpri. + +procedure keyselect () + +#-- +include "keyselect.com" + +pointer input # list of image names +pointer output # sdas table name +pointer cols # list of keyword and table column names +pointer expr # boolean expression used to select images +pointer cdfile # column description file + +bool first +int ngroup +int phu_copied # set by tbfpri and ignored +pointer sp, keywords, columns, cluster, image +pointer imlist, grplist, colptr, im, tp + +string noread "No images read. Output table not created." + +bool tp_fetch(), eval_expr() +int imtgetim() +pointer imtopen(), immap(), tp_open(), op_table() + +begin + # Allocate dynamic memory for strings + + call smark(sp) + call salloc (input, SZ_FNAME, TY_CHAR) + call salloc (output, SZ_FNAME, TY_CHAR) + call salloc (cols, SZ_COMMAND, TY_CHAR) + call salloc (expr, SZ_COMMAND, TY_CHAR) + call salloc (cdfile, SZ_FNAME, TY_CHAR) + + call salloc (keywords, SZ_COMMAND, TY_CHAR) + call salloc (columns, SZ_COMMAND, TY_CHAR) + call salloc (cluster, SZ_FNAME, TY_CHAR) + call salloc (image, SZ_FNAME, TY_CHAR) + + # Read task parameters + + call clgstr ("input", Memc[input], SZ_FNAME) + call clgstr ("output", Memc[output], SZ_FNAME) + call clgstr ("cols", Memc[cols], SZ_FNAME) + call clgstr ("expr", Memc[expr], SZ_FNAME) + call clgstr ("cdfile", Memc[cdfile], SZ_FNAME) + + # If keyword list or expression is contained in a file, read the file + + if (Memc[cols] == '@') + call rd_list (Memc[cols+1], Memc[cols], SZ_COMMAND) + call fmt_list (Memc[cols]) + + if (Memc[expr] == '@') + call rd_list (Memc[expr+1], Memc[expr], SZ_COMMAND) + call fmt_expr (Memc[expr]) + + # Separate out the header keyword and table column names + + call sep_list (Memc[cols], Memc[keywords], Memc[columns], SZ_COMMAND) + + # Loop over all images and all groups in image + + first = true + imlist = imtopen (Memc[input]) + + while (imtgetim (imlist, Memc[cluster], SZ_FNAME) != EOF) { + + # Hasgroup is set to true to get us through the loop the + # first time. It then is set to false, but can be set to + # true if either eval_expr() or cpy_table() accesses a + # group parameter. + + hasgroup = true + grplist = tp_open (Memc[cluster], 0, ngroup) + + while (hasgroup && tp_fetch (grplist, Memc[image])) { + im = immap (Memc[image], READ_ONLY, 0) + hasgroup = false + + # Open output table first time through loop + + if (first) { + first = false + call tbfpri (Memc[cluster], Memc[output], phu_copied) + tp = op_table (im, Memc[output], Memc[keywords], + Memc[columns], Memc[cdfile]) + call rd_table (Memc[columns], tp, colptr) + } + + # Copy keywords from header to table if expression is true + + if (Memc[expr] == EOS) { + call cpy_table (im, tp, colptr, Memc[keywords]) + } else if (eval_expr (im, Memc[expr])) { + call cpy_table (im, tp, colptr, Memc[keywords]) + } + + call imunmap (im) + } + call tp_close (grplist) + } + + # Close files and release memory + + call imtclose (imlist) + call sfree(sp) + + if (first) { + call eprintf (noread) + + } else { + call mfree (colptr, TY_POINTER) + call tbtclo (tp) + } + +end diff --git a/pkg/utilities/nttools/keyselect/keyword.x b/pkg/utilities/nttools/keyselect/keyword.x new file mode 100644 index 00000000..b360e7cd --- /dev/null +++ b/pkg/utilities/nttools/keyselect/keyword.x @@ -0,0 +1,253 @@ +include <imio.h> +include <imhdr.h> +include "keyselect.h" + +#* HISTORY * +#* B.Simon 12-Mar-92 Original + +# GET_KEYWORD -- Get the keyword from the image header + +procedure get_keyword (im, name, dtype, value, maxch) + +pointer im # i: image descriptor +char name[ARB] # i: keyword name +int dtype # o: keyword data type +char value[ARB] # o: keyword value +int maxch # i: maximum length of value string +#-- +include "keyselect.com" + +string badname "Warning: header keyword %s not found in %s\n" + +int imgftype(), gf_gfind() + +begin + # Any name beginning with a $ is a special keyword + + if (name[1] == '$') { + call spec_keyword (im, name, dtype, value, maxch) + + } else { + # Get the data type of the header keyword + # If the keyword is not found set the data type to + # zero to indicate this and return + + iferr { + dtype = imgftype (im, name) + } then { + call eprintf (badname) + call pargstr (name) + call pargstr (IM_HDRFILE(im)) + + dtype = 0 + value[1] = EOS + return + } + + if (dtype == TY_SHORT || dtype == TY_LONG) + dtype = TY_INT + if (dtype == TY_CHAR) + dtype = - maxch + + # Read header keyword from image. This procedure sets hasgroup + # to true if asked to retrieve a group parameter + + call imgstr (im, name, value, maxch) + if (dtype == TY_BOOL) { + if (value[1] == 'T') { + call strcpy ("yes", value, maxch) + } else { + call strcpy ("no", value, maxch) + } + } + + if (gf_gfind (im, name) > 0) + hasgroup = true + } + +end + +# NAME_KEYWORD -- Retrieve the default column name for a special keyword + +procedure name_keyword (name, colname, maxch) + +char name[ARB] # i: keyword name +char colname[ARB] # o: default column name +int maxch # i: maximum length of column name +#-- +int idx, junk +pointer sp, errmsg + +string special "group,dir,ext,hdr,pix,root" +string defaults "group,directory,extension,header_file,data_file,rootname" +string badname "Name for special keyword not recognized (%s)" + +int word_match(), word_find() + +begin + call smark (sp) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + if (name[1] != '$') { + call strcpy (name, colname, maxch) + return + } + + # Get the index of special keyword name in the list + # The find the corresponding name in the list of defaults + + idx = word_match (name[2], special) + if (idx == 0) { + call sprintf (Memc[errmsg], SZ_LINE, badname) + call pargstr (name) + call error (1, Memc[errmsg]) + } else { + junk = word_find (idx, defaults, colname, maxch) + } + + call sfree (sp) +end + +# SPEC_KEYWORD -- Get the value of a special keyword + +procedure spec_keyword (im, name, dtype, value, maxch) + +pointer im # i: image descriptor +char name[ARB] # i: keyword name +int dtype # o: keyword data type +char value[ARB] # o: keyword value +int maxch # i: maximum length of value string +#-- +include "keyselect.com" + +int match, ival, junk +pointer sp, image, ldir, root, errmsg, hdr, ext + +string int_special "group" +string str_special "dir,ext,hdr,pix,root" + +string badname "Name for special keyword not recognized (%s)" +string badimgext "Image extension not recognized (%s)" + +bool streq() +int word_match(), fnldir(), fnroot(), itoc() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (ldir, SZ_FNAME, TY_CHAR) + call salloc (root, SZ_FNAME, TY_CHAR) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + # Search lists for special keyword + + match = - word_match (name[2], int_special) + if (match == 0) + match = word_match (name[2], str_special) + + # Data type is determined from which list it is on + + if (match < 0) { + dtype = TY_INT + } else if (match > 0) { + dtype = - maxch + } else { + call sprintf (Memc[errmsg], SZ_LINE, badname) + call pargstr (name) + call error (1, Memc[errmsg]) + } + + # Break image name into its component parts + + if (match > 0) { + call imgcluster (IM_HDRFILE(im), Memc[image], SZ_FNAME) + + hdr = image + fnldir (Memc[image], Memc[ldir], SZ_FNAME) + ext = hdr + 1 + fnroot (Memc[hdr], Memc[root], SZ_FNAME) + } + + + # Get value of special keyword + + switch (match) { + case -1: + # group number $group + hasgroup = true + ival = max (1, IM_CLINDEX(im)) + junk = itoc (ival, value, maxch) + case 0: + # (not used) + ; + case 1: + # directory name $dir + call strcpy (Memc[ldir], value, maxch) + case 2: + # extension $ext + call strcpy (Memc[ext], value, maxch) + case 3: + # header file name $hdr + call strcpy (Memc[hdr], value, maxch) + case 4: + # pixel file name $pix + if (Memc[ext+2] != 'h' || Memc[ext+3] != EOS) { + call sprintf (Memc[errmsg], SZ_LINE, badimgext) + call pargstr (Memc[hdr]) + call error (1, Memc[errmsg]) + } + + call strcpy (Memc[root], value, maxch) + if (streq (Memc[ext], "imh")) { + call strcat (".pix", value, maxch) + } else { + Memc[ext+2] = 'd' + call strcat (".", value, maxch) + call strcat (Memc[ext], value, maxch) + } + case 5: + # root name $root + call strcpy (Memc[root], value, maxch) + } + + call sfree (sp) +end + +# TYPE_KEYWORD -- Retrieve the type of a special keyword + +int procedure type_keyword (name) + +char name[ARB] # i: special keyword name +#-- +int dtype +pointer sp, errmsg + +string int_special "group" +string str_special "dir,ext,hdr,pix,root" +string badname "Name for special keyword not recognized (%s)" + +int word_match() + +begin + call smark (sp) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + if (name[1] != '$') { + call sprintf (Memc[errmsg], SZ_LINE, badname) + call pargstr (name) + call error (1, Memc[errmsg]) + + } else if (word_match (name[2], int_special) > 0) { + dtype = TY_INT + + } else if (word_match (name[2], str_special) > 0) { + dtype = TY_CHAR + + } else { + call sprintf (Memc[errmsg], SZ_LINE, badname) + call pargstr (name) + call error (1, Memc[errmsg]) + } + + call sfree (sp) + return (dtype) +end + diff --git a/pkg/utilities/nttools/keyselect/list.x b/pkg/utilities/nttools/keyselect/list.x new file mode 100644 index 00000000..b25e1a7e --- /dev/null +++ b/pkg/utilities/nttools/keyselect/list.x @@ -0,0 +1,215 @@ +include "keyselect.h" + +#* HISTORY * +#* B.Simon 12-Mar-92 Original + +# BRK_LIST -- Retrieve a string from the list + +int procedure brk_list (list, ic, sep, str, maxch) + +char list[ARB] # i: list of items +int ic # u: index into list +char sep # i: character separating strings in the list +char str[ARB] # o: output string +int maxch # i: maximum length of output string +#-- +int jc + +begin + # Copy characters into output string until separation character + # or end of list is found + + for (jc = 1; jc <= maxch; jc = jc + 1) { + str[jc] = list[ic] + ic = ic + 1 + + if (str[jc] == sep) { + break + } else if (str[jc] == EOS) { + ic = ic - 1 # back up to EOS character + break + } + } + + str[jc] = EOS + return (jc-1) +end + +# CNT_LIST -- Count the number of items in a list + +int procedure cnt_list (list) + +char list[ARB] # i: list of items +#-- +int ic, count + +begin + # Number of items is number of separation characters plus one + + count = 1 + for (ic = 1; list[ic] != EOS; ic = ic + 1) { + if (list[ic] == SEP_CHAR) + count = count + 1 + } + + return (count) +end + +# FMT_LIST -- Format a list into canonical form + +procedure fmt_list (list) + +char list[ARB] # u: list of keyword names +#-- +bool tween +int ic, jc + +begin + jc = 1 + tween = true + + # Eliminate consecutive separation characters between list items + + for (ic = 1; list[ic] != EOS; ic = ic + 1) { + if (IS_SEP(list[ic])) { + if (! tween) { + tween = true + list[jc] = SEP_CHAR + jc = jc + 1 + } + + } else { + tween = false + if (jc < ic) + list[jc] = list[ic] + jc = jc + 1 + } + } + + # Eliminate trailing separation character + + if (! tween || jc == 1) { + list[jc] = EOS + } else { + list[jc-1] = EOS + } + +end + +# RD_LIST -- Read values from a file into a list + +procedure rd_list (fname, list, maxch) + +char fname[ARB] # i: file containing list +char list[ARB] # o: output list +int maxch # i: maximum length of list +#-- +int fd, ic, nc + +int open(), getline() + +begin + # Concatenate contents of the file into a single long string + # while preserving the newlines between them + + fd = open (fname, READ_ONLY, TEXT_FILE) + + for (ic = 1; ic < maxch; ic = ic + nc) { + nc = getline (fd, list[ic]) + if (nc <= 0) + break + } + + list[ic] = EOS + call close (fd) + +end + +# SEP_LIST -- Separate list into keywords and table column names + +procedure sep_list (list, keywords, columns, maxch) + +char list[ARB] # i: combined list of columns and keywords +char keywords[ARB] # o: list of header keyword names +char columns[ARB] # o: list of table column names +int maxch # i: declared length of output strings +#-- +char eq, sep, cat +int ic, jc, kc, mc, nc +pointer sp, word, key, col + +data eq / ASSIGN_CHAR / +data sep / SEP_CHAR / +data cat / CONCAT_CHAR / + +string nolist "List of header keywords is empty. No table created." + +int stridx(), gstrcpy(), brk_list() + +begin + call smark(sp) + call salloc (word, SZ_LINE, TY_CHAR) + call salloc (key, SZ_LINE, TY_CHAR) + call salloc (col, SZ_LINE, TY_CHAR) + + ic = 1 + jc = 1 + kc = 1 + + # Extract the next item from the combined list of columns and keywords + + while (brk_list (list, ic, sep, Memc[word], SZ_LINE) > 0) { + + # Break the item into the column and keyword names + # If both are not given in the item assume they are the same + + nc = stridx (eq, Memc[word]) + if (nc > 0) { + Memc[word+nc-1] = EOS + call strcpy (Memc[word], Memc[col], SZ_LINE) + call strcpy (Memc[word+nc], Memc[key], SZ_LINE) + + } else { + call strcpy (Memc[word], Memc[col], SZ_LINE) + call strcpy (Memc[word], Memc[key], SZ_LINE) + + # Translate keyword names into their default column names + # and substitute underscores for the concatenation char + + if (Memc[col] == '$') { + call name_keyword (Memc[col], Memc[col], SZ_LINE) + + } else { + repeat { + mc = stridx (cat, Memc[col]) + if (mc == 0) + break + + Memc[col+mc-1] = '_' + } + } + } + + # Append keyword and column name to output string + + jc = jc + gstrcpy (Memc[key], keywords[jc], maxch-jc) + keywords[jc] = SEP_CHAR + jc = jc + 1 + + kc = kc + gstrcpy (Memc[col], columns[kc], maxch-kc) + columns[kc] = SEP_CHAR + kc = kc + 1 + } + + # Exit with error if either list is empty + + if (jc == 1 || kc == 1) + call error (1, nolist) + + # Eliminate trailing separation character + + keywords[jc-1] = EOS + columns[kc-1] = EOS + + call sfree(sp) +end diff --git a/pkg/utilities/nttools/keyselect/mkpkg b/pkg/utilities/nttools/keyselect/mkpkg new file mode 100644 index 00000000..d22d2201 --- /dev/null +++ b/pkg/utilities/nttools/keyselect/mkpkg @@ -0,0 +1,15 @@ +# Update the keyselect application code in the ttools package library +# Author: B.Simon, 12-Mar-92 + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +libpkg.a: + expr.x <evexpr.h> "keyselect.h" + keyselect.x "keyselect.com" + keyword.x <imio.h> <imhdr.h> "keyselect.h" "keyselect.com" + list.x "keyselect.h" + tab.x <imhdr.h> <tbset.h> "keyselect.h" + ; diff --git a/pkg/utilities/nttools/keyselect/tab.x b/pkg/utilities/nttools/keyselect/tab.x new file mode 100644 index 00000000..1e4dd769 --- /dev/null +++ b/pkg/utilities/nttools/keyselect/tab.x @@ -0,0 +1,353 @@ +include <imhdr.h> +include <tbset.h> +include "keyselect.h" + +#* HISTORY * +#* B.Simon 12-Mar-92 Original + +# CPY_TABLE -- Copy keywords from header to table row + +procedure cpy_table (im, tp, colptr, keywords) + +pointer im # i: image descriptor +pointer tp # i: table descriptor +pointer colptr # i: pointer to array of column descriptors +char keywords # i: list of header keywords +#-- +char cat, sep +int row, dtype, ic, jc, kc +pointer sp, cp, nlist, vlist, name, value + +data cat / CONCAT_CHAR / +data sep / SEP_CHAR / + +string nocolumn "cpy_table: not enough columns to store keywords" + +int tbpsta(), brk_list(), stridx(), gstrcpy() + +begin + call smark(sp) + call salloc (nlist, SZ_LINE, TY_CHAR) + call salloc (vlist, SZ_LINE, TY_CHAR) + call salloc (name, SZ_LINE, TY_CHAR) + call salloc (value, SZ_LINE, TY_CHAR) + + ic = 1 + cp = colptr + row = tbpsta (tp, TBL_NROWS) + 1 + + # Extract each keyword from the list of keywords + + while (brk_list (keywords, ic, sep, Memc[nlist], SZ_LINE) > 0) { + + # If the keyword is not a list of concatenated keywords + # copy its value into a string + + if (stridx (cat, Memc[nlist]) == 0) { + call get_keyword (im, Memc[nlist], dtype, + Memc[vlist], SZ_LINE) + + # Otherwise break the list of concatenated keywords + # and concatenate their values into a string + + } else { + jc = 1 + kc = 0 + while (brk_list (Memc[nlist], jc, cat, + Memc[name], SZ_LINE) > 0){ + + call get_keyword (im, Memc[name], dtype, + Memc[value], SZ_LINE) + + if (dtype != 0) { + kc = kc + gstrcpy (Memc[value], Memc[vlist+kc], + SZ_LINE-kc) + Memc[vlist+kc] = SEP_CHAR + kc = kc + 1 + } + } + kc = max (kc, 1) + Memc[vlist+kc-1] = EOS + } + + # Write the value into the table + + if (Memi[cp] == NULL) + call error (1, nocolumn) + + call tbeptt (tp, Memi[cp], row, Memc[vlist]) + cp = cp + 1 + } + + call sfree(sp) +end + +# FMT_TABLE -- Retrieve column format from column description file + +procedure fmt_table (cd, col, units, fmt, dtype) + +int cd # i: file descriptor of column description file +char col[ARB] # i: name of column to retrieve information for +char units[ARB] # o: column units +char fmt[ARB] # o: column format +int dtype # o: column data type +#-- +char star, comment +bool match +int idx, junk, length, typevals[5] +pointer sp, line, input, name, type, ftnfmt, errmsg + +string typestr "rdibc" +string badtype "Illegal datatype for column %s (%s)" +string badname "Warning: column not found in column description file (%s)\n" + +data star / '*' / +data comment / '#' / +data typevals /TY_REAL, TY_DOUBLE, TY_INT, TY_BOOL, TY_CHAR / + +bool streq() +int getline(), stridx(), ctoi + +begin + call smark (sp) + call salloc (line, SZ_LINE, TY_CHAR) + call salloc (input, SZ_COLNAME, TY_CHAR) + call salloc (name, SZ_COLNAME, TY_CHAR) + call salloc (type, SZ_COLFMT, TY_CHAR) + call salloc (ftnfmt, SZ_COLFMT, TY_CHAR) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + call strcpy (col, Memc[input], SZ_COLNAME) + call strlwr (Memc[input]) + + match = false + call seek (cd, BOF) + while (! match && getline (cd, Memc[line]) != EOF) { + + # Remove trailing comments from line + + idx = stridx (comment, Memc[line]) + if (idx > 0) + Memc[line+idx-1] = EOS + + # Column name is the first word on the line + + call sscan (Memc[line]) + call gargwrd (Memc[name], SZ_COLNAME) + call strlwr (Memc[name]) + + # If the name matches the procedure argument + # read the remaining fields on the line + + match = streq (Memc[input], Memc[name]) + if (match) { + call gargwrd (Memc[type], SZ_COLFMT) + call gargwrd (Memc[ftnfmt], SZ_COLFMT) + call gargwrd (units, SZ_COLUNITS) + + call strlwr (Memc[type]) + call tbbftp (Memc[ftnfmt], fmt) + + # Convert the type string to the corresponding integer value + + if (Memc[type] == EOS) { + dtype = 0 + + } else { + idx = stridx (Memc[type], typestr) + if (idx == 0) { + call sprintf (Memc[errmsg], SZ_LINE, badtype) + call pargstr (Memc[name]) + call pargstr (Memc[type]) + call error (1, Memc[errmsg]) + } + + dtype = typevals[idx] + if (dtype == TY_CHAR) { + idx = stridx (star, Memc[type]) + if (idx > 0) { + idx = idx + 1 + junk = ctoi (Memc[type], idx, length) + if (length > 0) + dtype = - length + } + } + } + + } + } + + # Send warning message and set defaults if no match + + if (! match) { + dtype = 0 + fmt[1] = EOS + units[1] = EOS + + call eprintf (badname) + call pargstr (col) + } + + call sfree (sp) +end + +# OP_TABLE -- Open the output table + +pointer procedure op_table(im, output, keywords, columns, cdfile) + +pointer im # i: image descriptor +char output[ARB] # i: table name +char keywords[ARB] # i: list of header keywords +char columns[ARB] # i: list of column names +char cdfile[ARB] # i: optional column description file +#-- +bool append +char sep, cat +int ic, jc, dtype +pointer sp, tp, cp, cd, col, key, units, fmt, errmsg + +data sep / SEP_CHAR / +data cat / CONCAT_CHAR / + +string nocolumn "Column not found in existing output table (%s)" +string nokeyword "op_table: no matching keyword for column" +string notfound "Warning: keyword not found when creating table (%s)\n" + +bool isblank() +int open(), stridx(), imgftype(), brk_list(), type_keyword() +pointer tbtopn() + +begin + call smark (sp) + call salloc (col, SZ_COLNAME, TY_CHAR) + call salloc (key, SZ_LINE, TY_CHAR) + call salloc (units, SZ_COLUNITS, TY_CHAR) + call salloc (fmt, SZ_COLFMT, TY_CHAR) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + # Open column description file + + if (isblank (cdfile)) { + cd = NULL + } else { + cd = open (cdfile, READ_ONLY, TEXT_FILE) + } + + # Append rows to the table if the table already exists + # otherwise create a new table + + append = true + iferr (tp = tbtopn (output, READ_WRITE, NULL)) { + append = false + tp = tbtopn (output, NEW_FILE, NULL) + } + + ic = 1 + jc = 1 + while (brk_list (columns, ic, sep, Memc[col], SZ_COLNAME) > 0) { + + if (brk_list (keywords, jc, sep, Memc[key], SZ_LINE) == 0) + call error (1, nokeyword) + + # Verify that the columns exist if we are in append mode + # Define the new columns if we are not + + if (append) { + call tbcfnd (tp, Memc[col], cp, 1) + if (cp == NULL) { + call sprintf (Memc[errmsg], SZ_LINE, nocolumn) + call pargstr (Memc[col]) + call error (1, Memc[errmsg]) + } + + } else { + # Get column characteristics from the column description file + # or use defaults and image header keyword type + + if (cd != NULL) + call fmt_table (cd, Memc[col], + Memc[units], Memc[fmt], dtype) + + if (cd == NULL || dtype == 0) { + Memc[units] = EOS + Memc[fmt] = EOS + + if (stridx (cat, Memc[key]) != 0) { + dtype = - SZ_BIGCOL + + } else if (Memc[key] == '$'){ + dtype = type_keyword (Memc[key]) + + } else { + iferr { + dtype = imgftype (im, Memc[key]) + } then { + dtype = 0 + call eprintf (notfound) + call pargstr (Memc[key]) + } + } + } + + if (dtype == 0 || dtype == TY_CHAR) + dtype = - SZ_STRCOL + if (dtype == TY_SHORT || dtype == TY_LONG) + dtype = TY_INT + if (dtype == TY_REAL) + dtype = TY_DOUBLE + + call tbcdef (tp, cp, Memc[col], Memc[units], Memc[fmt], + dtype, 1, 1) + } + } + + # Create the new table if not in append mode + + if (! append) + call tbtcre (tp) + + call sfree (sp) + return (tp) +end + +# RD_TABLE -- Create an array of column pointers from the list of column names + +procedure rd_table (columns, tp, colptr) + +char columns[ARB] # i: list of column names +pointer tp # i: table descriptor +pointer colptr # o: pointer to array of column names +#-- +char sep +int nptr, ic +pointer sp, cp, col, errmsg + +data sep / SEP_CHAR / +string nocolumn "rd_table: column not found (%s)" + +int cnt_list(), brk_list() + +begin + call smark (sp) + call salloc (col, SZ_LINE, TY_CHAR) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + nptr = cnt_list (columns) + 1 + call malloc (colptr, nptr, TY_POINTER) + + ic = 1 + cp = colptr + while (brk_list (columns, ic, sep, Memc[col], SZ_LINE) > 0) { + call tbcfnd (tp, Memc[col], Memi[cp], 1) + if (cp == NULL) { + call sprintf (Memc[errmsg], SZ_LINE, nocolumn) + call pargstr (Memc[col]) + + call error (1, Memc[errmsg]) + } + cp = cp + 1 + } + + Memi[cp] = NULL + call sfree(sp) +end |