/* File gethead.c * January 20, 2015 * By Jessica Mink Harvard-Smithsonian Center for Astrophysics) * Send bug reports to jmink@cfa.harvard.edu Copyright (C) 1996-2015 Smithsonian Astrophysical Observatory, Cambridge, MA USA This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include #include "libwcs/wcs.h" #include "libwcs/fitsfile.h" #include "libwcs/wcscat.h" #define MAXKWD 100 #define MAXFILES 2000 static int maxnkwd = MAXKWD; static int maxncond = MAXKWD; static int maxnfile = MAXFILES; #define FILE_FITS 1 #define FILE_IRAF 2 #define FILE_ASCII 3 static void usage(); extern char *GetFITShead(); static char nextnsp(); static int PrintValues(); static char *RevMsg = "GETHEAD WCSTools 3.9.4, 2 August 2016, Jessica Mink (jmink@cfa.harvard.edu)"; static int verbose = 0; /* verbose/debugging flag */ static int nfile = 0; static int ndec = -9; static int maxlfn = 0; static int listall = 0; static int listpath = 0; static int j2000 = 0; /* If 1, convert ra, dec keywords to J2000 */ static int tabout = 0; static int tabpad = 0; static int tabchar = 0; /* If 1, separate values by 1st keyward char */ static int logfile = 0; static int printhead = 0; static int fillblank=0; /* If 1, replace blanks in strings with _ */ static int forceascii = 0; static int version = 0; /* If 1, print only program name and version */ static int printfill=0; /* If 1, print ___ for unfound keyword values */ static int printfile=1; /* If 1, print filename first if >1 files */ static int keyeqval=0; /* If 1, print keyword=value */ static int keyeqvaln=0; /* If 1, print keyword=value */ static char *rootdir=NULL; /* Root directory for input files */ static int ncond=0; /* Number of keyword conditions to check */ static int condand=1; /* If 1, AND comparisons, else OR */ static int toeol = 0; /* If 1, return values from ASCII file to EOL */ static int maxml = 20000; /* Maximum length of IRAF multi-line keyword */ static char **cond, **newcond; /* Conditions to check */ static char **ccond, **newccond; /* Condition characters */ static int nproc = 0; static char *extensions; /* Extension number(s) or name to read */ static char *extension; /* Extension number or name to read */ static int filekey = 0; /* If 1, FILENAME keyword has been requested */ static char *mstring; /* IRAF keyword multi-line value */ int main (ac, av) int ac; char **av; { char *str; char **kwd; /* Keywords to read */ char **kwdnew; /* Keywords to read */ int nkwd = 0; int nkwd1 = 0; char **fn, **newfn; /* File name arrays */ char wcond, **newccond; int *ft, *newft; /* File type vectors to match fn[] */ int ifile; int lfn; char filename[256]; char *name; FILE *flist = NULL; FILE *fdk; char *listfile; char *ilistfile; char *klistfile; int ikwd, lkwd, i, j; char *kw, *kwe; char string[80]; char *fext, *fcomma; char *namext; char *extroot = NULL; char *extroot0; char *lastroot = NULL; int nch; int nbytes; int filetype; int icond; int nfext = 0; int nrmax=10; struct Range *erange = NULL; mstring = (char *) calloc (maxml, 1); ilistfile = NULL; klistfile = NULL; extension = NULL; extensions = NULL; namext = NULL; ncond = 0; nfile = 0; fn = (char **)calloc (maxnfile, sizeof(char *)); ft = (int *)calloc (maxnfile, sizeof(int)); kwd = (char **)calloc (maxnkwd, sizeof(char *)); cond = (char **)calloc (maxncond, sizeof(char *)); ccond = (char **)calloc (maxncond, sizeof(char *)); /* Check for help or version command first */ str = *(av+1); if (!str || !strcmp (str, "help") || !strcmp (str, "-help")) usage(); if (!strcmp (str, "version") || !strcmp (str, "-version")) { version = 1; usage(); } /* crack arguments */ for (av++; --ac > 0; av++) { if (*(str = *av)=='-') { char c; while ((c = *++str)) switch (c) { case 'a': /* list file even if the keywords are not found */ listall++; break; case 'b': /* Replace blanks with underscores */ fillblank = 1; break; case 'c': /* Force reading as an ASCII file */ forceascii++; break; case 'd': /* Root directory for input */ if (ac < 2) usage(); rootdir = *++av; ac--; break; case 'e': /* list keyword=value for input to sethead */ keyeqval++; break; case 'f': /* Do not print file names */ printfile = 0; break; case 'g': /* list keyword=value */ keyeqvaln++; break; case 'h': /* Output column headings */ printhead++; break; case 'i': /* Log files changed */ logfile++; break; case 'j': /* Convert output RA, Dec to J2000 */ j2000++; break; case 'l': /* Return values to end of line */ toeol++; break; case 'm': /* Maximum length of IRAF multi-line keyword */ if (ac < 2) usage(); maxml = (int) (atof (*++av)); free (mstring); mstring = (char *) calloc (maxml, 1); ac--; break; case 'n': /* Number of decimal places in output */ if (ac < 2) usage(); ndec = (int) (atof (*++av)); ac--; break; case 'o': /* OR conditions insted of ANDing them */ condand = 0; break; case 'p': /* List file pathnames, not just file names */ listall++; listpath++; break; case 'r': /* Separate output values by single character */ tabchar = 1; break; case 's': /* Do not pad output tab table */ tabpad = 0; break; case 't': /* Output tab table */ tabout++; break; case 'u': /* Always print ___ if keyword not found */ printfill++; break; case 'v': /* More verbosity */ verbose++; break; case 'x': /* FITS extension to read */ if (ac < 2) usage(); if (isnum (*(av+1)) || isrange (*(av+1))) { extroot = NULL; extensions = *++av; ac--; } else { extroot = *++av; lastroot = extroot + strlen (extroot); extensions = extroot; while (extensions < lastroot) { if (isrange (extensions)) break; else extensions++; } if (extensions == lastroot) { extensions = calloc (16, 1); if (strlen (extroot) > 0) strcpy (extensions, "1-1000"); else strcpy (extensions, "0-1000"); } else { extroot0 = extroot; extroot = calloc (16, 1); strncpy (extroot, extroot0, extensions-extroot0); } ac--; } if (isrange (extensions)) { listall++; erange = RangeInit (extensions, nrmax); nfext = rgetn (erange); if (verbose) fprintf (stderr, "Searching extensions %s\n", extensions); } else { extension = extensions; if (extension) nfext = 1; else nfext = 0; if (verbose) fprintf (stderr, "Searching extension %s\n", extension); } break; default: usage(); break; } } /* File containing a list of keywords or files */ else if (*av[0] == '@') { listfile = *av + 1; if (isimlistd (listfile, rootdir)) { ilistfile = listfile; nfile = getfilelines (ilistfile); } else if (isfilelist (listfile, rootdir)) { ilistfile = listfile; nfile = getfilelines (ilistfile); } else { klistfile = listfile; nkwd1 = getfilelines (klistfile); if (nkwd1 > 0) { if (nkwd+nkwd1 > maxnkwd) { maxnkwd = nkwd + nkwd1 + 32; kwdnew = (char **) calloc (maxnkwd, sizeof (char **)); for (ikwd = 0; ikwd < nkwd; ikwd++) kwdnew[ikwd] = kwd[ikwd]; free (kwd); kwd = kwdnew; } if ((fdk = fopen (klistfile, "r")) == NULL) { fprintf (stderr,"GETHEAD: File %s cannot be read\n", klistfile); nkwd = 0; } else { for (ikwd = 0; ikwd < nkwd1; ikwd++) { kwd[nkwd] = (char *) calloc (32, 1); first_token (fdk, 31, kwd[nkwd++]); if (!strcasecmp (kwd[nkwd-1], "filename")) filekey++; } fclose (fdk); } } } } /* Image file */ else if (isfits (*av) || isiraf (*av)) { if (nfile >= maxnfile) { maxnfile = maxnfile * 2; nbytes = maxnfile * sizeof (char *); newfn = (char **) calloc (maxnfile, sizeof (char *)); for (i = 0; i < nfile; i++) { newfn[i] = fn[i]; } free (fn); fn = newfn; newft = (int *) calloc (maxnfile*2, sizeof (int)); for (i = 0; i < nfile; i++) { newft[i] = ft[i]; } free (ft); ft = newft; } fn[nfile] = *av; if (forceascii) { ft[nfile] = FILE_ASCII; } else if (isfits (*av)) { ft[nfile] = FILE_FITS; } else { ft[nfile] = FILE_IRAF; } if (listpath || (name = strrchr (fn[nfile],'/')) == NULL) { name = fn[nfile]; } else { name = name + 1; } lfn = strlen (name); if (lfn > maxlfn) { maxlfn = lfn; } nfile++; } /* Text file */ else if (isfile (*av)) { if (nfile >= maxnfile) { maxnfile = maxnfile * 2; newfn = (char **) calloc (maxnfile, sizeof (char *)); for (i = 0; i < nfile; i++) newfn[i] = fn[i]; free (fn); fn = newfn; nbytes = maxnfile * sizeof (int); newft = (int *) calloc (maxnfile, sizeof (int)); for (i = 0; i < nfile; i++) newft[i] = ft[i]; free (ft); ft = newft; } fn[nfile] = *av; ft[nfile] = FILE_ASCII; if (listpath || (name = strrchr (fn[nfile],'/')) == NULL) { name = fn[nfile]; } else { name = name + 1; } lfn = strlen (name); if (lfn > maxlfn) { maxlfn = lfn; } nfile++; } /* Condition */ else if (strchr (*av, '=') != NULL || strchr (*av, '#') != NULL || strchr (*av, '>') != NULL || strchr (*av, '<') != NULL ) { if (ncond >= maxncond) { maxncond = maxncond * 2; newcond = (char **) calloc(maxncond, sizeof(void *)); for (i = 0; i < ncond; i++) newcond[i] = cond[i]; free (cond); cond = newcond; newccond = (char **) calloc(maxncond, sizeof(void *)); for (i = 0; i < ncond; i++) newccond[i] = ccond[i]; free (ccond); ccond = newccond; } cond[ncond] = *av; ccond[ncond] = strchr (*av, '='); if (ccond[ncond] == NULL) { ccond[ncond] = strchr (*av, '#'); } if (ccond[ncond] == NULL) { ccond[ncond] = strchr (*av, '>'); } if (ccond[ncond] == NULL) { ccond[ncond] = strchr (*av, '<'); } kwe = ccond[ncond]; if (kwe != NULL) { for (kw = cond[ncond]; kw < kwe; kw++) { if (*kw > 96 && *kw < 123) { *kw = *kw - 32; } } } ncond++; } /* Keyword */ else { if (nkwd >= maxnkwd) { maxnkwd = maxnkwd * 2; kwdnew = (char **) calloc (sizeof(char *), maxnkwd); for (ikwd = 0; ikwd < nkwd; ikwd++) { kwdnew[ikwd] = kwd[ikwd]; } free (kwd); kwd = kwdnew; } lkwd = strlen (*av); kwd[nkwd] = calloc (sizeof(char), lkwd+1); for (i = 0; i < lkwd; i++) kwd[nkwd][i] = (*av)[i]; if (!strcasecmp (kwd[nkwd], "filename")) filekey++; nkwd++; } } if (nkwd <= 0 && nfile <= 0 ) usage (); else if (nkwd <= 0) { fprintf (stderr, "GETHEAD: no keywords specified\n"); exit (1); } else if (nfile <= 0 ) { fprintf (stderr, "GETHEAD: no files specified\n"); exit (1); } if (nkwd > 1 && tabpad) printfill = 1; if (nfile < 2 && !listall) printfile = 0; /* Print column headings if tab table or headings requested */ if (printhead) { /* Print conditions in header */ for (icond = 0; icond < ncond; icond++) { if (verbose) { if (condand || icond == 0) { printf ("%s\n",cond[icond]); } else { printf (" or %s\n",cond[icond]); } } else if (tabout) { if (condand || icond == 0) { printf ("condition %s\n", cond[icond]); } else { printf ("condition or %s\n", cond[icond]); } } } if (printfile) { if (filekey) printf ("FILE_NAME"); else printf ("FILENAME"); if (maxlfn > 8) { for (i = 8; i < maxlfn; i++) { printf (" "); } } if (tabout) { printf (" "); } else { printf (" "); } } /* Make keyword names upper case and print keyword names in header */ for (ikwd = 0; ikwd < nkwd; ikwd++) { lkwd = strlen (kwd[ikwd]); kwe = kwd[ikwd] + lkwd; if (ft[0] != FILE_ASCII) { for (kw = kwd[ikwd]; kw < kwe; kw++) { if (*kw > 96 && *kw < 123) { *kw = *kw - 32; } } } printf ("%s",kwd[ikwd]); if (verbose || ikwd == nkwd - 1) { printf ("\n"); } else if (tabout) { printf (" "); } else { printf (" "); } } /* Print field-defining hyphens if tab table output requested */ if (printhead && tabout) { if (printfile) { strcpy (string, "-----------------------------------"); if (maxlfn > 8) { string[maxlfn] = (char) 0; } else { string[8] = (char) 0; } printf ("%s",string); if (verbose || ikwd == nkwd - 1) { printf ("\n"); } else { printf (" "); } } for (ikwd = 0; ikwd < nkwd; ikwd++) { strcpy (string, "--------------"); lkwd = strlen (kwd[ikwd]); string[lkwd] = (char) 0; printf ("%s",string); if (verbose || ikwd == nkwd - 1) { printf ("\n"); } else { printf (" "); } string[lkwd] = '-'; } } } /* Open file containing a list of images, if there is one */ if (ilistfile != NULL) { if ((flist = fopen (ilistfile, "r")) == NULL) { fprintf (stderr,"GETHEAD: Image list file %s cannot be read\n", ilistfile); usage (); } } /* Read through headers of images */ for (ifile = 0; ifile < nfile; ifile++) { if (ilistfile != NULL) { first_token (flist, 254, filename); if (forceascii) filetype = FILE_ASCII; else if (isiraf (filename)) filetype = FILE_IRAF; else if (isfits (filename)) { filetype = FILE_FITS; if ((fcomma = strchr (filename, ','))) { fext = fcomma + 1; if (isrange (fext)) { erange = RangeInit (fext, nrmax); nfext = rgetn (erange); extension = calloc (1, 8); *fcomma = (char) 0; } else if (!strcmp (fext, "all")) { erange = RangeInit ("1-500", nrmax); nfext = rgetn (erange); extension = calloc (1, 8); *fcomma = (char) 0; } else nfext = 1; } } else filetype = FILE_ASCII; if (nfext > 1) { rstart (erange); extension = calloc (1, 8); for (i = 0; i < nfext; i++) { j = rgeti4 (erange); sprintf (extension, "%d", j); nch = strlen (filename) + 2 + strlen (extension); if (extroot) nch = nch + strlen (extroot); namext = (char *) calloc (1, nch); strcpy (namext, filename); strcat (namext, ","); if (extroot) strcat (namext,extroot); strcat (namext, extension); if (PrintValues (namext, filetype, nkwd, kwd)) { if (namext != NULL) { free (namext); namext = NULL; } break; } if (namext != NULL) { free (namext); namext = NULL; } } if (extension != NULL) { free (extension); extension = NULL; } /* if (erange != NULL) free (erange); */ } else PrintValues (filename, filetype, nkwd, kwd); } else { if ((fcomma = strchr (fn[ifile], ','))) { fext = fcomma + 1; if (isrange (fext)) { erange = RangeInit (fext, nrmax); nfext = rgetn (erange); extension = calloc (1, 8); *fcomma = (char) 0; } else if (!strcmp (fext, "all")) { erange = RangeInit ("1-500", nrmax); nfext = rgetn (erange); extension = calloc (1, 8); *fcomma = (char) 0; } else nfext = 1; } /* If there is a range of extensions, use them */ if (nfext > 1) { rstart (erange); extension = calloc (1, 8); for (i = 0; i < nfext; i++) { j = rgeti4 (erange); sprintf (extension, "%d", j); nch = strlen (fn[ifile]) + 2 + strlen (extension); if (extroot) nch = nch + strlen (extroot); namext = (char *) calloc (1, nch); strcpy (namext, fn[ifile]); strcat (namext, ","); if (extroot) strcat (namext,extroot); strcat (namext, extension); sprintf (extension, "%d", j); if (PrintValues (namext, ft[ifile], nkwd, kwd)) { if (namext != NULL) { free (namext); namext = NULL; } break; } if (namext != NULL) { free (namext); namext = NULL; } } if (extension != NULL) { free (extension); extension = NULL; } /* if (erange != NULL) free (erange); */ } else (void) PrintValues (fn[ifile], ft[ifile], nkwd, kwd); } if (verbose) printf ("\n"); /* Log the processing of this file, if requested */ if (logfile) { nproc++; fprintf (stderr, "%d: %s processed.\r", nproc, filename); } } if (ilistfile != NULL) fclose (flist); free (mstring); return (0); } static void usage () { fprintf (stderr,"%s\n",RevMsg); if (version) exit (-1); fprintf (stderr,"Print FITS or IRAF header keyword values\n"); fprintf(stderr,"Usage: gethead [-abhoptv][-d dir][-f num][-m num][-n num] file1.fit ... filen.fits kw1 kw2 ... kwn\n"); fprintf(stderr," or : gethead [-abhoptv][-d dir][-f num][-m num][-n num] @filelist kw1 kw2 ... kwn\n"); fprintf(stderr," or : gethead [-abhoptv][-d dir][-f num][-m num][-n num] file1.fit ... filen.fits @keywordlist\n"); fprintf(stderr," or : gethead [-abhoptv][-d dir][-f num][-m num][-n num] @filelist @keywordlist\n"); fprintf(stderr," -a: List file even if keywords are not found or null\n"); fprintf(stderr," -b: Replace blanks in strings with underscores\n"); fprintf(stderr," -c: Read all files as plain ASCII\n"); fprintf(stderr," -d dir: Root directory for input files (default is cwd)\n"); fprintf(stderr," -e: Output keyword=value's on one line per file\n"); fprintf(stderr," -f: Never print filenames (default is print if >1)\n"); fprintf(stderr," -g: Output keyword=value's on one line per keyword\n"); fprintf(stderr," -h: Print column headings\n"); fprintf(stderr," -j: Print output ra and dec in J2000\n"); fprintf(stderr," -m num: Change maximum length of IRAF multi-line value\n"); fprintf(stderr," -n num: Number of decimal places in numeric output\n"); fprintf(stderr," -o: OR conditions instead of ANDing them\n"); fprintf(stderr," -p: Print full pathnames of files\n"); fprintf(stderr," -s: Do not pad tab-separated table with spaces\n"); fprintf(stderr," -t: Output in tab-separated table format\n"); fprintf(stderr," -u: Always print ___ if keyword not found or null value\n"); fprintf(stderr," -v: Verbose\n"); fprintf(stderr," -x [range]: Read header for these extensions (no arg=all)\n"); exit (1); } static int PrintValues (name, filetype, nkwd, kwd) char *name; /* Name of FITS or IRAF image file */ int filetype; /* Type of file (FILE_FITS, FILE_IRAF, FILE_ASCII) */ int nkwd; /* Number of keywords for which to print values */ char *kwd[]; /* Names of keywords for which to print values */ { char *header; /* FITS image header or contents of ASCII file */ char *cstr, *str; int iraffile; char fnform[8]; char string[256]; char estring[80]; char temp[1028]; char keyword[16]; char *filename; char outline[1000]; char padline[1000]; char ctab = (char) 9; char cspace = (char) 32; char *subkwd; char pchar; char *kw, *kwe, *filepath; char *ext, *namext, cext; int ikwd, nfound, notfound, nch, iepoch; int lkwd = 0; int jval, jcond, icond, i, j, lout, lstr; double dval, dcond, dnum, epoch, ra, dec; char tcond; char cvalue[64], *cval; char numstr[32], numstr1[32]; int pass, iwcs, nwild, sys1, sys2, ncdec; ext = NULL; namext = NULL; filepath = NULL; header = NULL; mstring[0] = (char) 0; ext = strchr (name, ','); if (extension && !ext) { nch = strlen (name) + 2 + strlen (extension); namext = (char *) calloc (1, nch); strcpy (namext, name); strcat (namext, ","); strcat (namext, extension); } else { nch = strlen (name) + 1; namext = (char *) calloc (1, nch); strcpy (namext, name); } ext = strchr (namext, ','); if (rootdir) { nch = strlen (rootdir) + strlen (namext) + 1; filepath = (char *) calloc (1, nch); strcat (filepath, rootdir); strcat (filepath, "/"); strcat (filepath, namext); } else { nch = strlen (namext) + 1; filepath = (char *) calloc (1, nch); strcpy (filepath, namext); } if (verbose) fprintf (stderr, "Reading from file %s\n", filepath); if (!tabout && listall) printfill = 1; /* Read ASCII file into buffer */ if (filetype == FILE_ASCII) { if ((header = getfilebuff (filepath)) == NULL) { if (namext != NULL) free (namext); if (verbose) fprintf (stderr, "GETHEAD: file %s has no content\n", filepath); if (filepath != NULL) free (filepath); ext = NULL; namext = NULL; filepath = NULL; return (-1); } else if (strlen (header) == 0) { if (namext != NULL) free (namext); if (verbose) fprintf (stderr, "GETHEAD: file %s has null at start\n", filepath); if (filepath != NULL) free (filepath); free (header); ext = NULL; namext = NULL; filepath = NULL; header = NULL; return (-1); } } /* Retrieve FITS header from FITS or IRAF .imh file */ else if ((header = GetFITShead (filepath, verbose)) == NULL) { if (namext != NULL) free (namext); if (filepath != NULL) free (filepath); ext = NULL; namext = NULL; filepath = NULL; return (-1); } if (verbose) { fprintf (stderr,"%s\n",RevMsg); fprintf (stderr,"Print Header Parameter Values from "); hgeti4 (header, "IMHVER", &iraffile ); if (filetype == FILE_ASCII) fprintf (stderr,"ASCII file %s\n", namext); else if (filetype == FILE_IRAF) fprintf (stderr,"IRAF image file %s\n", namext); else fprintf (stderr,"FITS image file %s\n", namext); } /* Find file name */ if (listpath || (filename = strrchr (namext,'/')) == NULL) filename = namext; else if (rootdir) filename = namext; else filename = filename + 1; if (printfile) { if (ext) { cext = *ext; *ext = (char) 0; } sprintf (fnform, "%%-%ds", maxlfn); sprintf (outline, fnform, filename); if (ext) { *ext = '['; sprintf (string, "%s]", ext); strcat (outline, string); *ext = cext; } if (tabout) strcat (outline, " "); else strcat (outline, " "); } else outline[0] = (char) 0; /* Check conditions */ pass = 0; if (ncond > 0) { for (icond = 0; icond < ncond; icond++) { if (condand) pass = 0; tcond = *ccond[icond]; /* Extract test value from comparison string */ *ccond[icond] = (char) 0; cstr = ccond[icond]+1; if (strchr (cstr, ':')) { dnum = str2dec (cstr); num2str (numstr, dnum, 0, 7); cstr = numstr; } strfix (cstr, fillblank, 1); /* Read comparison value from header */ if (!hgets (header, cond[icond], 64, cvalue)) continue; cval = cvalue; if (strchr (cval, ':')) { dnum = str2dec (cval); num2str (numstr1, dnum, 0, 7); cval = numstr1; } strfix (cval, fillblank, 1); /* Compare floating point numbers */ if (isnum (cstr) == 2 && isnum (cval)) { *ccond[icond] = tcond; dcond = atof (cstr); dval = atof (cval); if (tcond == '=' && dval == dcond) pass = 1; if (tcond == '#' && dval != dcond) pass = 1; if (tcond == '>' && dval > dcond) pass = 1; if (tcond == '<' && dval < dcond) pass = 1; } /* Compare integers */ else if (isnum (cstr) == 1 && isnum (cval)) { *ccond[icond] = tcond; jcond = atoi (cstr); jval = atoi (cval); if (tcond == '=' && jval == jcond) pass = 1; if (tcond == '#' && jval != jcond) pass = 1; if (tcond == '>' && jval > jcond) pass = 1; if (tcond == '<' && jval < jcond) pass = 1; } /* Compare strings (only equal or not equal */ else { *ccond[icond] = tcond; if (tcond == '=' && !strcmp (cstr, cval)) pass = 1; if (tcond == '#' && strcmp (cstr, cval)) pass = 1; } if (condand && !pass) { if (namext != NULL) free (namext); if (filepath != NULL) free (filepath); if (header != NULL) free (header); ext = NULL; namext = NULL; filepath = NULL; header = NULL; return (0); } } if (!pass) { if (namext != NULL) free (namext); if (filepath != NULL) free (filepath); if (header != NULL) free (header); ext = NULL; namext = NULL; filepath = NULL; header = NULL; return (0); } } /* Read keywords from header */ nfound = 0; notfound = 0; for (ikwd = 0; ikwd < nkwd; ikwd++) { /* Allow for sub-keyword in IRAF multi-line keywords */ if ((subkwd = strchr (kwd[ikwd], ':')) != NULL) { *subkwd = (char) 0; subkwd++; } /* IF FITS header, look for upper case keywords only */ if (filetype != FILE_ASCII) { lkwd = strlen (kwd[ikwd]); kwe = kwd[ikwd] + lkwd; for (kw = kwd[ikwd]; kw < kwe; kw++) { if (*kw > 96 && *kw < 123) *kw = *kw - 32; } } for (i = 0; i < 16; i++) keyword[i] = (char) 0; strcpy (keyword, kwd[ikwd]); /* Read keyword value from ASCII file */ if (toeol) lstr = -256; else lstr = 256; for (i = 0; i < 256; i++) string[i] = (char) 0; if (filetype == FILE_ASCII && agets (header, keyword, lstr, fillblank, string)) { str = string; if (ndec > -9 && isnum (str) && strchr (str, '.')) num2str (str, atof(str), 0, ndec); if (keyeqvaln) printf ("%s = %s\n", keyword, str); else if (keyeqval) { if (strchr (str,' ')) sprintf (temp, "%s=\'%s\'", keyword, str); else sprintf (temp, "%s=%s", keyword, str); strcat (outline, temp); } else if (verbose) { sprintf (temp, " %s = %s", keyword, str); strcat (outline, temp); } else if (tabchar) { sprintf (temp, "%c%s", keyword[0], str); strcat (outline, temp); } else strcat (outline, str); nfound++; } /* Read all keywords from multiple WCS's if wildcarded with @ */ else if (keyword[lkwd-1] == '@') { keyword[lkwd-1] = (char) 0; nwild = 0; for (iwcs = -1; iwcs < 26; iwcs++) { if (iwcs < 0) keyword[lkwd-1] = (char)0; else keyword[lkwd-1] = (char)(iwcs+65); if (hgets (header, keyword, 80, string)) { if (string[0] == '#' && isnum (string+1)) { lstr = strlen (string); for (i = 0; i < lstr; i++) string[i] = string[i+1]; } str = string; strfix (str, fillblank, 0); if (ndec > -9 && isnum (str) && strchr (str, '.')) num2str (string, atof(str), 0, ndec); if (verbose) { if (strchr (str,' ')) printf ("%s = \"%s\"\n", keyword, str); else printf ("%s = %s\n", keyword, str); } else if (keyeqvaln) { if (strchr (str,' ')) printf ("%s=\"%s\"\n", keyword, str); else printf ("%s=%s\n", keyword, str); } else if (keyeqval) { if (strchr (str,' ')) sprintf (temp, "%s=\'%s\'", keyword, str); else sprintf (temp, "%s=%s", keyword, str); strcat (outline, temp); } else if (tabchar) { sprintf (temp, "%c%s", keyword[0], str); strcat (outline, temp); } else { if (nwild) { if (tabout) strcat (outline, " "); else strcat (outline, " "); } strcat (outline, str); nwild++; } nfound++; } } } /* Read one FITS keyword value */ else if (hgets (header, keyword, 80, string)) { if (string[0] == '#' && isnum (string+1)) { lstr = strlen (string); for (i = 0; i < lstr; i++) string[i] = string[i+1]; } /* Convert coordinates to J2000 from B1950 */ if (!strcmp (keyword,"RA")) { if (!isnum (string)) hgets (header, "RRA", 80, string); ncdec = StrNdec (string); if (ncdec < 3) ncdec = 3; if (j2000) { if (!hgets (header, "EPOCH", 80, estring) || !isnum (estring)) { if (!hgets (header, "REPOCH", 80, estring)) strcat (estring, "2000"); } epoch = atof (estring); iepoch = (int) (epoch + 0.5); if (iepoch == 1950) { ra = str2ra (string); hgets (header, "DEC", 80, string); if (!isnum (string)) hgets (header, "RDEC", 80, string); dec = str2dec (string); fk425e (&ra, &dec, epoch); ra2str (string, 80, ra, ncdec); } else if (iepoch != 2000) { if (iepoch < 2000) sys1 = WCS_B1950; else sys1 = WCS_J2000; sys2 = WCS_J2000; ra = str2ra (string); hgets (header, "DEC", 80, string); if (!isnum (string)) hgets (header, "RDEC", 80, string); dec = str2dec (string); wcscon (sys1, sys2,epoch,2000.0,&ra,&dec,epoch); ra2str (string, 80, ra, ncdec); } else { ra = str2ra (string); ra2str (string, 80, ra, ncdec); } } else { ra = str2ra (string); ra2str (string, 80, ra, ncdec); } } if (!strcmp (keyword,"DEC")) { if (!isnum (string)) hgets (header, "RDEC", 80, string); ncdec = StrNdec (string); if (ncdec < 2) ncdec = 2; if (j2000) { if (!hgets (header, "EPOCH", 80, estring) || !isnum (estring)) { if (!hgets (header, "REPOCH", 80, estring)) strcat (estring, "2000"); } epoch = atof (estring); iepoch = (int) (epoch + 0.5); if (iepoch == 1950) { dec = str2dec (string); hgets (header, "RA", 80, string); if (!isnum (string)) hgets (header, "RRA", 80, string); ra = str2ra (string); fk425e (&ra, &dec, epoch); dec2str (string, 80, dec, ncdec); } else if (iepoch != 2000) { if (iepoch < 2000) sys1 = WCS_B1950; else sys1 = WCS_J2000; sys2 = WCS_J2000; dec = str2dec (string); hgets (header, "ra", 80, string); if (!isnum (string)) hgets (header, "RRA", 80, string); ra = str2ra (string); wcscon (sys1, sys2,epoch,2000.0,&ra,&dec,epoch); dec2str (string, 80, dec, ncdec); } else { dec = str2dec (string); dec2str (string, 80, dec, ncdec); } } else { dec = str2dec (string); dec2str (string, 80, dec, ncdec); } } if (!strcmp (keyword,"EPOCH")) { if (j2000) strcpy (string,"2000"); if (!isnum (string)) hgets (header,"REPOCH",80,string); } if (j2000 && !strcmp (keyword,"EQUINOX")) strcpy (string,"2000"); str = string; strfix (str, fillblank, 0); if (ndec > -9 && isnum (str) && strchr (str, '.')) { if (isnum (str) < 3) num2str (string, atof(str), 0, ndec); } if (verbose) { if (strchr (str,' ')) printf ("%s = \"%s\"\n", keyword, str); else printf ("%s = %s\n", keyword, str); } else if (keyeqvaln) { if (strchr (str,' ')) printf ("%s=\"%s\"\n", keyword, str); else printf ("%s=%s\n", keyword, str); } else if (keyeqval) { if (strchr (str,' ')) sprintf (temp, "%s=\'%s\'", keyword, str); else sprintf (temp, "%s=%s", keyword, str); strcat (outline, temp); } else if (tabchar) { sprintf (temp, "%c%s", keyword[0], str); strcat (outline, temp); } else if (strlen (str) < 1) strcat (outline, "___"); else strcat (outline, str); nfound++; } /* Read IRAF-style multiple-line keyword value */ else if (hgetm (header, keyword, maxml, mstring)) { if (subkwd != NULL) { if (agets (mstring, subkwd, lstr, fillblank, string)) { if (verbose) { if (strchr (string,' ')) printf ("%s.%s = \"%s\"\n", keyword, subkwd, string); else printf ("%s.%s = %s\n", keyword, subkwd, string); } else if (keyeqvaln) { if (strchr (mstring,' ')) printf ("%s.%s=\"%s\"\n", keyword, subkwd, string); else printf ("%s.%s=%s\n", keyword, subkwd, string); } else if (keyeqval) { if (strchr (str,' ')) sprintf (temp, "%s=\'%s\'", keyword, str); else sprintf (temp, "%s=%s", keyword, str); strcat (outline, temp); } else strcat (outline, string); } else if (keyeqvaln) printf ("%s not found\n", keyword); else if (printfill) strcat (outline, "___"); else notfound = 1; } else if (verbose) { if (strchr (mstring,' ')) printf ("%s = \"%s\"\n", keyword, mstring); else printf ("%s = %s\n", keyword, mstring); } else if (keyeqvaln) { if (strchr (mstring,' ')) printf ("%s=\"%s\"\n", keyword, mstring); else printf ("%s=%s\n", keyword, mstring); } else if (keyeqval) { if (strchr (mstring, ' ')) sprintf (temp, " %s=\'%s\'", keyword, mstring); else sprintf (temp, " %s=%s", keyword, mstring); strcat (outline, temp); } else { if (strlen (mstring) < 1000) strcat (outline, mstring); else strncat (outline, mstring, 999); } nfound++; } else if (keyeqvaln) printf ("%s not found\n", keyword); else if (printfill) strcat (outline, "___"); else notfound = 1; if (!keyeqvaln && !tabchar && ikwd < nkwd-1) { if (tabout) strcat (outline, " "); else strcat (outline, " "); } } /* Print line of keywords */ if (!verbose && !keyeqvaln && (nfound > 0 || printfill || listall) && (nfile < 2 || nfound > 0 || listall)) { /* Remove spaces used to pad tab-separated tables for readability */ if (tabout && !tabpad) { lout = strlen (outline); strcpy (padline, outline); for (i = 0; i < 1000; i++) outline[i] = (char) 0; j = 0; pchar = ctab; for (i = 0; i < lout; i++) { if (padline[i] == cspace && pchar == ctab) continue; if (padline[i] == cspace && nextnsp (padline+i) == ctab) continue; if (padline[i] == cspace && nextnsp (padline+i) == (char) 0) continue; outline[j++] = padline[i]; pchar = padline[i]; } } printf ("%s\n", outline); } if (namext != NULL) free (namext); if (filepath != NULL) free (filepath); if (header != NULL) free (header); ext = NULL; namext = NULL; filepath = NULL; header = NULL; return (0); } /* Return next character in string which is not a space */ static char nextnsp (string) char *string; { char *schar; schar = string; while (*schar == ' ') schar++; return (*schar); } /* Sep 4 1996 New program * Oct 8 1996 Add newline after file name in verbose mode * * Feb 21 1997 Check pointers against NULL explicitly for Linux * Nov 2 1997 Allow search of multiple files from command line or list file * Nov 12 1997 Add option to print tab tables or column headings * Dec 12 1997 Read IRAF version 2 .imh files * * Jan 5 1998 Do not print line unless keyword is found * Jan 27 1998 Clean up scientific notation and trailing zeroes * Mar 12 1998 Read IRAF multi-line keyword values * May 27 1998 Include fitsio.h instead of fitshead.h * Jun 2 1998 Fix bug in hput() * Jun 3 1998 Add -p option * Jun 18 1998 Print tab table heading only if -h option used * Aug 6 1998 Change fitsio.h to fitsfile.h * Sep 1 1998 Set number of decimal places in floating output with -n * Oct 5 1998 Check more carefully for FITS and IRAF files on command line * Nov 30 1998 Add version and help commands for consistency * * Feb 12 1999 Print null string if single keyword is not found * Feb 17 1999 Add -d option to set root input directory * Apr 1 1999 Add warning if too many files or keywords on command line * Apr 2 1999 Add -f and -m to change maximum number of files or keywords * Jun 9 1999 Initialize outline so Linux doesn't print garbage * Jun 21 1999 Fix bug so that -a option works, always printing filename * Jul 13 1999 Use only first token from line of list as filename * Jul 14 1999 Read lists of BOTH keywords and files simultaneously * Jul 15 1999 Reallocate keyword and file lists if default limits exceeded * Oct 22 1999 Drop unused variables after lint * Nov 16 1999 Add -u to always print underscores if keyword not found * Nov 19 1999 Add -f to never print filenames * Nov 30 1999 Fix so no file name is printed if only one file unless -a * Nov 30 1999 Cast realloc's * * Feb 24 2000 Add option to output keyword=value * Mar 1 2000 Add option to read ASCII files with keyword=value in them * Mar 17 2000 Add conditions * Mar 20 2000 Drop leading # from numbers * Mar 21 2000 Add -b option to replace blanks with underscores * Jun 8 2000 If no keywords or files specified, say so * Jun 12 2000 If -p is set, print all file names (-a) * * Feb 21 2001 Add @ wildcard option for multiple WCS keywords * Feb 27 2001 Add space or tab between wildcard multiple WCS keyword values * Apr 23 2001 Add -g for keyword=val and print same way if -v * Sep 25 2001 Allow file and command line lists of ASCII files * * Jan 31 2002 Fix bug to always add underlines if printing tab table headers * Feb 26 2002 Return values to end of line if -l option set * Apr 2 2002 Add option to log processing to stderr * Apr 24 2002 Add -c option to force files to be read as plain ASCII * May 23 2002 Add -x option to specify extension to read * May 31 2002 Add -s option to drop space-padding for tab table readability * Jun 6 2002 Allow -x to specify range of numbered extensions * Jun 18 2002 List filename(s) if -x used * Jun 19 2002 Add verbose argument to GetFITShead() * Jun 20 2002 If -x and no argument, read all extensions * * Feb 5 2003 Set nfext tp zero if no extensions * Mar 25 2003 If null keyword value and padding on, print ___ * Jul 17 2003 Add root directory argumeht to isfilelist() * Oct 29 2003 Allow keyword specification from both list file and command line * Nov 18 2003 Fix strfix() to keep all of exponents (found by Anthony Miceli) * * Apr 15 2004 Allow e as well as E for exponents * Dec 20 2004 If printing filename for tab-separated file, head with PathName * * Jan 14 2005 Change PathName back to filename * Jun 9 2005 Fix bugs dealing with large numbers of files or keywords * Jun 15 2005 Write one-per-line output in SETHEAD input file format * Jul 18 2005 Do not write one-per-line verbose output in SETHEAD input file format * * Jan 17 2006 ALWAYS print line if -a * Jun 20 2006 Clean up code * Jun 28 2006 Do not drop trailing zeroes except to compare values * Jun 29 2006 Rename strclean() strfix() and move to hget.c * Jul 5 2006 If only one extension specified by -x, do not listall * Jul 12 2006 Add option using : to read a sub-keyword from IRAF multi-line * Jul 13 2006 Print only first 999 characters of multiline keyword value * * Jan 10 2007 Declare RevMsg static, not const * Jul 25 2007 Fix bug which badly reset sexigesimal decimal places to ndec * Dec 21 2007 Add option to put range of extensions in filenames * * Jan 09 2008 Fix handling of extensions with files from listfile * Apr 03 2009 Increase default size of multi-line value buffer to 20000 * * Apr 06 2010 Add fillblank argument to agets() * * May 19 2011 Free all allocated memory to eliminate memory leaks * May 20 2011 Add -j option to convert output RA and Dec to J2000 * May 20 2011 Make RA seconds output at least 3 decimal places; Dec, 2 * Jun 21 2011 If FILENAME keyword is requested, first column is FILE_NAME * Aug 12 2011 Fix range of extensions from -x * Aug 12 2011 Add prefixed range of extensions from -x * Dec 14 2011 If length of header/file content string is zero, exit with error * * Aug 10 2012 Call fk425e() instead of fk425() * * May 7 2014 Fix bug with unallocated extension * May 29 2014 Fix bugs dealing with freeing allocated memory * Aug 25 2014 Fix bug dealing with ranges of extensions * Dec 19 2014 Add option to separate values by first character of keyword * * Jan 20 2015 Add quotes to string values with spaces in -e option */