diff options
Diffstat (limited to 'sys/imio/imt')
-rw-r--r-- | sys/imio/imt/README | 280 | ||||
-rw-r--r-- | sys/imio/imt/fxf.h | 172 | ||||
-rw-r--r-- | sys/imio/imt/imt.x | 342 | ||||
-rw-r--r-- | sys/imio/imt/imx.h | 28 | ||||
-rw-r--r-- | sys/imio/imt/imx.x | 242 | ||||
-rw-r--r-- | sys/imio/imt/imxbreakout.x | 233 | ||||
-rw-r--r-- | sys/imio/imt/imxescape.x | 74 | ||||
-rw-r--r-- | sys/imio/imt/imxexpand.x | 1287 | ||||
-rw-r--r-- | sys/imio/imt/imxexpr.x | 222 | ||||
-rw-r--r-- | sys/imio/imt/imxftype.x | 119 | ||||
-rw-r--r-- | sys/imio/imt/imxparse.x | 203 | ||||
-rw-r--r-- | sys/imio/imt/imxpreproc.x | 539 | ||||
-rw-r--r-- | sys/imio/imt/mkpkg | 24 | ||||
-rw-r--r-- | sys/imio/imt/t_urlget.x | 94 | ||||
-rw-r--r-- | sys/imio/imt/zzdebug.x | 227 |
15 files changed, 4086 insertions, 0 deletions
diff --git a/sys/imio/imt/README b/sys/imio/imt/README new file mode 100644 index 00000000..be232470 --- /dev/null +++ b/sys/imio/imt/README @@ -0,0 +1,280 @@ + + Enhanced Image List Template Package + + April 15, 2011 + + + The enhanced image list package provides new capabilities for handling +image lists, but remains backwards compatible with tasks currently using +the IMT interface. The enhancements allow for expansion of MEF files into +lists of extensions using the @-file operator, as well as selection of +images within more general lists by means of modifiers (e.g. a simple +expression such as the extname/extver or explicit extension number, or more +complex boolean expressions to allow selection by header keyword). In +addition, tables may now take the @-file operator to use a column +containing image references as an input list. + + +======================================================================== +TODO: + - Describe syntax for use with tables and selection by row values + - Describe remote image specification caching mechanism +======================================================================== + + + +Template Strings +---------------- + +The FNT template package supports the following forms of pattern strings: + + alpha, *.x, data* // .pix, [a-m]*, @list_file, nite%1%2%.1024.imh + +i.e. simple filenames, wildcard expansion in filenames, concatenation of +filenames, @files, substitution in filenames, or a comma-delimited list of +the above. The image template package (IMT) extends these patterns to +allow image names followed by a cluster index or image section in [] +brackets. These patterns remain unchanged in the new version of the +package to allow backward compatability with existing applications. Lists +of these types represent *explicit* collections of images, i.e. a +collection based on the image name (wildcards) or as a result of processing +by some task (e.g. expansion of an MEF file to create an input @-file of +expanded extension specifications). + + The enhanced version of the IMT package further abstracts the concept +of image collections to include data objects such as MEF files or tables +containing a list of image references that *implicitly* defines the list +(e.g. the expanded MEF extension specification or the complete column of +image references). Further, we allow this list (which might be quite +broad) to be refined using modifiers or selectors on the list and thus +dynamically create the list without requiring the use (and management) of +intermediate files. For example, + + + @file* expand all files beginning w/ 'file' + @file//".fits" append ".fits" to contents of 'file' + + @mef.fits expand all (image) extensions of an MEF file + @mef.fits[SCI] select SCI extensions from MEF file + @mef.fits[SCI,2][noinherit] select v2 SCI extns, add kernel param + @mef.fits[1-16x2] select range of extensions from MEF file + @mef.fits[+1-8] create a list of extensions for an MEF + + *.fits[1:100,1:100] append section to all FITS images + @@file[1:100,1:100] append section to expanded MEFs in 'file' + + *.fits[filter?='V'] select images w/ FILTER keyword containing 'V' + @*.fits[gain<3.0] select image extns where GAIN keyword < 3.0 + *.fits[filter?='V';gain<2.0] select using multiple OR's expressions + + +Template Syntax +--------------- + + The previous syntax and behavior of image templates is unchanged in +this version, new functionality is provided by (optional) new syntax now +supported in the template pattern string. Briefly, + + - wildcard filename expansion may now be applied to @-files + + - the use of an '@' operator is now permitted on MEF files. By + default, all image extensions in the file will be included in the + list, modifiers may be used to select specific extensions or to + indicate a range of extensions to be used. + + - the use of an '@@' operator to indicate expansion of the contents + of an @-file. For example, an @-file of MEF image names can be + expanded to list of all the file extensions using "@@file", whereas + just using "@file" would list the names of the MEF files as before. + + - modifier expressions enclosed in square brackets may be appended + to an image template string (or @-file) to either constrain the + list (e.g. only a range of MEF extensions, only images with a certain + keyword value, etc) or to append extra information to the image + specification (e.g. to add an image section to all images in the + list). Multiple modifier expressions may be used + + + The allowed syntax for a template string can be described roughly in +the following way: + + + [@@ | @] <file> [extname] [<expr>;...] [<ikparams>] [<section>] + [@@ | @] <file> [extname,extver][<expr>;...] [<ikparams>] [<section>] + [@@ | @] <file> [index_range] [<expr>;...] [<ikparams>] [<section>] + + <-------- selectors -------> <------ modifiers -----> + + The <file> specification may be the name of a file, and image, or a +table. The behavior of the @-file and @@-file operators will depend on +the type of <file> but the @-file usage remains backward compatible when +used with text files. + + The use of a modifier/selection on an MEF file will automatically +trigger expansion of the extensions in the image and so an '@' operator is +not strictly required, however only those extensions matching the selection +expression will be present in the final image list. Note that the use of +index ranges and extname/extver selectors are mutually exclusive, selector +expressions may be added to either. + + +@-file Operations +----------------- + + The @-file operator is unchanged from previous versions when used with +text files of image names. Modifier/selector expressions however can now +be applied to the contents of the @-file to select from the list only those +images that match the selector expression, or to augment the name in the +list with an additional image syntax such as a section or kernel parameters. + + +@@-file Operations +------------------ + + The @@-file operator is new syntax meant to allow the contents of an +@-file to be expanded automaticaly, e.g. as if there were an @-file of +@-file names. Primarily this can be used to create a list of MEF image +names in which an @-file would return the names of the MEF, while the +@@-file syntax could be used to expand each MEF into individual extension +specifications. + + +Extension Indices +----------------- + + The [index_range] modifier may be used to specify an explicit set of +extensions to be used. Index ranges are specified as a comma-delimited +list of strings specifying individual range segments as described in the +RANGES help page. + + The use of a '+' operator before an index range indicates the range +list should be expanded without checking that the extension exists in the +MEF itself. Otherwise, only those extensions present in the MEF will be +included in the list. + + +Selection Expressions +--------------------- + + Selection expressions may be used to restrict a template list to only +those images that match some boolean expression, e.g. to provide for +selection based on a header keyword value. Expressions follow the same +guidelines as in the HSELECT task 'expr' parameter (see the help page +for details). Multiple expressions may be specified if they are separated +by a semicolon however they are evaluated as a single expression of +OR'd values rather than as individual expressions. This is significant +when considering that expressions may contain keywords not present in +all images being checked, for instance + + *.fits[filter?='V';gain<3.0] + +would evaluate as if the expression had been written + + (filter?='V' || gain < 3.0) + +If a particular image lacks either the 'filter' or 'gain' keyword the +entire expression will evaluate to false because of an error even if one +of the two clauses would otherwise have been true. + +[NOTE: This behavior will be changed in a future version.] + + + +Image Sections +-------------- + Image sections may be added to an image specification by adding a +separate modifier string. The section will be added once selection of +the list by the selector expressions is complete. An example of where +this might be used is in automatically specifying the bias section for +all images in a list, e.g. + + @mef.fits[1:128,*] all extensions in the image + @mef.fits[1-16x2][1:128,*] only 'left' amplifiers of a mosaic + @mef.fits[2-16x2][1024:1128,*] only 'right' amplifiers of a mosaic + m31*.fits[345:528,200:300] same section in all registered images + +No check is made that the image section is valid for the given image. + + +Kernel Parameters +----------------- + + A comma-delimited list of image kernel parameters may be added to any +image specification by adding the keywords to a separate modifier. For +example, + @mef.fits[1-8][noinherit,padline=30] + +would expand the file 'mef.fits' to include extensions 1 thru 8 and add the +kernel parameters, generating a list such as + + mef.fits[1][noinherit,padline=30] + mef.fits[2][noinherit,padline=30] + : : : : + mef.fits[8][noinherit,padline=30] + +No check is made to verify that the image kernel keywords are appropriate +for the image type. Supplying an incorrect kernel parameter will likely +result in the task throwing an error when opening the image. + + + +-------------------------------------------------------------------------------- + +Appendix 1: Examples + + file + file* + @file + @file* + + @file[2] extension + @file[SCI] extname + @file[SCI,2] extname+extver + + @file[2][noinherit] extension + ikiparams + @file[SCI][noinherit] extname + ikiparams + @file[SCI,2][noinherit] extname+extver + ikiparams + + @file[2][1:20,2:30] extension + section + @file[SCI][1:20,2:30] extname + section + @file[SCI,2][1:20,2:30] extname+extver + section + + @file[2][noinherit][1:20,2:30] extension + ikiparams + section + @file[SCI][noinherit][1:20,2:30] extname + ikiparams + section + @file[SCI,2][noinherit][1:20,2:30] extname+extver + ikiparams + section + + @file[noinherit] ikiparams + @file[noinherit][1:123,2:234] ikiparams + sections + + @file[1:123,2:234] sections + + @file[1:123,2:234] sections + + mef*.fits[filter?='V'] selection expression + mef*.fits[filter?='V';filter?='B'] selection expressions (OR) + mef*.fits[filter?='V'||filter?='B'] selection expressions (OR) + mef*.fits[gain>0.5&&gain<2.0] selection expressions (AND) + + Expressions will evaluate to 'false' if there is an error such as + "keyword not found", meaning that no images will match when one or + more keywords may not be present. Best to use a comma-delimited list + in this case. + + Concatenation + + @file // foo append + @file* // foo append wildcards + @file // [2] append modifiers + + foo // @file prepend + foo // @file* prepend wildcards + foo // @file[2] prepend modifiers + + Prior Behavior: + + foo // bar.fits ==> foobar.fits + foo.fits // bar ==> foobar.fits + + foo // @file1 ==> foosif1.fits,foomef1.fits + @file1 // bar ==> sif1foo.fits,mef1foo.fits + diff --git a/sys/imio/imt/fxf.h b/sys/imio/imt/fxf.h new file mode 100644 index 00000000..c4e6188b --- /dev/null +++ b/sys/imio/imt/fxf.h @@ -0,0 +1,172 @@ +# FITS.H -- IKI/FITS internal definitions. + +define FITS_ORIGIN "NOAO-IRAF FITS Image Kernel July 2003" + +define FITS_LENEXTN 4 # max length imagefile extension +define SZ_DATATYPE 16 # size of datatype string (eg "REAL*4") +define SZ_EXTTYPE 20 # size of exttype string (eg BINTABLE) +define SZ_KEYWORD 8 # size of a FITS keyword +define SZ_EXTRASPACE (81*32) # extra space for new cards in header +define DEF_PHULINES 0 # initial allocation for PHU +define DEF_EHULINES 0 # initial allocation for EHU +define DEF_PADLINES 0 # initial value for extra lines in HU +define DEF_PLMAXLEN 32768 # default max PLIO encoded line length +define DEF_PLDEPTH 0 # default PLIO mask depth + +define FITS_BLOCK_BYTES 2880 # FITS logical block length (bytes) +define FITS_BLOCK_CHARS 1440 # FITS logical block length (spp chars) +define FITS_STARTVALUE 10 # first column of value field +define FITS_ENDVALUE 30 # last column of value field +define FITS_SZVALSTR 21 # nchars in value string +define LEN_CARD 80 # length of FITS card. +define LEN_UACARD 81 # size of a Userarea line. +define LEN_OBJECT 63 # maximum length of a FITS string value +define LEN_FORMAT 40 # maximum length of a TFORM value +define NO_KEYW -1 # indicates no keyword is present. + +define MAX_OFFSETS 100 # max number of offsets per cache entry. +define MAX_CACHE 60 # max number of cache entries. +define DEF_CACHE 10 # default number of cache entries. + +define DEF_HDREXTN "fits" # default header file extension +define ENV_FKINIT "fkinit" # FITS kernel initialization + +define DEF_ISOCUTOVER 0 # date when ISO format dates kick in +define ENV_ISOCUTOVER "isodates" # environment override for default + +define FITS_BYTE 8 # Bits in a FITS byte +define FITS_SHORT 16 # Bits in a FITS short +define FITS_LONG 32 # Bits in a FITS long +define FITS_REAL -32 # 32 Bits FITS IEEE float representation +define FITS_DOUBLE -64 # 64 Bits FITS IEEE double representation + +define COL_VALUE 11 # Starting column for parameter values +define NDEC_REAL 7 # Precision of real +define NDEC_DOUBLE 14 # Precision of double + +define FITS_LEN_CHAR (((($1) + 1439)/1440)* 1440) + +# Extension subtypes. +define FK_PLIO 1 + +# Mapping of FITS Keywords to IRAF image header. All unrecognized keywords +# are stored here. + +#define UNKNOWN Memc[($1+IMU-1)*SZ_MII_INT+1] +define UNKNOWN Memc[($1+IMU-1)*SZ_STRUCT+1] + + +# FITS image descriptor, used internally by the FITS kernel. The required +# header parameters are maintained in this descriptor, everything else is +# simply copied into the user area of the IMIO descriptor. + +define LEN_FITDES 500 +define LEN_FITBASE 400 + +define FIT_ACMODE Memi[$1] # image access mode +define FIT_PFD Memi[$1+1] # pixel file descriptor +define FIT_PIXOFF Memi[$1+2] # pixel offset +define FIT_TOTPIX Memi[$1+3] # size of image in pixfile, chars +define FIT_IO Memi[$1+4] # FITS I/O channel +define FIT_ZCNV Memi[$1+5] # set if on-the-fly conversion needed +define FIT_IOSTAT Memi[$1+6] # i/o status for zfio routines +define FIT_TFORMP Memi[$1+7] # TFORM keyword value pointer +define FIT_TTYPEP Memi[$1+8] # TTYPE keyword value pointer +define FIT_TFIELDS Memi[$1+9] # number of fields in binary table +define FIT_PCOUNT Memi[$1+10] # PCOUNT keyword value + # extra space +define FIT_BSCALE Memd[P2D($1+16)] +define FIT_BZERO Memd[P2D($1+18)] +define FIT_BITPIX Memi[$1+20] # bits per pixel +define FIT_NAXIS Memi[$1+21] # number of axes in image +define FIT_LENAXIS Memi[$1+22+$2-1]# 35:41 = [7] max +define FIT_ZBYTES Memi[$1+30] # Status value for FIT_ZCNV mode +define FIT_HFD Memi[$1+31] # Header file descriptor +define FIT_PIXTYPE Memi[$1+32] +define FIT_CACHEHDR Memi[$1+33] # Cached main header unit's address. +define FIT_CACHEHLEN Memi[$1+34] # Lenght of the above. +define FIT_IM Memi[$1+35] # Has the 'im' descriptor value +define FIT_GROUP Memi[$1+36] +define FIT_NEWIMAGE Memi[$1+37] # Newimage flag +define FIT_HDRPTR Memi[$1+38] # Header data Xtension pointer +define FIT_PIXPTR Memi[$1+39] # Pixel data Xtension pointer +define FIT_NUMOFFS Memi[$1+40] # Number of offsets in cache header. +define FIT_EOFSIZE Memi[$1+41] # Size in char of file before append. +define FIT_XTENSION Memi[$1+42] # Yes, if an Xtension has been read. +define FIT_INHERIT Memi[$1+43] # INHERIT header keyword value. +define FIT_EXTVER Memi[$1+44] # EXTVER value (integer only) +define FIT_EXPAND Memi[$1+45] # Expand the header? +define FIT_MIN Memr[P2R($1+46)]# Minimum pixel value +define FIT_MAX Memr[P2R($1+47)]# Maximum pixel value +define FIT_MTIME Meml[$1+48] # Time of last mod. for FITS unit +define FIT_SVNANR Memr[P2R($1+49)] +define FIT_SVNAND Memd[P2D($1+50)] +define FIT_SVMAPRIN Memi[$1+52] +define FIT_SVMAPROUT Memi[$1+53] +define FIT_SVMAPDIN Memi[$1+54] +define FIT_SVMAPDOUT Memi[$1+55] +define FIT_EXTEND Memi[$1+56] # FITS extend keyword +define FIT_PLMAXLEN Memi[$1+57] # PLIO maximum linelen + # extra space +define FIT_EXTTYPE Memc[P2C($1+70)] # extension type +define FIT_FILENAME Memc[P2C($1+110)] # FILENAME value +define FIT_EXTNAME Memc[P2C($1+150)] # EXTNAME value +define FIT_DATATYPE Memc[P2C($1+190)] # datatype string +define FIT_TITLE Memc[P2C($1+230)] # title string +define FIT_OBJECT Memc[P2C($1+270)] # object string +define FIT_EXTSTYPE Memc[P2C($1+310)] # FITS extension subtype + # extra space + +# The FKS terms carry the fkinit or kernel section arguments. +define FKS_APPEND Memi[$1+400] # YES, NO append an extension +define FKS_INHERIT Memi[$1+401] # YES, NO inherit the main header +define FKS_OVERWRITE Memi[$1+402] # YES, NO overwrite an extension +define FKS_DUPNAME Memi[$1+403] # YES, NO allow duplicated EXTNAME +define FKS_EXTVER Memi[$1+404] # YES, NO allow duplicated EXTNAME +define FKS_EXPAND Memi[$1+405] # YES, NO expand the header +define FKS_PHULINES Memi[$1+406] # Allocated lines in PHU +define FKS_EHULINES Memi[$1+407] # Allocated lines in EHU +define FKS_PADLINES Memi[$1+408] # Additional lines for HU +define FKS_NEWFILE Memi[$1+409] # YES, NO force newfile +define FKS_CACHESIZE Memi[$1+410] # size of header cache +define FKS_SUBTYPE Memi[$1+411] # BINTABLE subtype +define FKS_EXTNAME Memc[P2C($1+412)] # EXTNAME value + # extra space + + +# Reserved FITS keywords known to this code. + +define FK_KEYWORDS "|bitpix|datatype|end|naxis|naxisn|simple|bscale|bzero\ +|origin|iraf-tlm|filename|extend|irafname|irafmax|irafmin|datamax\ +|datamin|xtension|object|pcount|extname|extver|nextend|inherit\ +|zcmptype|tform|ttype|tfields|date|" + +define KW_BITPIX 1 +define KW_DATATYPE 2 +define KW_END 3 +define KW_NAXIS 4 +define KW_NAXISN 5 +define KW_SIMPLE 6 +define KW_BSCALE 7 +define KW_BZERO 8 +define KW_ORIGIN 9 +define KW_IRAFTLM 10 +define KW_FILENAME 11 +define KW_EXTEND 12 +define KW_IRAFNAME 13 +define KW_IRAFMAX 14 +define KW_IRAFMIN 15 +define KW_DATAMAX 16 +define KW_DATAMIN 17 +define KW_XTENSION 18 +define KW_OBJECT 19 +define KW_PCOUNT 20 +define KW_EXTNAME 21 +define KW_EXTVER 22 +define KW_NEXTEND 23 +define KW_INHERIT 24 +define KW_ZCMPTYPE 25 +define KW_TFORM 26 +define KW_TTYPE 27 +define KW_TFIELDS 28 +define KW_DATE 29 diff --git a/sys/imio/imt/imt.x b/sys/imio/imt/imt.x new file mode 100644 index 00000000..64e1441c --- /dev/null +++ b/sys/imio/imt/imt.x @@ -0,0 +1,342 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +.help imt +.nf ___________________________________________________________________________ +IMT -- Image template package. + +The image template package is based upon the filename template package, the +main difference being that the IMT package knows about the use of [] in image +names, e.g., for image sections or cluster indices. + + list = imtopenp (clparam) + + list = imtopen (template) + imtclose (list) + nchars|eof = imtgetim (list, image, maxch) + nchars|eof = imtrgetim (list, index, image, maxch) + len = imtlen (list) + imtrew (list) + +An image template consists of a comma delimited list of one or more patterns. +Each pattern consists of a filename template optionally followed by a cluster +index or image section. + + filename_template [image stuff] , ... + +In the simplest case a simple alphanumeric image or file name may be given. +Template expansion is carried out by parsing off the [] image stuff, calling +FNTOPNB to expand the filename template, and then appending the [] string to +each output filename returned by FNTGFNB. Multiple adjacent [] sequences are +permitted and are treated as one long string. + +The [ must be escaped to be included in the filename template. The escape +will be passed on, causing the [ to be passed through into the file output +filename. This prevents use of the [chars] character class notation in image +templates; the [] are either interpreted as part of the image specification, +or as part of the filename. +.endhelp _____________________________________________________________________ + +define SZ_FNT 16384 +define CH_DELIM 20B # used to flag image section + + +# IMTOPENP -- Open an image template obtained as the string value of a CL +# parameter. + +pointer procedure imtopenp (param) + +char param[ARB] # CL parameter with string value template +pointer sp, template, imt +pointer imtopen() +errchk clgstr + +begin + call smark (sp) + call salloc (template, SZ_FNT, TY_CHAR) + + call clgstr (param, Memc[template], SZ_FNT) + imt = imtopen (Memc[template]) + + call sfree (sp) + return (imt) +end + + +# IMTOPEN -- Open an image template. The filename template package is +# sophisticated enough to do all the necessary filename editing, etc., so all +# we need do is recast the image notation into a FNT edit operation, e.g., +# `*.imh[*,-*]' becomes `*.hhh%%?\[\*\,-\*]%', with the ? (CH_DELIM, actually +# an unprintable ascii code) being included to make it easy to locate the +# section string in the filenames returned by FNT. We then open the resultant +# template and perform the inverse mapping upon the filenames returned by FNT. + +pointer procedure imtopen (template) + +char template[ARB] # image template + +int sort, level, ip, ch +pointer sp, listp, fnt, op +define output {Memc[op]=$1;op=op+1} + +int fntopnb(), strlen() +pointer imxopen() +bool envgetb() + +begin + # The interface is unchanged as far as the applications are + # concerned, but we'll branch here to the enhanced list processing + # if it is available. + + if (envgetb ("use_vo") && envgetb ("use_new_imt")) + return (imxopen (template)) + + + call smark (sp) + call salloc (fnt, max(strlen(template)*2, SZ_FNT), TY_CHAR) + + # Sorting is disabled as input and output templates, derived from the + # same database but with string editing used to modify the output list, + # may be sorted differently as sorting is performed upon the edited + # output list. + + sort = NO + + op = fnt + for (ip=1; template[ip] != EOS; ip=ip+1) { + ch = template[ip] + + if (ch == '[') { + if (ip > 1 && template[ip-1] == '!') { + # ![ -- Pass a [ to FNT (character class notation). + Memc[op-1] = '[' + + } else if (ip > 1 && template[ip-1] == '\\') { + # \[ -- The [ is part of the filename. Pass it on as an + # escape sequence to get by the FNT. + + output ('[') + + } else { + # [ -- Unescaped [. This marks the beginning of an image + # section sequence. Output `%%[...]%' and escape all + # pattern matching metacharacters until a comma template + # delimiter is encountered. Note that a comma within [] + # is not a template delimiter. + + output ('%') + output ('%') + output (CH_DELIM) + + level = 0 + for (; template[ip] != EOS; ip=ip+1) { + ch = template[ip] + if (ch == ',') { # , + if (level <= 0) + break # exit loop + else { + output ('\\') + output (ch) + } + } else if (ch == '[') { # [ + output ('\\') + output (ch) + level = level + 1 + } else if (ch == ']') { # ] + output (ch) + level = level - 1 + } else if (ch == '*') { # * + output ('\\') + output (ch) + } else # normal chars + output (ch) + } + output ('%') + ip = ip - 1 + } + + } else if (ch == '@') { + # List file reference. Output the CH_DELIM code before the @ + # to prevent further translations on the image section names + # returned from the list file, e.g., "CH_DELIM // @listfile". + + output (CH_DELIM) + output ('/') + output ('/') + output (ch) + + } else + output (ch) + } + + Memc[op] = EOS + + listp = fntopnb (Memc[fnt], sort) + + call sfree (sp) + return (listp) +end + + +# IMTGETIM -- Get the next image name from the image template. FNT returns a +# filename with optional appended image section (preceded by the CH_DELIM +# character). Our job is to escape any [ in the filename part of the image +# name to avoid interpretation of these chars as image section characters by +# IMIO. The CH_DELIM is deleted and everything following is simply copied +# to the output. + +int procedure imtgetim (imt, outstr, maxch) + +pointer imt # image template descriptor +char outstr[ARB] # output string +int maxch # max chars out + +int nchars +pointer sp, buf +int fntgfnb(), imt_mapname() +errchk fntgfnb + +begin + call smark (sp) + call salloc (buf, SZ_PATHNAME, TY_CHAR) + + if (fntgfnb (imt, Memc[buf], SZ_PATHNAME) == EOF) { + outstr[1] = EOS + call sfree (sp) + return (EOF) + } + + nchars = imt_mapname (Memc[buf], outstr, maxch) + call sfree (sp) + return (nchars) +end + + +# IMTRGETIM -- Like imt_getim, but may be used to randomly access the image +# list. + +int procedure imtrgetim (imt, index, outstr, maxch) + +pointer imt # image template descriptor +int index # list element to be returned +char outstr[ARB] # output string +int maxch # max chars out + +int nchars +pointer sp, buf +int fntrfnb(), imt_mapname() +errchk fntrfnb + +begin + call smark (sp) + call salloc (buf, SZ_PATHNAME, TY_CHAR) + + if (fntrfnb (imt, index, Memc[buf], SZ_PATHNAME) == EOF) { + outstr[1] = EOS + call sfree (sp) + return (EOF) + } + + nchars = imt_mapname (Memc[buf], outstr, maxch) + call sfree (sp) + return (nchars) +end + + +# IMTLEN -- Return the number of image names in the expanded list. + +int procedure imtlen (imt) + +pointer imt # image template descriptor +int fntlenb() + +begin + return (fntlenb (imt)) +end + + +# IMTREW -- Rewind the expanded image list. + +procedure imtrew (imt) + +pointer imt # image template descriptor + +begin + call fntrewb (imt) +end + + +# IMTCLOSE -- Close an image template. + +procedure imtclose (imt) + +pointer imt # image template descriptor + +begin + call fntclsb (imt) +end + + +# IMT_MAPNAME -- Translate the string returned by FNT into an image +# specification suitable for input to IMIO. + +int procedure imt_mapname (fnt, outstr, maxch) + +char fnt[ARB] # FNT string +char outstr[ARB] # output string +int maxch + +int ip, op +char url[SZ_PATHNAME], cfname[SZ_PATHNAME] + +int strncmp(), strlen() +bool envgetb() + +begin + # Check for a URL-encoded string. + + if (strncmp ("http:", fnt, 5) == 0) { + call aclrc (url, SZ_PATHNAME) + call sprintf (url, SZ_PATHNAME, "http://%s") + call pargstr (fnt[6]) + + call fcadd ("cache$", url, "", cfname, SZ_PATHNAME) + call strcpy (cfname, outstr, SZ_PATHNAME) + return (strlen (cfname)) + } + + op = 1 + for (ip=1; fnt[ip] != EOS; ip=ip+1) { + if (fnt[ip] == '[') { + outstr[op] = '\\' + op = op + 1 + outstr[op] = '[' + op = op + 1 + + } else if (fnt[ip] == CH_DELIM) { + for (ip=ip+1; fnt[ip] != EOS; ip=ip+1) { + outstr[op] = fnt[ip] + op = op + 1 + if (op > maxch) + break + } + break + + } else { + outstr[op] = fnt[ip] + op = op + 1 + if (op > maxch) + break + } + } + outstr[op] = EOS + + # FIXME + if (envgetb ("vo_prefetch") && strncmp (outstr, "cache", 5) == 0) { +# call sprintf (cfname, SZ_LINE, "%s.fits") + call sprintf (cfname, SZ_LINE, "%s") + call pargstr (outstr) + call fcwait ("cache$", cfname) + } + + return (op - 1) +end diff --git a/sys/imio/imt/imx.h b/sys/imio/imt/imx.h new file mode 100644 index 00000000..362e146f --- /dev/null +++ b/sys/imio/imt/imx.h @@ -0,0 +1,28 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> + + +define SZ_FNT 32768 +define CH_DELIM 20B # used to flag image section + +define IMT_FILE 0 # file list +define IMT_IMAGE 1 # image list +define IMT_TABLE 2 # table list (ascii file) +define IMT_VOTABLE 3 # table list (XML file) +define IMT_URL 4 # file URL +define IMT_DIR 5 # directory + +define IMT_OUTPUTS "|none|list|file|" # expansion options +define IMTY_NONE 1 # No output +define IMTY_LIST 2 # List output +define IMTY_FILE 3 # File output + +define SZ_RANGE 100 # Size of extension range list +define SZ_LISTOUT 16384 # Size of extension output list + +define FIRST 1 # Default starting range +define LAST MAX_INT # Default ending range +define STEP 1 # Default step +define EOLIST -1 # End of list + diff --git a/sys/imio/imt/imx.x b/sys/imio/imt/imx.x new file mode 100644 index 00000000..ba3f7bc8 --- /dev/null +++ b/sys/imio/imt/imx.x @@ -0,0 +1,242 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <syserr.h> +include <ctype.h> +include "imx.h" + +define DEBUG FALSE + + +# IMXOPEN -- Open an image template using the enhanced expansion +# capabilities. This procedure is simply the entry point to the imtopen() +# method in the standard IMT interface. + +pointer procedure imxopen (template) + +char template[ARB] # image template + +int i, sort, level, ip, ch, expand, nchars, nimages, index, type +int max_fnt, fnt_len, len, flen +pointer listp, intmp, fnt, op, exp +char lfile[SZ_LINE], lexpr[SZ_LINE], likparams[SZ_LINE], lsec[SZ_LINE] +char lindex[SZ_LINE], lextname[SZ_LINE], lextver[SZ_LINE], elem[SZ_LINE] + +pointer imx_preproc (), imx_imexpand (), imx_fexpand () +pointer imx_texpand (), imx_dexpand () +int imx_filetype (), imx_parse (), imx_get_element () +int fntopnb (), strlen (), strsearch() +int sum, fntlenb() +bool envgetb() + +define output {Memc[op]=$1;op=op+1} +define escape {output('\\');output($1)} + +begin + # Pre-process the input template. + intmp = imx_preproc (template) + + if (DEBUG) { + call eprintf ("template: '%s'\npreproc: '%s'\n\n") + call pargstr (template) + call pargstr (Memc[intmp]) + } + + + fnt_len = 0 # initialize + max_fnt = SZ_FNT + call calloc (fnt, max_fnt, TY_CHAR) + + # Sorting is disabled as input and output templates, derived from the + # same database but with string editing used to modify the output list, + # may be sorted differently as sorting is performed upon the edited + # output list. + + sort = NO + + op = fnt + ip = intmp + + for (ip=intmp; Memc[ip] != EOS; ip=ip+1) { + ch = Memc[ip] + + if (ch == '[') { + if (ip > 1 && Memc[ip-1] == '!') { + # ![ -- Pass a [ to FNT (character class notation). + Memc[op-1] = '[' + + } else if (ip > 1 && Memc[ip-1] == '\\') { + # \[ -- The [ is part of the filename. Pass it on as an + # escape sequence to get by the FNT. + + output ('[') + + } else { + # [ -- Unescaped [. This marks the beginning of an image + # section sequence. Output `%%[...]%' and escape all + # pattern matching metacharacters until a comma template + # delimiter is encountered. Note that a comma within [] + # is not a template delimiter. + + output ('%') + output ('%') + output (CH_DELIM) + + level = 0 + for (; Memc[ip] != EOS; ip=ip+1) { + ch = Memc[ip] + if (ch == ',') { # , + if (level <= 0) + break # exit loop + else { + escape (ch) + } + } else if (ch == '[') { # [ + escape (ch) + level = level + 1 + } else if (ch == ']') { # ] + output (ch) + level = level - 1 + } else if (ch == '*') { # * + escape (ch) + } else # normal chars + output (ch) + } + output ('%') + ip = ip - 1 + } + + } else if (ch == '@') { + # List file reference. Output the CH_DELIM code before the @ + # to prevent further translations on the image section names + # returned from the list file, e.g., "CH_DELIM // @listfile". + + # See if we're asking to expand the contents of the file, + # e.g. as in "@@listfile" where 'listfile' contains MEFs + # or tables we later expand. + expand = NO + if (Memc[ip+1] == '@') + expand = YES + + # Break out the listfile from the filtering expression. + + index = 1 + nchars = imx_get_element (Memc[ip], index, elem, SZ_LINE) + ip = ip + strlen(elem) - 1 + + nchars = imx_parse (elem, lfile, lindex, lextname, + lextver, lexpr, lsec, likparams, SZ_LINE) + + if (DEBUG) { + call eprintf ("imtopen: lfile='%s' lexpr='%s' ip='%s'\n") + call pargstr (lfile) + call pargstr (lexpr) + call pargstr (Memc[ip]) + } + + + exp = NULL + type = imx_filetype (lfile) + switch (type) { + case IMT_IMAGE: + exp = imx_imexpand (lfile, lexpr, lindex, lextname, lextver, + likparams, lsec, nimages) + + case IMT_TABLE: + case IMT_VOTABLE: + exp = imx_texpand (lfile, type, lexpr, lindex, "", nimages) + + case IMT_FILE: + if (strsearch (lfile, "//") > 0) { + call calloc (exp, SZ_FNAME, TY_CHAR) + call strcpy (lfile, Memc[exp], SZ_FNAME) + nimages = 1 + + } else if (lfile[1] == '@' && strsearch(lfile, "//") == 0) { + exp = imx_fexpand (lfile[2], lexpr, lindex, lextname, + lextver, likparams, lsec, nimages) +# if (nimages > 0) { +# output (CH_DELIM); output ('/'); output ('/') +# } + + } else { + call calloc (exp, SZ_FNAME, TY_CHAR) + call strcpy (lfile, Memc[exp], SZ_FNAME) + nimages = 1 + } + + case IMT_DIR: + exp = imx_dexpand (lfile, lexpr, lindex, lextname, lextver, + likparams, lsec, nimages) + } + + if (DEBUG) { + call eprintf ("expand: exp='%s' len=%d nim=%d\n") + call pargstr (Memc[exp]) + call pargi (strlen(Memc[exp])) + call pargi (nimages) + } + + + # Copy to the output template string. + len = strlen (Memc[exp]) + if (nimages > 0) { + if ((fnt_len + len) >= max_fnt) { + max_fnt = max_fnt + len + 1 + if (fnt != NULL) + call realloc (fnt, max_fnt, TY_CHAR) + else + call calloc (fnt, max_fnt, TY_CHAR) + op = fnt + if (fnt_len > 0) + op = fnt + strlen (Memc[fnt]) + } + for (i=0; i < len; i=i+1) + output (Memc[exp+i]) + Memc[op+1] = EOS + fnt_len = fnt_len + strlen (Memc[exp]) + } + + if (exp != NULL) + call mfree (exp, TY_CHAR) + nimages = 0 + + } else + output (ch) + } + output ('\0') + Memc[op] = EOS + + + # Clean up the expanded template string in case there were selection + # filters that rejected images and we have extra commas in the string. + len = strlen (Memc[fnt]) + if (Memc[fnt+len-1] == ',') { # kill trailing commas + for (ip=fnt+len-1; Memc[ip] == ',' && ip >= fnt; ip=ip-1) + Memc[ip] = '\0' + } + if (Memc[fnt] == ',') { + for (ip=fnt; Memc[ip] == ','; ) # skip leading commas + ip = ip + 1 + for (op=fnt; Memc[ip] != EOS; ip=ip+1) { + Memc[op] = Memc[ip] + op = op + 1 + } + Memc[op] = '\0' + } + + if (DEBUG) { + call eprintf ("imxopen: fnt='%s'\n") + call pargstr (Memc[fnt]) + } + + + # Open the template string using the filename list. + listp = fntopnb (Memc[fnt], sort) + + # Clean up. + call mfree (fnt, TY_CHAR) + call mfree (intmp, TY_CHAR) + + return (listp) +end diff --git a/sys/imio/imt/imxbreakout.x b/sys/imio/imt/imxbreakout.x new file mode 100644 index 00000000..57a92b8a --- /dev/null +++ b/sys/imio/imt/imxbreakout.x @@ -0,0 +1,233 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> + + +# IMX_BREAKOUT -- Break out the filename template from the filtering +# expression in the list item. Our input value is a single item in the +# template list, we'll logically separate image parameters, section strings +# and extension values from expressions that might be used in filtering. + +int procedure imx_breakout (item, expand, fname, expr, sec, ikparams, maxch) + +char item[ARB] #i template string ptr +int expand #i expanding contents? +char fname[ARB] #o list filename +char expr[ARB] #o filtering expression +char sec[ARB] #o section string +char ikparams[ARB] #o image kernel params +int maxch #i max chars in fname and expr + +char ch, str[SZ_LINE], sifname[SZ_LINE] +int nchars, ip, op +bool is_sif + +bool imx_issection(), imx_sifmatch() +int stridx() + +define next_str_ 99 + +begin + call aclrc (fname, maxch) + call aclrc (expr, maxch) + call aclrc (sec, maxch) + + # At the start the ip points to the '@' in the template string. + # Skip ahead to the start of the filename template string. + ip = 1 + if (expand == YES) + ip = ip + 1 + + # Copy out the filename template up to the EOS, a '[' to indicate + # the start of a filter expression, or a comma indicating the next + # item in the list. + ch = item[ip] + for (op=1; ch != EOS; op=op+1) { + fname[op] = ch + + ch = item[ip+1] + if (ch == ',' || ch == EOS) + return (ip-1) # next list item, no filter expr + else if (ch == '[') + break # break to get the filter expr + + ip = ip + 1 + } + + + # Get the string up to the closing ']' char. +next_str_ + ip = ip + 2 + ch = item[ip] + call aclrc (str, SZ_LINE) + for (op=1; ch != EOS; op=op+1) { + str[op] = ch + + ip = ip + 1 + ch = item[ip] + if (ch == ']') + break # break to get the filter expr + } + + if (imx_issection (str)) { + call strcpy (str, sec, SZ_LINE) + } else { + if (expr[1] != EOS) { + call strcat (",", expr, SZ_LINE) + call strcat (str, expr, SZ_LINE) + } else + call strcpy (str, expr, SZ_LINE) + } + + if (item[ip+1] != EOS) + goto next_str_ + + call imx_ikparams (expr, ikparams, SZ_LINE) + + # If we've found both a section and an expression, check that the + # section isn't being confused with an index list. + #if (sec[1] != EOS && expr[1] != EOS) { + # if (!is_sif && stridx (':', sec) == 0) { + # call strcat (",", expr, SZ_LINE) + # call strcat (sec, expr, SZ_LINE) + # } + #} + + if (sec[1] != EOS) { + call aclrc (sifname, SZ_LINE) + call sprintf (sifname, SZ_LINE, "%s[1][%s]") + if (fname[1] == '@') + call pargstr (fname[2]) + else + call pargstr (fname) + call pargstr (sec) + } else { + call strcpy (fname, sifname, SZ_LINE) + } + is_sif = imx_sifmatch (sifname, "yes") + + nchars = ip - 1 + return (nchars) +end + + +# IMX_ISSECTION -- Determine if the string is an image section. +# +# Note: There is a possible ambiguity here where using an image section +# that represents a single pixel (e.g. foo.fits[100,100]) which might also +# be a list of image extensions. + +bool procedure imx_issection (str) + +char str[ARB] # string to be checked + +int ip, stridxs() + +begin + for (ip=1; str[ip] != EOS; ip=ip+1) { + if (IS_ALPHA(str[ip]) || stridxs ("x()<>?", str) > 0) + return (FALSE) + } + + # Test for a range list, e.g. "[1-5]" + if (stridxs ("-,", str) > 0 && stridxs (":*", str) == 0) + return (FALSE); + + # Test for a section that flips axes, e.g. "[-*,*]" + if (stridxs ("-*:,", str) > 0) + return (TRUE); + + return (FALSE) +end + + +# IMX_IKPARMS -- Break out the image kernel params from the template list +# expression string. + +procedure imx_ikparams (expr, ikparams, maxch) + +char expr[ARB] # expression string to modify +char ikparams[ARB] # extracted image kernel params +int maxch # max size of output strings + +int ip, op, nexpr, niki +char ch, in[SZ_LINE], sub[SZ_LINE] + +bool imx_isikparam() + +begin + call aclrc (in, SZ_LINE) # initialize + call strcpy (expr, in, SZ_LINE) + nexpr = 0 + niki = 0 + + call aclrc (expr, maxch) + call aclrc (ikparams, maxch) + for (ip=1; in[ip] != EOS; ip=ip+1) { + # Copy out the sub expression, i.e. up to the comma or EOS. + call aclrc (sub, SZ_LINE) + op = 1 + while (in[ip] != EOS && in[ip] != ',' && in[ip] != ';') { + sub[op] = in[ip] + ip = ip + 1 + op = op + 1 + } + ch = in[ip] + + if (imx_isikparam (sub)) { + if (niki > 0) + call strcat (",", ikparams, maxch) + call strcat (sub, ikparams, maxch) + niki = niki + 1 + + } else { + if (nexpr > 0) + call strcat (",", expr, maxch) + call strcat (sub, expr, maxch) + nexpr = nexpr + 1 + } + + if (ch == EOS) + break + } +end + + +# IMX_ISIKPARAM -- See whether the substring refers to an image kernel param. + +bool procedure imx_isikparam (str) + +char str[ARB] # string to check + +int strncmp() + +begin + if (strncmp (str, "extname", 7) == 0 || strncmp (str, "extver", 6) == 0) + return (TRUE) + + # Check for the "no" versions of selected keywords. + else if (strncmp (str, "no", 2) == 0) { + if ((strncmp (str[3], "append", 4) == 0) || + (strncmp (str[3], "inherit", 4) == 0) || + (strncmp (str[3], "overwrite", 4) == 0) || + (strncmp (str[3], "dupname", 4) == 0) || + (strncmp (str[3], "expand", 4) == 0)) + return (TRUE) + } + + # Other kernel keywords. + if (strncmp (str, "inherit", 4) == 0 || + strncmp (str, "overwrite", 4) == 0 || + strncmp (str, "dupname", 4) == 0 || + strncmp (str, "append", 4) == 0 || + strncmp (str, "noappend", 4) == 0 || + strncmp (str, "type", 4) == 0 || + strncmp (str, "expand", 4) == 0 || + strncmp (str, "phulines", 4) == 0 || + strncmp (str, "ehulines", 4) == 0 || + strncmp (str, "padlines", 4) == 0 || + strncmp (str, "cachesize", 4) == 0) + return (TRUE) + + return (FALSE) +end diff --git a/sys/imio/imt/imxescape.x b/sys/imio/imt/imxescape.x new file mode 100644 index 00000000..92750ab7 --- /dev/null +++ b/sys/imio/imt/imxescape.x @@ -0,0 +1,74 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "imx.h" + + +# IMX_ESCAPE -- Return a pointer to the composed file name, escaping parts +# as needed. + +pointer procedure imx_escape (in, index, extname, extver, ikparams, + section, expr, maxch) + +char in[ARB] #I File image name (without kernel or image sec) +char index[ARB] #I Range list of extension indexes +char extname[ARB] #I Pattern for extension names +char extver[ARB] #I Range list of extension versions +char ikparams[ARB] #I Image kernel parameters +char section[ARB] #I Image section +char expr[ARB] #I Selection expression +int maxch #I Print errors? + +pointer out, op +int i, len, level +char ch, peek, prev +bool init_esc + +int strlen() + +define output {Memc[op]=$1;op=op+1} +define escape {output('\\');output($1)} + +begin + len = max (SZ_LINE, strlen (in)) + call calloc (out, max (SZ_LINE, (4*len)), TY_CHAR) + + op = out + level = 0 + + init_esc = false + for (i=1; i <= len; i=i+1) { + prev = in[max(1,i)] + ch = in[i] + peek = in[i+1] + + if (ch == EOS) + break; + if (ch == '[') { + if (prev != ']' && !init_esc) { + output ('%') + output ('%') + output (CH_DELIM) + init_esc = true + } + escape (ch) + level = level + 1 + } else if (ch == ']') { + output (ch) + if (peek != '[') # closing delim + output ('%') + level = level - 1 + } else if (ch == ',') { + if (level > 0) + output('\\') + if (level == 0) + init_esc = false + output (ch) + } else if (ch == '*') + escape (ch) + else + output (ch) + } + output (EOS) + + return (out) +end diff --git a/sys/imio/imt/imxexpand.x b/sys/imio/imt/imxexpand.x new file mode 100644 index 00000000..72efb17c --- /dev/null +++ b/sys/imio/imt/imxexpand.x @@ -0,0 +1,1287 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <syserr.h> +include <imhdr.h> +include <imset.h> +include <mach.h> +include <fio.h> +include <finfo.h> +include <ctype.h> +include <diropen.h> + +include "imx.h" +include <votParse_spp.h> + + +define SZ_BUF 8192 # name buffer string + + +# IMX_IMEXPAND -- Expand a template of FITS files into a list of image +# extensions. + +pointer procedure imx_imexpand (input, expr, index, extname, extver, ikparams, + section, nimages) + +char input[ARB] # List of ME file names +char expr[ARB] # Filtering expression +char index[ARB] # Range list of extension indexes +char extname[ARB] # Patterns for extension names +char extver[ARB] # Range list of extension versions +char ikparams[ARB] # Image kernel parameters +char section[ARB] # Image section parameters +int nimages # Number of output images + +int lindex # List index number? +int lname # List extension name? +int lver # List extension version? + +pointer in, out # Pointer to output string +pointer sp, sif, image, listout +int list, len, maxch + +int imx_extns(), strlen(), fntgfnb(), fntlenb() +pointer imx_escape() +bool imx_sifmatch() + +begin + call smark (sp) + call salloc (in, SZ_FNAME, TY_CHAR) + call salloc (image, SZ_FNAME, TY_CHAR) + + + lindex = YES # expansion parameters + lname = NO + lver = NO + out = NULL + len = 0 + nimages = 0 + maxch = SZ_LISTOUT + + call aclrc (Memc[in], SZ_FNAME) + if (input[1] == '@') + call strcpy (input[2], Memc[in], SZ_FNAME) + else + call strcpy (input, Memc[in], SZ_FNAME) + + # Get the list. + list = imx_extns (Memc[in], "IMAGE", index, extname, extver, + lindex, lname, lver, ikparams, section, expr, YES) + + if (list == NULL || fntlenb (list) == 0) { + call calloc (out, SZ_LINE, TY_CHAR) + call strcpy (Memc[in], Memc[out], SZ_LINE) + if (section[1] != EOS) { + call strcat ("\\[", Memc[out], maxch) + call strcat (section, Memc[out], maxch) + call strcat ("]", Memc[out], maxch) + } + if (ikparams[1] != EOS) { + call strcat ("\\[", Memc[out], maxch) + call strcat (ikparams, Memc[out], maxch) + call strcat ("]", Memc[out], maxch) + } + + if (index[1] == EOS && imx_sifmatch (Memc[out], expr)) { + nimages = 1 + sif = imx_escape (Memc[out], index, extname, extver, ikparams, + section, expr, maxch) + } else + call calloc (sif, SZ_LINE, TY_CHAR) + call mfree (out, TY_CHAR) + return (sif) + } + + # Format the output and set the number of images. + call calloc (listout, maxch, TY_CHAR) + iferr { + while (fntgfnb (list, Memc[image], SZ_FNAME) != EOF) { + nimages = nimages + 1 + if (nimages > 1) { + call strcat (",", Memc[listout], maxch) + len = len + 1 + } + if ((len + strlen (Memc[image])) >= maxch) { + maxch = maxch + SZ_LISTOUT + call realloc (listout, maxch, TY_CHAR) + } + + call strcat (Memc[image], Memc[listout], maxch) + len = len + strlen (Memc[image]) + +# if (section[1] != EOS) { +# call strcat ("[", Memc[listout], maxch) +# call strcat (section, Memc[listout], maxch) +# call strcat ("]", Memc[listout], maxch) +# len = len + strlen (section) + 2 +# } + } + + # Escape the output image specification in a form that is correct + # for the filename template interface. + + out = imx_escape (Memc[listout], index, extname, extver, ikparams, + section, expr, maxch) + + } then { + call fntclsb (list) + call sfree (sp) + call error (1, "Output list format is too long") + } + call fntclsb (list) + call sfree (sp) + + return (out) +end + + +# IMX_FEXPAND -- Expand a template of files into a list of images names. + +pointer procedure imx_fexpand (input, expr, index, extname, extver, ikparams, + section, nimages) + +char input[ARB] # List of ME file names +char expr[ARB] # Filtering expression +char index[ARB] # Range list of extension indexes +char extname[ARB] # Patterns for extension names +char extver[ARB] # Range list of extension versions +char ikparams[ARB] # Image kernel parameters +char section[ARB] # Image section parameters +int nimages # Number of output images + +pointer sp, name, exp, lexp, nexp +int fd, ip, op, len, elen, nlines, nims, maxch, nchars, level +bool do_proc +char line[SZ_LINE], buf[SZ_LINE], ch + +define output {buf[op]=$1;op=op+1} + + +int open(), getline(), strlen(), stridx() +pointer imx_imexpand() + +begin + iferr (fd = open (input, READ_ONLY, TEXT_FILE)) { + call error (1, "Cannot open @file") + return (NULL) + } + + call smark (sp) + call salloc (name, SZ_PATHNAME, TY_CHAR) + + maxch = SZ_FNT + call calloc (exp, maxch, TY_CHAR) + call aclrc (Memc[exp], maxch) + +#call eprintf ( +# "fexpand: index='%s' name='%s' ver='%s' sec='%s' ik='%s' expr='%s'\n") +# call pargstr (index) ; call pargstr (extname) ; call pargstr (extver) ; +# call pargstr (section) ; call pargstr (ikparams) ; call pargstr (expr) + + nlines = 0 + nchars = 0 + nimages = 0 + + while (getline (fd, line) > 0) { + len = strlen (line) + line[len] = EOS # kill newline + nlines = nlines + 1 + + call aclrc (Memc[name], SZ_PATHNAME) + call sprintf (Memc[name], SZ_PATHNAME, "@%s") + call pargstr (line) + + lexp = 0 + do_proc = (index[1]!=EOS || section[1]!=EOS || + expr[1]!=EOS || extname[1]!=EOS) + + if (input[1] == '@' || do_proc) { + + # We're either being asked to expand what is presumably a + # image name in the form of an @@file input, or else we've + # added image sections, expressions, etc where the correct + # output specification is the expanded image name. + + lexp = imx_imexpand (Memc[name], expr, index, extname, extver, + ikparams, section, nims) + + elen = 0 + if (lexp != NULL && Memc[lexp] != EOS) + elen = strlen (Memc[lexp]) + + # Reallocate space is the output name if needed. + #if ((nchars + elen) >= (maxch - SZ_FNAME)) { + if ((nchars + elen) >= maxch) { + call calloc (nexp, maxch + SZ_FNT, TY_CHAR) + call amovc (Memc[exp], Memc[nexp], maxch) + call mfree (exp, TY_CHAR) + maxch = maxch + SZ_FNT + exp = nexp + } + + # Create a comma-delimited list. + if (nlines > 1) + call strcat (",", Memc[exp], maxch) + if (lexp != NULL && Memc[lexp] != EOS) { + call strcat (Memc[lexp], Memc[exp], maxch) + nchars = nchars + elen + 1 + } + nimages = nimages + nims + } else { + if (nlines > 1) { + call strcat (",", Memc[exp], maxch) + nchars = nchars + 1 + } + if (stridx ('[', line) != 0) { + call aclrc (buf, SZ_LINE) + op = 1 + for (ip=1; line[ip] != EOS; ip=ip+1) { + if (line[ip] == '[') { + output ('%') + output ('%') + output (CH_DELIM) + + level = 0 + for (; line[ip] != EOS; ip=ip+1) { + ch = line[ip] + if (ch == ',') { # , + if (level <= 0) + break # exit loop + else { + output ('\\') + output (ch) + } + } else if (ch == '[') { # [ + output ('\\') + output (ch) + level = level + 1 + } else if (ch == ']') { # ] + output (ch) + level = level - 1 + } else if (ch == '*') { # * + output ('\\') + output (ch) + } else # normal chars + output (ch) + } + output ('%') + ip = ip - 1 + + break + } + buf[op] = line[ip] + op = op + 1 + } + call strcat (buf, Memc[exp], maxch) + nchars = nchars + strlen (buf) + + } else { + call strcat (line, Memc[exp], maxch) + nchars = nchars + strlen (line) + } + + nchars = nchars + len + 1 + nimages = nimages + 1 + + # Reallocate space is the output name if needed. + + if ((nchars + SZ_LINE) >= maxch) { + call calloc (nexp, maxch + SZ_FNT, TY_CHAR) + call amovc (Memc[exp], Memc[nexp], maxch) + call mfree (exp, TY_CHAR) + maxch = maxch + SZ_FNT + exp = nexp + } + } + call mfree (lexp, TY_CHAR) + } + + call close (fd) # clean up + call sfree (sp) + + return (exp) +end + + +# IMX_TEXPAND -- Expand a template of tables into a list of images. + +pointer procedure imx_texpand (input, type, expr, index, fmt, nimages) + +char input[ARB] # Input table name +int type # Table type +char expr[ARB] # Filtering expression +char index[ARB] # Range list of table rows +char fmt[ARB] # Requested file format +int nimages # Number of output images + +char fname[SZ_PATHNAME] # File name to open +char ofname[SZ_PATHNAME] +pointer sp, exp, nodename +int ip, vfd, status, delim + +pointer imx_votable(), imx_table() +int vfnopen(), vfnmapu(), strncmp(), ki_gnode() + +begin + call smark (sp) + call salloc (nodename, SZ_PATHNAME, TY_CHAR) + + exp = NULL # initialize values + nimages = 0 + + # Get the base filename without the '@' prefix. + if (input[1] == '@') + call strcpy (input[2], fname, SZ_PATHNAME) + else + call strcpy (input, fname, SZ_PATHNAME) + + # Map input VFN to OSFN. + ip = 1 + if (strncmp (fname, "http://", 7) == 0) { + call strcpy (fname, ofname, SZ_PATHNAME) + } else { + vfd = vfnopen (fname, READ_ONLY) + status = vfnmapu (vfd, ofname, SZ_PATHNAME) + call vfnclose (vfd, VFN_NOUPDATE) + + # If the file resides on the local node strip the node name, + # returning a legal host system filename as the result. + if (ki_gnode (ofname, Memc[nodename], delim) == 0) + ip = delim + 1 + } + + + # Now process the file. For a VOTable we parse the file and + # extract the acref columns as cached image names, for ascii + # tables we read the URLs directly but likewise returned the + # cache name. + + if (type == IMT_TABLE) + exp = imx_table (ofname[ip], index, nimages) + else if (type == IMT_VOTABLE) + exp = imx_votable (ofname[ip], expr, index, fmt, nimages) + + call sfree (sp) + return (exp) +end + + +# IMX_DEXPAND -- Expand a directory into a list of images. + +pointer procedure imx_dexpand (input, expr, index, extname, extver, ikparams, + sec, nimages) + +char input[ARB] # List of MEF file names +char expr[ARB] # Filtering expression +char index[ARB] # Index range +char extname[ARB] # Extension name +char extver[ARB] # Extension version +char ikparams[ARB] # IKI parameters +char sec[ARB] # Image section +int nimages # Number of output images + +pointer sp, exp, nodename, imname, listout +int dir, len, llen, nim, ip, delim, vfd, status, maxlen +char dirname[SZ_PATHNAME], ofname[SZ_PATHNAME], pdir[SZ_PATHNAME] +char fpath[SZ_PATHNAME], fname[SZ_PATHNAME] + +pointer imx_imexpand () +int vfnopen(), vfnmapu(), ki_gnode(), imx_filetype() +int strlen(), diropen(), isdirectory(), getline() + +begin + call smark (sp) + call salloc (nodename, SZ_PATHNAME, TY_CHAR) + + # Get the base filename without the '@' prefix. + if (input[1] == '@') { + if (input[2] == '@') + call strcpy (input[3], dirname, SZ_PATHNAME) + else + call strcpy (input[2], dirname, SZ_PATHNAME) + } else + call strcpy (input, dirname, SZ_PATHNAME) + + # Remove trailing '/' or '$' from dir + len = strlen (dirname) + if (dirname[len] == '/') + dirname[len] = EOS + + # Map input VFN to OSFN. + ip = 1 + vfd = vfnopen (dirname, READ_ONLY) + status = vfnmapu (vfd, ofname, SZ_PATHNAME) + call vfnclose (vfd, VFN_NOUPDATE) + + # If the file resides on the local node strip the node name, + # returning a legal host system filename as the result. + if (ki_gnode (ofname, Memc[nodename], delim) == 0) + ip = delim + 1 + + call sfree (sp) + + # Otherwise, read through the directory and remove the contents. + dir = diropen (ofname, SKIP_HIDDEN_FILES) + + maxlen = SZ_LISTOUT + call calloc (listout, SZ_LISTOUT, TY_CHAR) + llen = 0 + while (getline (dir, fname) != EOF) { + len = strlen (fname) + fname[len] = '\0' + + len = strlen (ofname) + if (ofname[len] == '/' || ofname[len] == '$') + call sprintf (fpath, SZ_PATHNAME, "%s%s") + else + call sprintf (fpath, SZ_PATHNAME, "%s/%s") + call pargstr (dirname) + call pargstr (fname) + + llen = llen + strlen (fpath) + + # We only test plain files, skip directories. + if (isdirectory (fpath, pdir, SZ_PATHNAME) > 0) + next + + if (imx_filetype (fpath) == IMT_IMAGE) { + + if (input[2] == '@') + imname = imx_imexpand (fpath, expr, index, extname, extver, + ikparams, sec, nim) + else { + call calloc (imname, SZ_PATHNAME, TY_CHAR) + call strcpy (fpath, Memc[imname], SZ_PATHNAME) + } + + if (imname != NULL && Memc[imname] != EOS) { + nimages = nimages + 1 + + if (nimages > 1) { + call strcat (",", Memc[listout], maxlen) + llen = llen + 1 + } + if ((llen + strlen (Memc[imname])) >= maxlen) { + maxlen = maxlen + SZ_LISTOUT + call realloc (listout, maxlen, TY_CHAR) + } + + call strcat (Memc[imname], Memc[listout], maxlen) + llen = llen + strlen (Memc[imname]) + + if (sec[1] != EOS) { + call strcat ("[", Memc[listout], maxlen) + call strcat (sec, Memc[listout], maxlen) + call strcat ("]", Memc[listout], maxlen) + llen = llen + strlen (sec) + 2 + } + + if (imname != NULL) + call mfree (imname, TY_CHAR) + } + } + } + + return (listout) +end + + +# IMX_FETCH -- Fetch the urls from the list. + +procedure imx_fetch (urls, istemp) + +char urls[ARB] #I file of URLS to download +bool istemp #i is input file temporary? + +char osfn[SZ_PATHNAME] +char url_osfn[SZ_PATHNAME] + +int n, envgets() +char nthreads[SZ_FNAME] + +begin + # Get the host pathname of the cache directory. + call fmapfn ("cache$", osfn, SZ_PATHNAME) + call strupk (osfn, osfn, SZ_PATHNAME) + + call fmapfn (urls, url_osfn, SZ_PATHNAME) + call strupk (url_osfn, url_osfn, SZ_PATHNAME) + + n = envgets ("vo_nthreads", nthreads, SZ_FNAME) + + # voget -B -C -D cache$ -b url -N <N> [-t] <infile> + if (istemp) { + call vx_voget (10, "-B", "-C", "-D", osfn, "-b", "url", + "-N", nthreads, "-t", url_osfn) + } else { + call vx_voget (10, "-B", "-C", "-D", osfn, "-b", "url", + "-N", nthreads, "-B", url_osfn) + } +end + + +# IMX_VOTABLE -- Read a VOTable, extracting the column of access references +# as the image list. + +pointer procedure imx_votable (input, expr, index, fmt, nimages) + +char input[ARB] # List of ME file names +char expr[ARB] # Filtering expression +char index[ARB] # Range list of table rows +char fmt[ARB] # Requested file format +int nimages # Number of output images + +pointer vot, exp, ranges +int nranges, tfd +char tfile[SZ_PATHNAME] + +int open() +int imx_decode_ranges() +pointer imx_votselect(), votinit() +bool envgetb() + +begin + # Create a temp file for the parsed access references. + call mktemp ("tmp$vot", tfile, SZ_PATHNAME) + iferr (tfd = open (tfile, NEW_FILE, TEXT_FILE)) { + nimages = 0 + return (NULL) + } + + # Expand the index string into a range structure. + if (index[1] != EOS) { + call calloc (ranges, 3 * SZ_RANGE, TY_INT) + if (imx_decode_ranges (index, Memi[ranges], SZ_RANGE, + nranges, YES) == ERR) { + call eprintf ("error parsing range '%s'\n") + call pargstr (index) + } + } else + ranges = NULL + + # Initialize the VOT struct and parse the table. + vot = votinit (input) + + # Select the column from the VOTable with the access reference. + exp = imx_votselect (vot, tfd, fmt, ranges, nimages) + + call mfree (ranges, TY_INT) + call votclose (vot) # close the files + call close (tfd) + + # Close the temp file and pre-fetch the data if needed. + if (envgetb ("vo_prefetch")) + call imx_fetch (tfile, true) + + return (exp) +end + + +# IMX_VOTSELECT -- Select the access reference column. + +pointer procedure imx_votselect (vot, fd, fmt, ranges, nimages) + +pointer vot #i VOTable struct pointer +int fd #i filename of selected rows +char fmt[ARB] #i file format +pointer ranges #i ranges struct pointer +int nimages #o no. selected images + +pointer exp +int col, len, clen, maxlen +char acref_ucd[SZ_FNAME], imfmt[SZ_FNAME], ucd_col[SZ_FNAME] +char acref[SZ_LINE], ucd[SZ_FNAME], buf[SZ_LINE], cfname[SZ_PATHNAME] +int i, rownum, field, acref_col, acfmt_col + +int strcmp(), strsearch(), strlen(), vx_getNext() +bool imx_in_range() + +begin + # Figure out which table column we want. Note that we assume there + # is only one <RESOURCE> element. The caller may pass in a specific + # column to be used, otherwise look for for the named UCD. + + col = 0 # FIXME + call aclrc (ucd_col, SZ_FNAME) # FIXME + call strcpy ("fits", imfmt, SZ_FNAME) # FIXME + + call aclrc (acref_ucd, SZ_FNAME) + if (col > 0) { + acref_col = col + } else { + if (ucd_col[1] != EOS) + call strcpy (ucd_col, acref_ucd, SZ_FNAME) + else + call strcpy (DEF_ACREF_UCD, acref_ucd, SZ_FNAME) + + # Find the access reference column number. + i = 0 + for (field=VOT_FIELD(vot); field > 0; field=vx_getNext (field)) { + call aclrc (ucd, SZ_FNAME) + call vx_getAttr (field, "ucd", ucd, SZ_FNAME) + if (strcmp (ucd, acref_ucd) == 0) { + acref_col = i + } else if (strcmp (ucd, DEF_FORMAT_UCD) == 0) + acfmt_col = i + i = i + 1 + } + } + + maxlen = SZ_BUF + call calloc (exp, maxlen, TY_CHAR) + + # Download the files. + for (i=0; i < VOT_NROWS(vot); i=i+1) { + call vx_getTableCell (VOT_TDATA(vot), i, acfmt_col, imfmt, SZ_FNAME) + + if (fmt[1] == EOS || (fmt[1] != EOS && strsearch(imfmt, fmt) > 0)) { + call vx_getTableCell (VOT_TDATA(vot), i, acref_col, + acref, SZ_LINE) + + # Do the row selection based on the index string. + rownum = i + 1 + if (ranges != NULL && ! imx_in_range (Memi[ranges], rownum)) + next + + # Generate a unique cache filename based on the URL. + call fcname ("cache$", acref, "url", cfname, SZ_PATHNAME) + + # Append the cache name to the output string. Reallocate the + # string pointer if needed. + clen = strlen (cfname) + if ((len + clen) >= maxlen) { + maxlen = maxlen + SZ_BUF + call realloc (exp, maxlen, TY_CHAR) + } + len = len + clen + + if (nimages == 0) { + call strcpy (cfname, Memc[exp], maxlen) + } else { + call strcat (",", Memc[exp], maxlen) + call strcat (cfname, Memc[exp], maxlen) + } + call aclrc (buf, SZ_LINE) + + # Write the URL to the download file. + call fprintf (fd, "%s\n") + call pargstr (acref) + + nimages = nimages + 1 + } + } + + return (exp) +end + + +# IMX_TABLE -- Read an ASCII text table of URLs and create the list +# of files to process. We apply the list index to do row selection +# and return a list of cached filenames. + +pointer procedure imx_table (input, index, nimages) + +char input[ARB] # List of ME file names +char index[ARB] # Range list of table rows +int nimages # Number of output images + +pointer exp, ranges +int rownum, nranges, fd, len, clen, maxlen +char buf[SZ_LINE], cfname[SZ_PATHNAME] + +int open(), getline(), strlen() +int imx_decode_ranges() +bool imx_in_range(), envgetb() + +begin + call aclrc (buf, SZ_LINE) + iferr (fd = open (input, READ_ONLY, TEXT_FILE)) + call syserr (SYS_FOPEN) + + maxlen = SZ_BUF + call calloc (exp, maxlen, TY_CHAR) + + call calloc (ranges, 3 * SZ_RANGE, TY_INT) + if (index[1] != EOS) { + if (imx_decode_ranges (index, Memi[ranges], SZ_RANGE, + nranges, YES) == ERR) { + call eprintf ("error parsing range '%s'\n") + call pargstr (index) + } + } + + len = 0 + nimages = 0 + rownum = 0 + while (getline (fd, buf) != EOF) { + + # Skip comments and blank lines. + if (buf[1] == '\n' || buf[1] == '#') + next + else + rownum = rownum + 1 + + # Do the row selection based on the index string. + if (index[1] != EOS && ! imx_in_range (Memi[ranges], rownum)) + next + + # Generate a unique cache filename based on the URL. + call fcname ("cache$", buf, "url", cfname, SZ_PATHNAME) + + # Append the cache name to the output string. Reallocate the + # string pointer if needed. + clen = strlen (cfname) + if ((len + clen) >= maxlen) { + maxlen = maxlen + SZ_BUF + call realloc (exp, maxlen, TY_CHAR) + } + len = len + clen + + if (nimages == 0) { + call strcpy (cfname, Memc[exp], maxlen) + } else { + call strcat (",", Memc[exp], maxlen) + call strcat (cfname, Memc[exp], maxlen) + } + call aclrc (buf, SZ_LINE) + + nimages = nimages + 1 + } + + call mfree (ranges, TY_INT) + call close (fd) + + if (envgetb ("vo_prefetch")) + call imx_fetch (input, false) + + return (exp) +end + + +# IMX_EXTNS -- Expand a template of ME files into a list of image extensions. + +int procedure imx_extns (files, exttype, index, extname, extver, + lindex, lname, lver, ikparams, section, expr, err) + +char files[ARB] #I List of ME files +char exttype[ARB] #I Extension type string +char index[ARB] #I Range list of extension indexes +char extname[ARB] #I Patterns for extension names +char extver[ARB] #I Range list of extension versions +int lindex #I List index number? +int lname #I List extension name? +int lver #I List extension version? +char expr[ARB] #I Selection expression +char ikparams[ARB] #I Image kernel parameters +char section[ARB] #I Image section parameters +int err #I Print errors? +int list #O Image list + +int i, fd, create +pointer sp, temp, fname, imname, sec, rindex, rextver, ikp, str +int fntopnb(), fntgfnb() +int imx_decode_ranges(), nowhite(), open() +errchk open, imx_extn, delete + +begin + call smark (sp) + call salloc (temp, SZ_FNAME, TY_CHAR) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (imname, SZ_FNAME, TY_CHAR) + call salloc (sec, SZ_FNAME, TY_CHAR) + call salloc (ikp, SZ_LINE, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + # Expand parameters. + list = fntopnb (files, NO) + call salloc (rindex, 3*SZ_RANGE, TY_INT) + if (imx_decode_ranges (index, Memi[rindex], SZ_RANGE, i, create) == ERR) + call error (1, "Bad index range list") + + rextver = NULL + if (nowhite (extver, Memc[str], SZ_LINE) > 0) { + call salloc (rextver, 3*SZ_RANGE, TY_INT) + if (imx_decode_ranges (Memc[str], Memi[rextver], SZ_RANGE, + i, create) == ERR) + call error (1, "Bad extension version range list") + } + + call aclrc (Memc[ikp], SZ_LINE) + i = nowhite (ikparams, Memc[ikp], SZ_LINE) + + # Expand ME files into list of image extensions in a temp file. + call mktemp ("@tmp$iraf", Memc[temp], SZ_FNAME) + fd = open (Memc[temp+1], NEW_FILE, TEXT_FILE) + while (fntgfnb (list, Memc[fname], SZ_FNAME) != EOF) { + call imgimage (Memc[fname], Memc[imname], SZ_FNAME) + call imgsection (Memc[fname], Memc[sec], SZ_FNAME) + + call imx_extn (fd, Memc[imname], exttype, expr, rindex, extname, + rextver, lindex, lname, lver, Memc[ikp], section, + create, err) + } + call fntclsb (list) + call close (fd) + + # Return list. + list = fntopnb (Memc[temp], NO) + call delete (Memc[temp+1]) + call sfree (sp) + + return (list) +end + + +# IMX_EXTN -- Expand a single ME file into a list of image extensions. +# The image extensions are written to the input file descriptor. + +procedure imx_extn (fd, fname, exttype, expr, index, extname, extver, lindex, + lname, lver, ikparams, section, create, err) + +int fd #I File descriptor for list +char fname[SZ_FNAME] #I File image name (without kernel or image sec) +char exttype[SZ_FNAME] #I File extension type +char expr[ARB] #I Selection expression +pointer index #I Range list of extension indexes +char extname[ARB] #I Pattern for extension names +pointer extver #I Range list of extension versions +int lindex #I List index number? +int lname #I List extension name? +int lver #I List extension version? +char ikparams[ARB] #I Image kernel parameters +char section[ARB] #I Image section +int create #I Create names from index range? +int err #I Print errors? + +pointer sp, image, name, type, str, im +int i, j, ver + +pointer immap() +int imx_get_next_number(), errcode(), imgeti(), stridxs(), strcmp() +bool imx_in_range(), imx_extmatch(), imx_matchexpr(), imx_sifmatch() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (type, SZ_FNAME, TY_CHAR) + call salloc (name, SZ_LINE, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + i = -1 + while (imx_get_next_number (Memi[index], i) != EOF) { + j = stridxs ("[", fname) + if (j > 0) { + if (i > 0) + break + call strcpy (fname, Memc[image], SZ_FNAME) + } else { + call sprintf (Memc[image], SZ_FNAME, "%s[%d]") + call pargstr (fname) + call pargi (i) + } + + if (section[1] != EOS) { + call strcat ("[", Memc[image], SZ_FNAME) + call strcat (section, Memc[image], SZ_FNAME) + call strcat ("]", Memc[image], SZ_FNAME) + } + + # We know the extension doesn't exist, generate the name. + if (create == YES) { + call fprintf (fd, "%s") + call pargstr (Memc[image]) + if (section[1] != EOS) { + call fprintf (fd, "[%s]") + call pargstr (section) + } + call fprintf (fd, "\n") + next + } + + + iferr (im = immap (Memc[image], READ_ONLY, 0)) { + switch (errcode()) { + case SYS_FXFRFEOF: + if (i == 1) { + if (extname[1] == EOS && imx_sifmatch (fname, expr)) { + call fprintf (fd, "%s\n") + call pargstr (fname) + next + } else + break + } + break + case SYS_IKIEXTN: + next + case SYS_IKIOPEN: + switch (i) { + case 0: + next + case 1: + if (err == YES) + call erract (EA_WARN) + break + default: + break + } + default: + call erract (EA_ERROR) + } + } + + + # Check the extension type. [NOT USED] + if (exttype[1] != EOS) { + iferr (call imgstr (im, "xtension", Memc[type], SZ_FNAME)) + Memc[type] = EOS + if (Memc[type] != EOS && strcmp (Memc[type], exttype) != 0) { + call imunmap (im) + next + } + } + +#call eprintf("imx_extn: name='%s' ver='%s' expr='%s' sec='%s' iki='%s'\n") +# call pargstr (extname) ; call pargstr (Memc[extver]) ; +# call pargstr (expr) ; call pargstr (section) ; +# call pargstr (ikparams) ; + + # Check the extension name. + if (extname[1] != EOS) { + iferr (call imgstr (im, "extname", Memc[name], SZ_FNAME)) + Memc[name] = EOS + if (!imx_extmatch (Memc[name], extname)) { + call imunmap (im) + next + } + } + + # Check the extension version. + if (extver != NULL) { + iferr (ver = imgeti (im, "extver")) { + call imunmap (im) + next + } + if (!imx_in_range (Memi[extver], ver)) { + call imunmap (im) + next + } + } + + # Check the selection expression. + if (expr[1] != EOS) { + if (!imx_matchexpr (im, expr)) { + call imunmap (im) + next + } + } + + + # Set the extension name and version. + if (lname == YES) { + iferr (call imgstr (im, "extname", Memc[name], SZ_LINE)) + Memc[name] = EOS + } else + Memc[name] = EOS + if (lver == YES) { + iferr (ver = imgeti (im, "extver")) + ver = INDEFI + } else + ver = INDEFI + + # Write the image name. + call fprintf (fd, fname) + if (j == 0) { + if (lindex == YES || (Memc[name] == EOS && IS_INDEFI(ver))) { + call fprintf (fd, "[%d]") + call pargi (i) + } + if (Memc[name] != EOS) { + call fprintf (fd, "[%s") + call pargstr (Memc[name]) + if (!IS_INDEFI(ver)) { + call fprintf (fd, ",%d") + call pargi (ver) + } + if (ikparams[1] != EOS) { + call fprintf (fd, ",%s") + call pargstr (ikparams) + } + call fprintf (fd, "]") + } else if (!IS_INDEFI(ver)) { + call fprintf (fd, "[extver=%d") + call pargi (ver) + if (ikparams[1] != EOS) { + call fprintf (fd, ",%s") + call pargstr (ikparams) + } + call fprintf (fd, "]") + } else if (ikparams[1] != EOS) { + call fprintf (fd, "[%s]%%") + call pargstr (ikparams) + } + } + if (section[1] != EOS) { + call fprintf (fd, "[%s]") + call pargstr (section) + } + call fprintf (fd, "\n") + + call imunmap (im) + } + + call sfree (sp) +end + + +# IMX_DECODE_RANGES -- Parse a string containing a list of integer numbers or +# ranges, delimited by either spaces or commas. Return as output a list +# of ranges defining a list of numbers, and the count of list numbers. +# Range limits must be positive nonnegative integers. ERR is returned as +# the function value if a conversion error occurs. The list of ranges is +# delimited by EOLIST. + +int procedure imx_decode_ranges (range_string, ranges, max_ranges, + nvalues, create) + +char range_string[ARB] # Range string to be decoded +int ranges[3, max_ranges] # Range array +int max_ranges # Maximum number of ranges +int nvalues # The number of values in the ranges +int create # generate range string? + +int ip, nrange, first, last, step, ctoi() + +begin + create = NO + if (range_string[1] == '+') { + ip = 2 + create = YES + } else + ip = 1 + nvalues = 0 + + do nrange = 1, max_ranges - 1 { + # Defaults to all nonnegative integers + first = FIRST + last = LAST + step = STEP + + # Skip delimiters + while (IS_WHITE(range_string[ip]) || range_string[ip] == ',') + ip = ip + 1 + + # Get first limit. + # Must be a number, '-', 'x', or EOS. If not return ERR. + if (range_string[ip] == EOS) { # end of list + if (nrange == 1) { + # Null string defaults + ranges[1, 1] = first + ranges[2, 1] = last + ranges[3, 1] = step + ranges[1, 2] = EOLIST + nvalues = MAX_INT + return (OK) + } else { + ranges[1, nrange] = EOLIST + return (OK) + } + } else if (range_string[ip] == '-') + ; + else if (range_string[ip] == 'x') + ; + else if (IS_DIGIT(range_string[ip])) { # ,n.. + if (ctoi (range_string, ip, first) == 0) + return (ERR) + } else + return (ERR) + + # Skip delimiters + while (IS_WHITE(range_string[ip]) || range_string[ip] == ',') + ip = ip + 1 + + # Get last limit + # Must be '-', or 'x' otherwise last = first. + if (range_string[ip] == 'x') + ; + else if (range_string[ip] == '-') { + ip = ip + 1 + while (IS_WHITE(range_string[ip]) || range_string[ip] == ',') + ip = ip + 1 + if (range_string[ip] == EOS) + ; + else if (IS_DIGIT(range_string[ip])) { + if (ctoi (range_string, ip, last) == 0) + return (ERR) + } else if (range_string[ip] == 'x') + ; + else + return (ERR) + } else + last = first + + # Skip delimiters + while (IS_WHITE(range_string[ip]) || range_string[ip] == ',') + ip = ip + 1 + + # Get step. + # Must be 'x' or assume default step. + if (range_string[ip] == 'x') { + ip = ip + 1 + while (IS_WHITE(range_string[ip]) || range_string[ip] == ',') + ip = ip + 1 + if (range_string[ip] == EOS) + ; + else if (IS_DIGIT(range_string[ip])) { + if (ctoi (range_string, ip, step) == 0) + ; + if (step == 0) + return (ERR) + } else if (range_string[ip] == '-') + ; + else + return (ERR) + } + + # Output the range triple. + ranges[1, nrange] = first + ranges[2, nrange] = last + ranges[3, nrange] = step + nvalues = nvalues + abs (last-first) / step + 1 + } + + return (ERR) # ran out of space +end + + +# IMX_GET_NEXT_NUMBER -- Given a list of ranges and the current file number, +# find and return the next file number. Selection is done in such a way +# that list numbers are always returned in monotonically increasing order, +# regardless of the order in which the ranges are given. Duplicate entries +# are ignored. EOF is returned at the end of the list. + +int procedure imx_get_next_number (ranges, number) + +int ranges[ARB] # Range array +int number # Both input and output parameter + +int ip, first, last, step, next_number, remainder + +begin + # If number+1 is anywhere in the list, that is the next number, + # otherwise the next number is the smallest number in the list which + # is greater than number+1. + + number = number + 1 + next_number = MAX_INT + + for (ip=1; ranges[ip] != EOLIST; ip=ip+3) { + first = min (ranges[ip], ranges[ip+1]) + last = max (ranges[ip], ranges[ip+1]) + step = ranges[ip+2] + if (step == 0) + call error (1, "Step size of zero in range list") + if (number >= first && number <= last) { + remainder = mod (number - first, step) + if (remainder == 0) + return (number) + if (number - remainder + step <= last) + next_number = number - remainder + step + } else if (first > number) + next_number = min (next_number, first) + } + + if (next_number == MAX_INT) + return (EOF) + else { + number = next_number + return (number) + } +end + + +# IMX_EXTMATCH -- Match extname against a comma-delimited list of patterns. + +bool procedure imx_extmatch (extname, patterns) + +char extname[ARB] #I Extension name to match +char patterns[ARB] #I Comma-delimited list of patterns +bool stat #O Match? + +int i, j, k, sz_pat, strlen(), patmake(), patmatch(), nowhite() +pointer sp, patstr, patbuf + +begin + stat = false + + sz_pat = strlen (patterns) + if (sz_pat == 0) + return (stat) + sz_pat = sz_pat + SZ_LINE + + call smark (sp) + call salloc (patstr, sz_pat, TY_CHAR) + call salloc (patbuf, sz_pat, TY_CHAR) + + i = nowhite (patterns, Memc[patstr], sz_pat) + if (i == 0) + stat = true + else if (i == 1 && Memc[patstr] == '*') + stat = true + else { + i = 1 + for (j=i;; j=j+1) { + if (patterns[j] != ',' && patterns[j] != EOS) + next + if (j - i > 0) { + if (j-i == 1 && patterns[i] == '*') { + stat = true + break + } + call strcpy (patterns[i], Memc[patstr+1], j-i) + Memc[patstr] = '^' + Memc[patstr+j-i+1] = '$' + Memc[patstr+j-i+2] = EOS + k = patmake (Memc[patstr], Memc[patbuf], sz_pat) + if (patmatch (extname, Memc[patbuf]) > 0) { + stat = true + break + } + } + if (patterns[j] == EOS) + break + i = j + 1 + } + } + + call sfree (sp) + return (stat) +end + + +# IMX_IN_RANGE -- Test number to see if it is in range. +# If the number is INDEFI then it is mapped to the maximum integer. + +bool procedure imx_in_range (ranges, number) + +int ranges[ARB] # Range array +int number # Number to be tested against ranges + +int ip, first, last, step, num + +begin + if (IS_INDEFI (number)) + num = MAX_INT + else + num = number + + for (ip=1; ranges[ip] != NULL; ip=ip+3) { + first = min (ranges[ip], ranges[ip+1]) + last = max (ranges[ip], ranges[ip+1]) + step = ranges[ip+2] + if (num >= first && num <= last) + if (mod (num - first, step) == 0) + return (true) + } + + return (false) +end diff --git a/sys/imio/imt/imxexpr.x b/sys/imio/imt/imxexpr.x new file mode 100644 index 00000000..55c185ef --- /dev/null +++ b/sys/imio/imt/imxexpr.x @@ -0,0 +1,222 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <evexpr.h> +include <imset.h> +include <imhdr.h> +include <ctype.h> +include <lexnum.h> + +define LEN_USERAREA 28800 # allow for the largest possible header +define SZ_IMAGENAME 63 # max size of an image name +define SZ_FIELDNAME 31 # max size of a field name + +define DEBUG FALSE + + + +# IMX_MATCHEXPR -- Match the open image descriptor against the expression. + +bool procedure imx_matchexpr (im, expr) + +pointer im #I image descriptor +char expr[ARB] #I expression string + +bool stat +char val[SZ_LINE] +pointer o + +pointer imt_im # getop common +char imt_image[SZ_IMAGENAME] +char imt_field[SZ_FIELDNAME] +common /imtgop/ imt_im, imt_image, imt_field + +pointer evexpr() +extern imx_getop() +int locpr() +errchk locpr, evexpr + +begin + call aclrc (val, SZ_LINE) + call aclrc (imt_image, SZ_IMAGENAME) + call aclrc (imt_field, SZ_FIELDNAME) + + imt_im = im + if (expr[1] != EOS) { + iferr { + o = evexpr (expr, locpr (imx_getop), 0) + call imx_encodeop (o, val, SZ_LINE) + stat = O_VALB(o) + call xev_freeop (o) + call mfree (o, TY_STRUCT) + } then + stat = FALSE + + if (DEBUG) { + call eprintf ("expr = '%s' %b\n") + call pargstr (expr) ; call pargb (stat) + } + + return (stat) + } + + return (FALSE) +end + + +# IMX_SIFMATCH -- Check whether the file is a simple image matching the +# expression. + +bool procedure imx_sifmatch (fname, expr) + +char fname[ARB] #I image name +char expr[ARB] #I expression string + +pointer im +bool stat + +pointer immap() +bool imx_matchexpr (), streq() +errchk immap + +begin + if (expr[1] == EOS) + return (TRUE) + + iferr (im = immap (fname, READ_ONLY, 0)) { + return (FALSE) + } + + if (streq (expr, "yes")) + stat = TRUE + else + stat = imx_matchexpr (im, expr) + call imunmap (im) + + return (stat) +end + + +# IMX_GETOP -- Satisfy an operand request from EVEXPR. In this context, +# operand names refer to the fields of the image header. The following +# special operand names are recognized: +# +# . a string literal, returned as the string "." +# $ the value of the current field +# $F the name of the current field +# $I the name of the current image +# $T the current time, expressed as an integer +# +# The companion procedure HE_GETOPSETIMAGE is used to pass the image pointer +# and image and field names. + +procedure imx_getop (operand, o) + +char operand[ARB] # operand name +pointer o # operand (output) + +pointer imt_im # getop common +char imt_image[SZ_IMAGENAME] +char imt_field[SZ_FIELDNAME] +common /imtgop/ imt_im, imt_image, imt_field +bool streq() +long clktime() +errchk imx_getfield + +begin + if (streq (operand, ".")) { + call xev_initop (o, 1, TY_CHAR) + call strcpy (".", O_VALC(o), 1) + + } else if (streq (operand, "$")) { + call imx_getfield (imt_im, imt_field, o) + + } else if (streq (operand, "$F")) { + call xev_initop (o, SZ_FIELDNAME, TY_CHAR) + call strcpy (imt_field, O_VALC(o), SZ_FIELDNAME) + + } else if (streq (operand, "$I")) { + call xev_initop (o, SZ_IMAGENAME, TY_CHAR) + call strcpy (imt_image, O_VALC(o), SZ_IMAGENAME) + + } else if (streq (operand, "$T")) { + # Assignment of long into int may fail on some systems. Maybe + # should use type string and let database convert to long... + + call xev_initop (o, 0, TY_INT) + O_VALI(o) = clktime (long(0)) + + } else + call imx_getfield (imt_im, operand, o) +end + + +# IMX_GETFIELD -- Return the value of the named field of the image header as +# an EVEXPR type operand structure. + +procedure imx_getfield (im, field, o) + +pointer im # image descriptor +char field[ARB] # name of field to be returned +pointer o # pointer to output operand + +bool imgetb() +int ftype, imgeti(), imgftype() +real imgetr() + +begin + iferr { + ftype = imgftype (im, field) + } then { + call xev_initop (o, SZ_LINE, TY_CHAR) # keyword not found + call aclrc (O_VALC(o), SZ_LINE) + return + } + + switch (ftype) { + case TY_BOOL: + call xev_initop (o, 0, TY_BOOL) + O_VALB(o) = imgetb (im, field) + + case TY_SHORT, TY_INT, TY_LONG: + call xev_initop (o, 0, TY_INT) + O_VALI(o) = imgeti (im, field) + + case TY_REAL, TY_DOUBLE, TY_COMPLEX: + call xev_initop (o, 0, TY_REAL) + O_VALR(o) = imgetr (im, field) + + default: + call xev_initop (o, SZ_LINE, TY_CHAR) + call imgstr (im, field, O_VALC(o), SZ_LINE) + } +end + + +# IMX_ENCODEOP -- Encode an operand as returned by EVEXPR as a string. EVEXPR +# operands are restricted to the datatypes bool, int, real, and string. + +procedure imx_encodeop (o, outstr, maxch) + +pointer o # operand to be encoded +char outstr[ARB] # output string +int maxch # max chars in outstr + +begin + switch (O_TYPE(o)) { + case TY_BOOL: + call sprintf (outstr, maxch, "%b") + call pargb (O_VALB(o)) + case TY_CHAR: + call sprintf (outstr, maxch, "%s") + call pargstr (O_VALC(o)) + case TY_INT: + call sprintf (outstr, maxch, "%d") + call pargi (O_VALI(o)) + case TY_REAL: + call sprintf (outstr, maxch, "%g") + call pargr (O_VALR(o)) + default: + call error (1, "unknown expression datatype") + } +end diff --git a/sys/imio/imt/imxftype.x b/sys/imio/imt/imxftype.x new file mode 100644 index 00000000..e083f032 --- /dev/null +++ b/sys/imio/imt/imxftype.x @@ -0,0 +1,119 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <syserr.h> +include <imhdr.h> +include "imx.h" + + +# IMX_FILETYPE -- Determine the file type. + +int procedure imx_filetype (fname) + +char fname[ARB] #i file name + +char img[SZ_FNAME], name[SZ_FNAME], buf[SZ_LINE] + +int i, nchars, fd +bool is_http_list + +int errcode(), open(), read(), access(), imaccess() +int strncmp(), strsearch(), isdirectory() +pointer im, immap() + +begin + # Check for a URL. + if (strncmp ("http://", fname, 7) == 0) + return (IMT_URL) + + call aclrc (name, SZ_FNAME) + if (fname[1] == '@') + call strcpy (fname[2], name, SZ_FNAME) + else + call strcpy (fname, name, SZ_FNAME) + + # See if it is a directory. + if (isdirectory (name, buf, SZ_LINE) > 0) + return (IMT_DIR) + + # Check for concatenated strings. + if (strsearch (fname, "//") > 0) { + if (isdirectory (fname, buf, SZ_LINE) > 0) + return (IMT_DIR) + else + return (IMT_FILE) + } + + call aclrc (img, SZ_FNAME) # PHU + call sprintf (img, SZ_FNAME, "%s[0]") + call pargstr (name) + + # Get a peek at the file. + call aclrc (buf, SZ_LINE) + if (imaccess (name, READ_ONLY) == YES || + imaccess (img, READ_ONLY) == YES) { + return (IMT_IMAGE); + } else if (access (name, 0, 0) == YES) { + fd = open (name, READ_ONLY, TEXT_FILE) + nchars = read (fd, buf, SZ_LINE) + call strupr (buf) + call close (fd) + } + + # See if it might be an image of some kind. + if (strncmp (buf, "SIMPLE", 6) == 0) { + + ifnoerr (im = immap (name, READ_ONLY, 0)) { # SIF, OIF, etc + call imunmap (im) + return (IMT_IMAGE) + } + + do i = 0, 1 { # MEF + call aclrc (img, SZ_FNAME) + call sprintf (img, SZ_FNAME, "%s[%d]") + call pargstr (name) + call pargi (i) + + iferr (im = immap (img, READ_ONLY, 0)) { + switch (errcode()) { + case SYS_FXFRFEOF: + break + case SYS_IKIEXTN: + next + case SYS_IKIOPEN: + if (i == 0) + next + break + default: + call erract (EA_ERROR) + } + } else { + call imunmap (im) + return (IMT_IMAGE) + } + } + + } else { + + # If we get this far, we have a file of some kind. See if it is a + # list of URLs, a VOTable, or a plain file. + is_http_list = FALSE + fd = open (name, READ_ONLY, TEXT_FILE) + do i = 1, 10 { + call aclrc (buf, SZ_LINE) + nchars = read (fd, buf, SZ_LINE) + call strupr (buf) + if (strsearch (buf, "VOTABLE") > 0) { + call close (fd) + return (IMT_VOTABLE) + } else if (strncmp (buf, "http://", 7) == 0) + is_http_list = TRUE + } + call close (fd) + } + + if (is_http_list) + return (IMT_TABLE) + else + return (IMT_FILE) +end diff --git a/sys/imio/imt/imxparse.x b/sys/imio/imt/imxparse.x new file mode 100644 index 00000000..f26f0918 --- /dev/null +++ b/sys/imio/imt/imxparse.x @@ -0,0 +1,203 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include <imhdr.h> +include "imx.h" + + +define IMT_INDEX 1 +define IMT_NAME 2 +define IMT_VER 3 +define IMT_EXPR 4 + +define DEBUG FALSE + + + +# IMX_PARSE -- Parse a filename to extract index ranges, extension names, +# versions and filtering expressions. + +int procedure imx_parse (input, fname, index, extname, extver, + expr, sec, ikparams, maxch) + +char input[ARB] #i template string ptr +char fname[ARB] #o file name +char index[ARB] #o index range string +char extname[ARB] #o extension name +char extver[ARB] #o extension version +char expr[ARB] #o filtering expression string +char sec[ARB] #o image section string +char ikparams[ARB] #o image kernel section params +int maxch #i max chars in string params + +pointer im +int nchars, ip, idx +char comma, lexpr[SZ_LINE], subex[SZ_LINE], name[SZ_PATHNAME] + +int imx_breakout(), imx_next_expr(), imx_expr_type(), stridx() +pointer immap() + +begin + call aclrc (expr, maxch) # initialize + call aclrc (index, maxch) + call aclrc (fname, maxch) + call aclrc (extver, maxch) + call aclrc (extname, maxch) + call aclrc (ikparams, maxch) + call aclrc (lexpr, SZ_LINE) + + + # Separate the filename from the expression string. + nchars = imx_breakout (input, NO, fname, lexpr, sec, ikparams, maxch) + + # Parse into sub-expression strings, breaking it up into the + # appropriate form depending on the contents. + if (lexpr[1] != EOS) { + ip = 1 + while (imx_next_expr (lexpr, ip, subex, maxch) != EOS) { + + if (DEBUG) { + call eprintf ("parse subex = '%s'\t\t'%s'\n") + call pargstr (subex) ; call pargstr (lexpr) + } + + switch (imx_expr_type (subex)) { + case IMT_INDEX: + call strcpy (subex, index, maxch) + case IMT_NAME: + call strcpy (subex, extname, maxch) + case IMT_VER: + comma = ',' + idx = stridx (comma, subex) + call strcpy (subex[idx+1], extver, maxch) + subex[idx] = '\0' + call strcpy (subex, extname, maxch) + case IMT_EXPR: + if (expr[1] != EOS) { + call strcat ("||", expr, maxch) + call strcat (subex, expr, maxch) + } else + call strcpy (subex, expr, maxch) + default: + call error (1, "unknown expression type") + } + + ip = ip + 1 + } + } + + if (DEBUG) { + call eprintf ("final expr = '%s' index = '%s' sec = '%s'\n") + call pargstr (expr) + call pargstr (index) + call pargstr (sec) + } + + call aclrc (name, SZ_PATHNAME) + if (fname[1] == '@') + call strcpy (fname[2], name, SZ_PATHNAME) + else + call strcpy (fname, name, SZ_PATHNAME) + if (index[1] != EOS) { + call strcat ("[", name, SZ_PATHNAME) + call strcat (index, name, SZ_PATHNAME) + call strcat ("]", name, SZ_PATHNAME) + } + if (sec[1] != EOS) { + call strcat ("[", name, SZ_PATHNAME) + call strcat (sec, name, SZ_PATHNAME) + call strcat ("]", name, SZ_PATHNAME) + } + +# iferr { +# im = immap (name, READ_ONLY, 0) +# call imunmap (im) +# } then +# ; + + return (nchars) +end + + +# IMX_NEXT_EXPR -- Get the next sub expression from the string. Expressions +# are delimited by semicolons, the location in the expression string is +# updated. + +int procedure imx_next_expr (expr, ip, subex, maxch) + +char expr[ARB] #i input expression string +int ip #u location in expr +char subex[ARB] #o sub expression string +int maxch #i max size of subexpr string + +char op + +begin + if (expr[ip] == EOS) + return (EOS) + + # Skip leading whitespace/delimiters. + while (IS_WHITE(expr[ip]) || expr[ip] == ';') + ip = ip + 1 + + op = 1 # copy until EOS or next delimiter + while (expr[ip] != EOS && expr[ip] != ';' && expr[ip] != ']') { + subex[op] = expr[ip] + ip = ip + 1 + op = op + 1 + } + subex[op] = EOS + + if (expr[ip] == ']') + ip = ip + 1 + + return (ip) +end + + +# IMX_EXPR_TYPE -- Determine the type of expression we have. A range list +# is assumed to be an extension index list; a single alphabetic word is +# assumed to be an extension name, if followed by a numeric value it also +# contains an extension version; anything else is a selection expression. + +int procedure imx_expr_type (expr) + +char expr[ARB] #i expression + +int ip, len +char ch +int strlen (), stridxs(), stridx() + +begin + len = strlen (expr) + + # [<expr>] + ch = expr[1] + if ((IS_ALNUM(expr[1]) || stridx (ch, "('\"") > 0) && + stridxs ("?=:()<>&|@", expr) != 0) + return (IMT_EXPR) + + # [extname,extver] + ch = ',' + if (IS_ALPHA(expr[1]) && IS_DIGIT(expr[len]) && stridx (ch, expr) > 0) + return (IMT_VER) + + # [extname] + if (IS_ALPHA(expr[1]) && stridx (ch, expr) == 0) + return (IMT_NAME) + + # [index] or [index_range] + if ((IS_DIGIT(expr[1])) || + ((expr[1] == '+' || expr[1] == '-') && IS_DIGIT(expr[2]))) { + for (ip=1; expr[ip] != EOS; ip = ip + 1) { + ch = expr[ip] + if (! IS_DIGIT(ch)) { + if (stridx (ch, "-x,+") == 0) + return (IMT_EXPR) + } + } + return (IMT_INDEX) + } + + return (0) +end diff --git a/sys/imio/imt/imxpreproc.x b/sys/imio/imt/imxpreproc.x new file mode 100644 index 00000000..b0faccfc --- /dev/null +++ b/sys/imio/imt/imxpreproc.x @@ -0,0 +1,539 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "imx.h" + +define DEBUG FALSE +define SZ_PREFIX 2 + + +pointer procedure imx_preproc (template) + +char template[ARB] #i input template string + +pointer exp, pre, out, op, list +char file[SZ_PATHNAME] +char mods[SZ_LINE], fname[SZ_LINE] +int i, j, osize, len, llen, nmods + +define output {Memc[out+op]=$1;op=op+1} +define outstr {len=strlen($1);for(j=1;j<=len;j=j+1)output($1[j])} +define outcomma {if(($1))output(',')} + +pointer imx_fnexpand (), imx_preproc_list() +pointer fntopnb() +int fntlenb(), fntgfnb(), strlen(), strsearch(), strncmp(), imx_split() + +begin + # First Pass: Do any filename expansion in the template, maintaining + # the '@' prefix and any modifiers. The result is a comma-delimited + # list we process later to expand further. + + exp = imx_fnexpand (template) + + # Second Pass: Process the matched list to expand the '@' files and + # modifiers into a simple comma-delimited list the FNT interface + # will process. + + pre = imx_preproc_list (Memc[exp]) + + # Third Pass: Handle concatenation in the filenames. + if ((strncmp (Memc[pre],"http://",7) == 0) || + (strncmp (Memc[pre],"file://",7) == 0)) { + osize = strlen (Memc[pre]) + call calloc (out, osize, TY_CHAR) + call strcpy (Memc[pre], Memc[out], osize) + + } else if (strsearch(Memc[pre],"//") > 0 && + strsearch(Memc[pre],".fits") > 0) { + + # FIXME -- Need to handle the case of concatenation with + # a MEF file. Problem is, expanding the MEF requires we + # recursively call ourselves to expand the image so we + # need to do some restructuring. For example, + # + # foo // @mef.fits -> foomef.fits[1],foomef.fits[2], .... + # @mef.fits // foo -> meffoo.fits[1],meffoo.fits[2], .... + + call error (0, "Image expansion/concatenation not yet supported.") + + + } else if (strsearch (Memc[pre], "//") > 0) { + + nmods = imx_split (Memc[pre], fname, mods, SZ_LINE) + list = fntopnb (fname, YES) + llen = fntlenb (list) + + osize = strlen (Memc[pre]) + call calloc (out, osize * 2, TY_CHAR) + + op = 0 + for (i=0; i < llen; i=i+1) { + call aclrc (file, SZ_PATHNAME) + if (fntgfnb (list, file, SZ_PATHNAME) == EOF) + break + + if ((op + strlen (file) + strlen (mods) + 3) >= osize) { + osize = osize + SZ_LINE + call realloc (out, osize, TY_CHAR) + } + + # FIXME ??? + #outcomma (i > 0); output ('@'); outstr(file) ; outstr(mods) + outcomma (i > 0); outstr(file) ; outstr(mods) + } + output ('\0') + call fntclsb (list) + + } else { + osize = strlen (Memc[pre]) + call calloc (out, osize, TY_CHAR) + call strcpy (Memc[pre], Memc[out], osize) + } + + if (DEBUG) { + call eprintf ("pre exp = '%s'\n") ; call pargstr (Memc[exp]) + call eprintf ("pre pre = '%s'\n") ; call pargstr (Memc[pre]) + call eprintf ("pre out = '%s'\n") ; call pargstr (Memc[out]) + } + + call mfree (exp, TY_CHAR) # clean up + call mfree (pre, TY_CHAR) + + return (out) +end + + +# IMX_FNEXPAND -- Do any filename expansion in the template, maintaining the +# '@' prefix and any modifiers. The result is a comma-delimited list we +# process later to expand further. + +pointer procedure imx_fnexpand (template) + +char template[ARB] #i input template string + +pointer elem, ep, op, out, listp, sz_out, op_start, op_end +int i, j, ip, in, len, llen, nelem, fi, fo +char prefix[SZ_PREFIX], fname[SZ_PATHNAME], mods[SZ_LINE] +char left[SZ_PATHNAME], right[SZ_PATHNAME] +char file[SZ_PATHNAME], cfname[SZ_PATHNAME], osfn[SZ_PATHNAME] + +define output {Memc[op]=$1;op=op+1} +define outstr {len=strlen($1);for(j=1;j<=len;j=j+1)output($1[j])} + +int fntopnb(), fntgfnb(), fntlenb(), strlen(), stridxs(), strsearch() +int imx_get_element(), strncmp(), stridx() + +begin + # Allocate an intial string buffer. + call calloc (out, SZ_FNT, TY_CHAR) + call calloc (elem, SZ_FNT, TY_CHAR) + + in = 1 + nelem = 0 + op = out + op_start = out + op_end = out + SZ_FNT - 1 + sz_out = SZ_FNT + + while (imx_get_element (template, in, Memc[elem], SZ_FNT) != EOS) { + + ep = elem + nelem = nelem + 1 + outcomma(nelem > 1) + + call aclrc (prefix, SZ_PREFIX) + call aclrc (fname, SZ_PATHNAME) + call aclrc (mods, SZ_LINE) + + # Gather any prefix '@' symbols. + if (Memc[elem] == '@') { + for (i=1; Memc[ep] == '@'; i=i+1) { + prefix[i] = Memc[ep] + ep = ep + 1 + } + } else { + ip = stridx ('@', Memc[elem]) + if (ip > 1) { + call strcpy (Memc[elem], prefix, ip-1) + ep = elem + ip - 1 + prefix[ip] = EOS + call strcat ("//", prefix[ip], SZ_PREFIX) + } + } + + # Get the filename component up to the EOS or the modifiers. + for (i=1; Memc[ep] != '[' && Memc[ep] != EOS; i=i+1) { + fname[i] = Memc[ep] + ep = ep + 1 + } + + if (strncmp ("http://", fname, 7) == 0) { + call fmapfn ("cache$", osfn, SZ_PATHNAME) + call strupk (osfn, osfn, SZ_PATHNAME) + + #call fcadd (osfn, fname, "fits", cfname, SZ_PATHNAME) + call fcadd (osfn, fname, "", cfname, SZ_PATHNAME) + + call strcpy (cfname, fname, SZ_PATHNAME) + + } else if (strncmp ("file://", fname, 7) == 0) { + fi = 8 + if (strncmp ("file:///localhost", fname, 17) == 0) + fi = 18 + else if (strncmp ("file://localhost", fname, 16) == 0) + fi = 17 + + for (fo=1; fname[fi] != EOS; fi=fi+1) { + if (fname[fi] == '/' && fname[fi+1] == '/') + fi = fi + 1 + cfname[fo] = fname[fi] + fo = fo + 1 + } + call strcpy (cfname, fname, SZ_PATHNAME) + } + + # Get the modifier strings. + for (i=1; Memc[ep] != EOS ; i=i+1) { + mods[i] = Memc[ep] + ep = ep + 1 + } + + + if (DEBUG) { + call eprintf ("fnexp: '%s' --> '%s' '%s' '%s'\n") + call pargstr (Memc[elem]); call pargstr (prefix); + call pargstr (fname); call pargstr (mods) + } + + # Expand wildcards if needed. + if (stridxs("*?", fname) > 0) { + + # FIXME - Need to do concatenation here ...?? + if (strsearch (fname, "//") > 0) { + call aclrc (left, SZ_PATHNAME) + call aclrc (right, SZ_PATHNAME) + + # Gather the left and right side of a concatenation with + # wildcards. Expand the side with the wildcard but + # maintain the concatenation so we keep the previous + # behavior in how these processed. + for (ip=1; fname[ip] != '/'; ip=ip+1) + left[ip] = fname[ip] + ip = ip + 2 + for (i=1; fname[ip] != EOS; ip=ip+1) { + right[i] = fname[ip] + i = i + 1 + } + + if (stridxs("*?", left) > 0) { + listp = fntopnb (left, YES) + llen = fntlenb (listp) + for (i=0; i < llen; i=i+1) { + call aclrc (file, SZ_PATHNAME) + if (fntgfnb (listp, file, SZ_PATHNAME) == EOF) + break + outcomma (i > 0) + outstr(prefix) + outstr(file) ; outstr("//") ; outstr(right) + } + call fntclsb (listp) + } else { + listp = fntopnb (right, YES) + llen = fntlenb (listp) + for (i=0; i < llen; i=i+1) { + call aclrc (file, SZ_PATHNAME) + if (fntgfnb (listp, file, SZ_PATHNAME) == EOF) + break + outcomma (i > 0) + outstr(prefix) + outstr(left) ; outstr("//") ; outstr(file) + } + call fntclsb (listp) + } + next + + } else { + listp = fntopnb (fname, YES) + llen = fntlenb (listp) + for (i=0; i < llen; i=i+1) { + call aclrc (file, SZ_PATHNAME) + if (fntgfnb (listp, file, SZ_PATHNAME) == EOF) + break + outcomma ( i > 0) + outstr(prefix) ; outstr(file) ; outstr(mods) + + + # Reallocate the output string if needed. + if ((op_end - op) < SZ_FNAME || op >= op_end) { + sz_out = sz_out + SZ_FNT + len = (op - out - 1) + + call calloc (op_start, sz_out, TY_CHAR) + call amovc (Memc[out], Memc[op_start], len) + for (op=op_start; Memc[op] != EOS; ) + op = op + 1 + + op_end = op_start + sz_out + call mfree (out, TY_CHAR) + out = op_start + } + } + call fntclsb (listp) + } + + + } else { + outstr(prefix) ; outstr(fname) ; outstr(mods) + } + + call aclrc (Memc[elem], SZ_FNT) + } + output ('\0') + + call mfree (elem, TY_CHAR) + return (out) +end + + +# IMX_PREPROC_LIST -- Process the expanded filename string to open any +# @files and produce final expression strings. + +pointer procedure imx_preproc_list (template) + +char template[ARB] #i template string + +pointer tp, ip, op, itp, listp, elem +int i, lp, in, len, tend, tlen, plen, llen +int nchars, atat, nelem, in_filter +char ch, file[SZ_LINE], expr[SZ_LINE], fname[SZ_PATHNAME] +char ikparams[SZ_LINE], sec[SZ_LINE], dirname[SZ_PATHNAME] + +define output {Memc[op]=$1;op=op+1} + +int fntopnb(), fntgfnb(), fntlenb(), strlen(), stridxs(), strsearch() +int access(), imx_get_element(), imx_breakout(), isdirectory() + +begin + # Allocate an intial string buffer. + tlen = strlen (template) + plen = max(strlen(template)*2, SZ_FNT) + call calloc (tp, plen, TY_CHAR) + call calloc (itp, tlen + 1, TY_CHAR) + call calloc (elem, SZ_FNT, TY_CHAR) + + in = 1 + op = tp + nelem = 0 + while (imx_get_element (template, in, Memc[elem], SZ_FNT) != EOS) { + + # Break out the filename and expression. + nchars = imx_breakout (Memc[elem], NO, file, expr, + sec, ikparams, SZ_LINE) + + nelem = nelem + 1 + outcomma (nelem > 1) + + atat = NO + call aclrc (Memc[itp], tlen+1) + + if (stridxs("[]", Memc[elem]) > 0 && expr[1] != EOS) { + if (Memc[elem] == '@' || strsearch (Memc[elem], "//") > 0) + call sprintf (Memc[itp], tlen+1, "%s") + else + call sprintf (Memc[itp], tlen+1, "@%s") + call pargstr (Memc[elem]) + + } else if (strsearch (Memc[elem], "][") > 0) { + call sprintf (Memc[itp], tlen+1, "@%s") + call pargstr (Memc[elem]) + + } else { + # Simple filename or @file, just copy it out if it exists. + if (Memc[elem] == '@') { + if (Memc[elem+1] != '@' && access (Memc[elem+1],0,0) == NO) + if (strsearch (Memc[elem], "//") == 0) + next + if (Memc[elem+1] == '@') { + lp = 1 + atat = YES + call sprintf (Memc[itp], tlen+1, "%s") + call pargstr (Memc[elem]) + } else { + lp = 0 + for (; Memc[elem+lp] != EOS; lp=lp+1) + output (Memc[elem+lp]) + next + } + } else { + lp = 0 + for (; Memc[elem+lp] != EOS; lp=lp+1) + output (Memc[elem+lp]) + } + } + + ip = itp + tend = itp + strlen (Memc[itp]) - 1 + ch = Memc[ip] + + if (ch == '@') { # @file + + if (Memc[ip+1] == '@') { # @@file + atat = YES + ip = ip + 1 + } + + if (atat == NO) { + # No metachars, copy item entirely to output string. + in_filter = NO + while (Memc[ip] != EOS && ip <= tend) { + if (Memc[ip] == '[') in_filter = YES + if (Memc[ip] == ']') in_filter = NO + if (Memc[ip] == ',' && in_filter == NO) { + output (Memc[ip]) + ip = ip + 1 + break + } + output (Memc[ip]) + ip = ip + 1 + } + next + } + + if (atat == YES) { + if (isdirectory (file[3], dirname, SZ_PATHNAME) > 0) { + len = strlen (file) + if (file[len] != '$') + call strcat ("/", file, SZ_FNAME) + call strcat ("*.fits", file, SZ_FNAME) + listp = fntopnb (file[3], YES) + } else + listp = fntopnb (file[2], YES) + } else + listp = fntopnb (file, YES) + + llen = fntlenb (listp) + for (i=0; i < llen; i=i+1) { + call aclrc (fname, SZ_PATHNAME) + if (fntgfnb (listp, fname, SZ_PATHNAME) == EOF) + break + + if (atat == YES) + output ('@') + for (lp=1; fname[lp] != EOS; lp=lp+1) + output (fname[lp]) + if (expr[1] != EOS) { # append extension info + output ('[') + for (lp=1; expr[lp] != EOS; lp=lp+1) + output (expr[lp]) + if (ikparams[1] != EOS) { + output (',') + for (lp=1; ikparams[lp] != EOS; lp=lp+1) + output (ikparams[lp]) + } + output (']') + } + if (sec[1] != EOS) { # append any section notation + output ('[') + for (lp=1; sec[lp] != EOS; lp=lp+1) + output (sec[lp]) + output (']') + } + + outcomma (i < (llen-1)) + } + call fntclsb (listp) + ip = ip + nchars + 1 + + if (Memc[ip+1] == ',') + break + } # else + # call strcpy (Memc[elem], Memc[op], SZ_FNT) + } + + call mfree (itp, TY_CHAR) + call mfree (elem, TY_CHAR) + + return (tp) +end + + +# IMX_GET_ELEMENT -- Get the next element of a list template. + +int procedure imx_get_element (template, ip, elem, maxch) + +char template[ARB] #i input template string +int ip #u template index +char elem[ARB] #o output string buffer +int maxch #i max size of output element + +int op, level, done +char ch + +begin + op = 1 + done = 0 + level = 0 + + if (template[ip] == EOS) + return (EOS) + if (template[ip] == ',') + ip = ip + 1 + + call aclrc (elem, maxch) + while (template[ip] != EOS) { + ch = template[ip] + + if (ch == EOS || (ch == ',' && level == 0)) { + done = 1 + } else if (ch == '[') + level = level + 1 + else if (ch == ']') + level = level - 1 + + if (done == 1) { + return (ip + 1) + } else + elem[op] = ch + + ip = ip + 1 + op = op + 1 + } + + return (ip) +end + + +# IMX_SPLIT -- Split a list element into the coarse filename and modifiers + +int procedure imx_split (in, fname, mods, maxch) + +char in[ARB] #i input template string +char fname[ARB] #o filename +char mods[ARB] #o modifier strings +int maxch #i max size of output string + +int i, j, nmods + +begin + # Allocate an intial string buffer. + nmods = 0 + call aclrc (mods, maxch) + call aclrc (fname, maxch) + + + # Gather any prefix '@' symbols. + for (i=1; in[i] != '[' && in[i] != EOS && i < maxch; i=i+1) + fname[i] = in[i] + + # Get the filename component up to the EOS or the modifiers. + if (in[i] == '[') { + for (j=1; in[i] != EOS && i < maxch && j < maxch; i=i+1) { + mods[j] = in[i] + j = j + 1 + if (in[i] == '[') + nmods = nmods + 1 + } + } + + return (nmods) +end diff --git a/sys/imio/imt/mkpkg b/sys/imio/imt/mkpkg new file mode 100644 index 00000000..eca1a520 --- /dev/null +++ b/sys/imio/imt/mkpkg @@ -0,0 +1,24 @@ +# Update the IMIO portion of the LIBEX library. + +$checkout libex.a ../ +$update libex.a +$checkin libex.a ../ +$exit + +libex.a: + imt.x + imx.x imx.h <error.h> + imxbreakout.x + imxparse.x imx.h <ctype.h> + imxescape.x imx.h + imxexpand.x imx.h <ctype.h> <error.h> <imhdr.h> <imset.h> <mach.h> + imxexpr.x imx.h <ctype.h> <error.h> <evexpr.h> <lexnum.h> + imxftype.x imx.h <error.h> + imxpreproc.x imx.h + ; + +test: + $call libpkg.a + $omake zzdebug.x + $link zzdebug.o libpkg.a + ; diff --git a/sys/imio/imt/t_urlget.x b/sys/imio/imt/t_urlget.x new file mode 100644 index 00000000..e0e7bf26 --- /dev/null +++ b/sys/imio/imt/t_urlget.x @@ -0,0 +1,94 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <syserr.h> +include <imhdr.h> +include <imset.h> +include <mach.h> + +task urlget = t_urlget + + + +# URLGET -- Do an HTTP GET of a URL to the named file. + +procedure t_urlget () + +pointer reply +char url[SZ_PATHNAME], fname[SZ_PATHNAME], extn[SZ_PATHNAME] +char cache[SZ_PATHNAME], lfname[SZ_PATHNAME] +int nread +bool use_cache, verbose + +int url_get() +bool fcaccess() + +begin + # Get the parameters + call clgstr ("url", url, SZ_PATHNAME) + + call url_to_name (url, fname, SZ_PATHNAME) + call strcpy ("", extn, SZ_PATHNAME) + call strcpy ("/tmp/cache/", cache, SZ_PATHNAME) + verbose = true + use_cache = false + + + # Tell them what we're doing. + if (verbose) { + call printf ("%s -> %s\n") + call pargstr (url) + call pargstr (fname) + call flush (STDOUT) + } + + # Retrieve the URL. + if (use_cache) { + call aclrc (lfname, SZ_FNAME); + + if (fcaccess (cache, url, "fits")) { + call fcname (cache, url, "f", lfname, SZ_PATHNAME) + if (extn[1] != EOS) { + # Add an extension to the cached file. + call strcat (".", lfname, SZ_PATHNAME) + call strcat (extn, lfname, SZ_PATHNAME) + } + } else { + # Add it to the cache, also handles the download. + call fcadd (cache, url, extn, lfname, SZ_PATHNAME) + } + call fcopy (lfname, fname) + + } else { + # Not in cache, or not using the cache, so force the download. + call calloc (reply, SZ_LINE, TY_CHAR) + nread = url_get (url, fname, reply) + call mfree (reply, TY_CHAR) + } +end + + +# URL_TO_NAME -- Generate a filename from a URL. + +procedure url_to_name (url, name, maxch) + +char url[ARB] #i URL being accessed +char name[ARB] #o output name +int maxch #i max size of output name + +int ip, strlen() +char ch + +begin + ip = strlen (url) + while (ip > 1) { + ch = url[ip] + if (ch == '/' || ch == '?' || ch == '&' || ch == ';' || ch == '=') { + call strcpy (url[ip+1], name, maxch) + return + } + ip = ip - 1 + } + + call strcpy (url[ip], name, maxch) +end diff --git a/sys/imio/imt/zzdebug.x b/sys/imio/imt/zzdebug.x new file mode 100644 index 00000000..746fc6f1 --- /dev/null +++ b/sys/imio/imt/zzdebug.x @@ -0,0 +1,227 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <syserr.h> +include <imhdr.h> +include <imset.h> +include <mach.h> +include "imx.h" + + +task imt = t_imt, + parse = t_parse, + fnexpand = t_fnexpand, + prelist = t_prelist, + preproc = t_preproc, + breakout = t_breakout, + imexpand = t_imexpand, + fexpand = t_fexpand + + + +# IMT -- Test the image template package. + +procedure t_imt () + +char template[SZ_LINE] +char image[SZ_FNAME] + +pointer imt, im, imtopen(), immap() +int i, imtgetim() +bool num, clgetb() + +begin + call clgstr ("in", template, SZ_LINE) + num = clgetb ("number") + + imt = imtopen (template) + + for (i=0; imtgetim (imt, image, SZ_FNAME) != EOF; i=i+1) { + + if (num) { + im = immap (image, READ_ONLY, 0) + call printf ("%3d %s %d x %d\n") + call pargi (i+1) + call pargstr (image) + call pargi (IM_LEN(im,1)) + call pargi (IM_LEN(im,2)) + call imunmap (im) + } else { + if (i > 0) + call printf (",") + call printf ("%s") + call pargstr (image) + } + } + call printf ("\n") + call printf ("Nimages = %d\n") + call pargi (i) + + call imtclose (imt) +end + + +# PARSE -- Test the image template package expression parse. + +procedure t_parse () + +char template[SZ_LINE], name[SZ_LINE], index[SZ_LINE], ikparams[SZ_LINE] +char extname[SZ_LINE], extver[SZ_LINE], expr[SZ_LINE], sec[SZ_LINE] + +int nch, imx_parse() + +begin + call clgstr ("in", template, SZ_LINE) + + nch = imx_parse (template, name, index, extname, extver, + expr, sec, ikparams, SZ_LINE) + + call eprintf ("%s\n") ; call pargstr (template) + call eprintf ("\tname\t= %s\n") ; call pargstr (name) + call eprintf ("\tindex\t= %s\n") ; call pargstr (index) + call eprintf ("\textname\t= %s\n") ; call pargstr (extname) + call eprintf ("\textver\t= %s\n") ; call pargstr (extver) + call eprintf ("\texpr\t= %s\n") ; call pargstr (expr) + call eprintf ("\tikparams\t= %s\n") ; call pargstr (ikparams) + call eprintf ("\tsec\t= %s\n") ; call pargstr (sec) +end + + +# FNEXPAND -- Test the image template package pre-processor. + +procedure t_fnexpand () + +char template[SZ_LINE] + +pointer pp, imx_fnexpand() + +begin + call clgstr ("in", template, SZ_LINE) + + pp = imx_fnexpand (template) + + call eprintf ("%s\n") + call pargstr (Memc[pp]) + call mfree (pp, TY_CHAR) +end + + +# PRELIST -- Test the image template package pre-processor. + +procedure t_prelist () + +char template[SZ_LINE] + +pointer pp, imx_preproc_list() + +begin + call clgstr ("in", template, SZ_LINE) + + pp = imx_preproc_list (template) + + call eprintf ("%s\n") + call pargstr (Memc[pp]) + call mfree (pp, TY_CHAR) +end + + +# PREPROC -- Test the image template package pre-processor. + +procedure t_preproc () + +char template[SZ_LINE] + +pointer pp, imx_preproc() + +begin + call clgstr ("in", template, SZ_LINE) + + pp = imx_preproc (template) + + call eprintf ("%s\n") + call pargstr (Memc[pp]) + call mfree (pp, TY_CHAR) +end + + +# BREAKOUT -- Test the image template package expression breakout code. + +procedure t_breakout () + +char template[SZ_LINE] + +int nchars +char image[SZ_LINE], expr[SZ_LINE], sec[SZ_LINE], ikparams[SZ_LINE] + +int imx_breakout() + +begin + call clgstr ("in", template, SZ_LINE) + + nchars = imx_breakout(template, NO, image, expr, sec, ikparams, SZ_LINE) + + call eprintf ("nchars=%d image='%s' expr='%s' sec='%s' ik='%s'\n") + call pargi (nchars) + call pargstr (image) + call pargstr (expr) + call pargstr (sec) + call pargstr (ikparams) +end + + +# IMEXPAND -- Test the MEF image expansion. + +procedure t_imexpand () + +char template[SZ_LINE] +int nimages + +pointer imt, imx_imexpand() + +begin + call clgstr ("in", template, SZ_LINE) + + imt = imx_imexpand (template, + "", # expr + "", # index + "", # extname + "", # extver + "", # ikparams + "", # sections + nimages) + + call printf ("nimages = %d\n%s\n"); + call pargi (nimages) + call pargstr (Memc[imt]) + + call mfree (imt, TY_CHAR) +end + + +# FEXPAND -- Test the filename expansion. + +procedure t_fexpand () + +char template[SZ_LINE] +int nimages + +pointer imt, imx_fexpand() + +begin + call clgstr ("in", template, SZ_LINE) + + imt = imx_fexpand (template, + "", # expr + "", # index + "", # extname + "", # extver + "", # ikparams + "", # sections + nimages) + + call printf ("nimages = %d\n%s\n"); + call pargi (nimages) + call pargstr (Memc[imt]) + + call mfree (imt, TY_CHAR) +end |