/*** File libwcs/hget.c *** May 19, 2011 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1994-2011 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: hget.c (Get FITS Header parameter values) * Purpose: Extract values for variables from FITS header string * Subroutine: hgeti2 (hstring,keyword,ival) returns short integer * Subroutine: hgeti4c (hstring,keyword,wchar,ival) returns long integer * Subroutine: hgeti4 (hstring,keyword,ival) returns long integer * Subroutine: hgetr4 (hstring,keyword,rval) returns real * Subroutine: hgetra (hstring,keyword,ra) returns double RA in degrees * Subroutine: hgetdec (hstring,keyword,dec) returns double Dec in degrees * Subroutine: hgetr8c (hstring,keyword,wchar,dval) returns double * Subroutine: hgetr8 (hstring,keyword,dval) returns double * Subroutine: hgetl (hstring,keyword,lval) returns logical int (0=F, 1=T) * Subroutine: hgetsc (hstring,keyword,wchar,lstr,str) returns character string * Subroutine: hgets (hstring,keyword, lstr, str) returns character string * Subroutine: hgetm (hstring,keyword, lstr, str) returns multi-keyword string * Subroutine: hgetdate (hstring,keyword,date) returns date as fractional year * Subroutine: hgetndec (hstring, keyword, ndec) returns number of dec. places * Subroutine: hgetc (hstring,keyword) returns character string * Subroutine: blsearch (hstring,keyword) returns pointer to blank lines before keyword * Subroutine: ksearch (hstring,keyword) returns pointer to header string entry * Subroutine: str2ra (in) converts string to right ascension in degrees * Subroutine: str2dec (in) converts string to declination in degrees * Subroutine: strsrch (s1, s2) finds string s2 in null-terminated string s1 * Subroutine: strnsrch (s1, s2, ls1) finds string s2 in ls1-byte string s1 * Subroutine: hlength (header,lhead) sets length of FITS header for searching * Subroutine: isnum (string) returns 1 if integer, 2 if fp number, else 0 * Subroutine: notnum (string) returns 0 if number, else 1 * Subroutine: numdec (string) returns number of decimal places in numeric string * Subroutine: strfix (string,blankfill,zerodrop) removes extraneous characters */ #include /* NULL, strlen, strstr, strcpy */ #include #include "fitshead.h" /* FITS header extraction subroutines */ #include #ifndef VMS #include #else #define INT_MAX 2147483647 /* Biggest number that can fit in long */ #define SHRT_MAX 32767 #endif #define VLENGTH 81 #ifdef USE_SAOLIB static int use_saolib=0; #endif char *hgetc (); static char val[VLENGTH+1]; static int multiline = 0; static int lhead0 = 0; /* Length of header string */ /* Set the length of the header string, if not terminated by NULL */ int hlength (header, lhead) const char *header; /* FITS header */ int lhead; /* Maximum length of FITS header */ { char *hend; if (lhead > 0) lhead0 = lhead; else { lhead0 = 0; hend = ksearch (header,"END"); lhead0 = hend + 80 - header; } return (lhead0); } /* Return the length of the header string, computing it if lhead0 not set */ int gethlength (header) char *header; /* FITS header */ { if (lhead0 > 0) return (lhead0); else return (hlength (header, 0)); } /* Extract Integer*4 value for variable from FITS header string */ int hgeti4c (hstring,keyword,wchar,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const char *wchar; /* Character of multiple WCS header; =0 if unused */ int *ival; /* Keyword value returned */ { char keyword1[16]; int lkey; if (wchar[0] < (char) 64) return (hgeti4 (hstring, keyword, ival)); else { strcpy (keyword1, keyword); lkey = strlen (keyword); keyword1[lkey] = wchar[0]; keyword1[lkey+1] = (char) 0; return (hgeti4 (hstring, keyword1, ival)); } } /* Extract long value for variable from FITS header string */ int hgeti4 (hstring,keyword,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ival; { char *value; double dval; int minint; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; minint = -INT_MAX - 1; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } dval = atof (val); if (dval+0.001 > INT_MAX) *ival = INT_MAX; else if (dval >= 0) *ival = (int) (dval + 0.001); else if (dval-0.001 < minint) *ival = minint; else *ival = (int) (dval - 0.001); return (1); } else { return (0); } } /* Extract integer*2 value for variable from fits header string */ int hgeti2 (hstring,keyword,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ short *ival; { char *value; double dval; int minshort; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } dval = atof (val); minshort = -SHRT_MAX - 1; if (dval+0.001 > SHRT_MAX) *ival = SHRT_MAX; else if (dval >= 0) *ival = (short) (dval + 0.001); else if (dval-0.001 < minshort) *ival = minshort; else *ival = (short) (dval - 0.001); return (1); } else { return (0); } } /* Extract real value for variable from FITS header string */ int hgetr4 (hstring,keyword,rval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ float *rval; { char *value; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } *rval = (float) atof (val); return (1); } else { return (0); } } /* Extract real*8 right ascension in degrees from FITS header string */ int hgetra (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; /* Right ascension in degrees (returned) */ { char *value; /* Get value from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII colon-delimited string to binary */ if (value != NULL) { *dval = str2ra (value); return (1); } else return (0); } /* Extract real*8 declination in degrees from FITS header string */ int hgetdec (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; /* Right ascension in degrees (returned) */ { char *value; /* Get value from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII colon-delimited string to binary */ if (value != NULL) { *dval = str2dec (value); return (1); } else return (0); } /* Extract real*8 value for variable from FITS header string */ int hgetr8c (hstring,keyword,wchar,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const char *wchar; /* Character of multiple WCS header; =0 if unused */ double *dval; /* Keyword value returned */ { char keyword1[16]; int lkey; if (wchar[0] < (char) 64) return (hgetr8 (hstring, keyword, dval)); else { strcpy (keyword1, keyword); lkey = strlen (keyword); keyword1[lkey] = wchar[0]; keyword1[lkey+1] = (char) 0; return (hgetr8 (hstring, keyword1, dval)); } } /* Extract real*8 value for variable from FITS header string */ int hgetr8 (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; { char *value; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } *dval = atof (val); return (1); } else { return (0); } } /* Extract logical value for variable from FITS header string */ int hgetl (hstring,keyword,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ival; { char *value; char newval; int lval; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); newval = val[0]; if (newval == 't' || newval == 'T') *ival = 1; else *ival = 0; return (1); } else { return (0); } } /* Extract real*8 date from FITS header string (dd/mm/yy or dd-mm-yy) */ int hgetdate (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; { double yeardays, seconds, fday; char *value,*sstr, *dstr, *tstr, *cstr, *nval; int year, month, day, yday, i, hours, minutes; static int mday[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { sstr = strchr (value,'/'); dstr = strchr (value,'-'); /* Original FITS date format: dd/mm/yy */ if (sstr > value) { *sstr = '\0'; day = (int) atof (value); *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr == NULL) sstr = strchr (nval,'-'); if (sstr > value) { *sstr = '\0'; month = (int) atof (nval); *sstr = '/'; nval = sstr + 1; year = (int) atof (nval); if (day > 31) { yday = year; year = day; day = yday; } if (year >= 0 && year <= 49) year = year + 2000; else if (year < 100) year = year + 1900; if ((year % 4) == 0) mday[1] = 29; else mday[1] = 28; if ((year % 100) == 0 && (year % 400) != 0) mday[1] = 28; if (day > mday[month-1]) day = mday[month-1]; else if (day < 1) day = 1; if (mday[1] == 28) yeardays = 365.0; else yeardays = 366.0; yday = day - 1; for (i = 0; i < month-1; i++) yday = yday + mday[i]; *dval = (double) year + ((double)yday / yeardays); return (1); } else return (0); } /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ else if (dstr > value) { *dstr = '\0'; year = (int) atof (value); *dstr = '-'; nval = dstr + 1; dstr = strchr (nval,'-'); month = 1; day = 1; tstr = NULL; if (dstr > value) { *dstr = '\0'; month = (int) atof (nval); *dstr = '-'; nval = dstr + 1; tstr = strchr (nval,'T'); if (tstr > value) *tstr = '\0'; day = (int) atof (nval); if (tstr > value) *tstr = 'T'; } /* If year is < 32, it is really day of month in old format */ if (year < 32) { i = year; year = day + 1900; day = i; } if ((year % 4) == 0) mday[1] = 29; else mday[1] = 28; if ((year % 100) == 0 && (year % 400) != 0) mday[1] = 28; if (day > mday[month-1]) day = mday[month-1]; else if (day < 1) day = 1; if (mday[1] == 28) yeardays = 365.0; else yeardays = 366.0; yday = day - 1; for (i = 0; i < month-1; i++) yday = yday + mday[i]; *dval = (double) year + ((double)yday / yeardays); /* Extract time, if it is present */ if (tstr > value) { nval = tstr + 1; hours = 0.0; minutes = 0.0; seconds = 0.0; cstr = strchr (nval,':'); if (cstr > value) { *cstr = '\0'; hours = (int) atof (nval); *cstr = ':'; nval = cstr + 1; cstr = strchr (nval,':'); if (cstr > value) { *cstr = '\0'; minutes = (int) atof (nval); *cstr = ':'; nval = cstr + 1; seconds = atof (nval); } else { minutes = (int) atof (nval); seconds = 0.0; } } fday = ((3.6e3 * (double)hours) + (6.e1 * (double)minutes) + seconds) / 8.64e4; *dval = *dval + (fday / yeardays); } return (1); } else return (0); } else return (0); } /* Extract IRAF multiple-keyword string value from FITS header string */ int hgetm (hstring, keyword, lstr, str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the root name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char *value; char *stri; char keywordi[16]; int lval, lstri, ikey; char keyform[8]; stri = str; lstri = lstr; sprintf (keywordi, "%s_1", keyword); if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%d"); else { sprintf (keywordi, "%s_01", keyword); if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%02d"); else { sprintf (keywordi, "%s_001", keyword); if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%03d"); else if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%03d"); else return (0); } } /* Loop through sequentially-named keywords */ multiline = 1; for (ikey = 1; ikey < 500; ikey++) { sprintf (keywordi, keyform, keyword, ikey); /* Get value for this keyword */ value = hgetc (hstring, keywordi); if (value != NULL) { lval = strlen (value); if (lval < lstri) strcpy (stri, value); else if (lstri > 1) { strncpy (stri, value, lstri-1); stri[lstri] = (char) 0; break; } else { str[0] = value[0]; break; } } else break; stri = stri + lval; lstri = lstri - lval; } multiline = 0; /* Return 1 if any keyword found, else 0 */ if (ikey > 1) return (1); else return (0); } /* Extract string value for variable from FITS header string */ int hgetsc (hstring,keyword,wchar,lstr,str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const char *wchar; /* Character of multiple WCS header; =0 if unused */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char keyword1[16]; int lkey; if (wchar[0] < (char) 64) return (hgets (hstring, keyword, lstr, str)); else { strcpy (keyword1, keyword); lkey = strlen (keyword); keyword1[lkey] = wchar[0]; keyword1[lkey+1] = (char) 0; return (hgets (hstring, keyword1, lstr, str)); } } /* Extract string value for variable from FITS header string */ int hgets (hstring, keyword, lstr, str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char *value; int lval; /* Get value and comment from header string */ value = hgetc (hstring,keyword); if (value != NULL) { lval = strlen (value); if (lval < lstr) strcpy (str, value); else if (lstr > 1) strncpy (str, value, lstr-1); else str[0] = value[0]; return (1); } else return (0); } /* Extract number of decimal places for value in FITS header string */ int hgetndec (hstring, keyword, ndec) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ndec; /* Number of decimal places in keyword value */ { char *value; int i, nchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Find end of string and count backward to decimal point */ *ndec = 0; if (value != NULL) { nchar = strlen (value); for (i = nchar-1; i >= 0; i--) { if (value[i] == '.') return (1); *ndec = *ndec + 1; } return (1); } else return (0); } /* Extract character value for variable from FITS header string */ char * hgetc (hstring,keyword0) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword0; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ { static char cval[80]; char *value; char cwhite[2]; char squot[2], dquot[2], lbracket[2], rbracket[2], slash[2], comma[2]; char space; char keyword[81]; /* large for ESO hierarchical keywords */ char line[100]; char *vpos, *cpar; char *q1, *q2, *v1, *v2, *c1, *brack1, *brack2; int ipar, i, lkey; #ifdef USE_SAOLIB int iel=1, ip=1, nel, np, ier; char *get_fits_head_str(); if( !use_saolib ){ #endif squot[0] = (char) 39; squot[1] = (char) 0; dquot[0] = (char) 34; dquot[1] = (char) 0; lbracket[0] = (char) 91; lbracket[1] = (char) 0; comma[0] = (char) 44; comma[1] = (char) 0; rbracket[0] = (char) 93; rbracket[1] = (char) 0; slash[0] = (char) 47; slash[1] = (char) 0; space = (char) 32; /* Find length of variable name */ strncpy (keyword,keyword0, sizeof(keyword)-1); brack1 = strsrch (keyword,lbracket); if (brack1 == NULL) brack1 = strsrch (keyword,comma); if (brack1 != NULL) { *brack1 = '\0'; brack1++; } /* Search header string for variable name */ vpos = ksearch (hstring,keyword); /* Exit if not found */ if (vpos == NULL) return (NULL); /* Initialize line to nulls */ for (i = 0; i < 100; i++) line[i] = 0; /* In standard FITS, data lasts until 80th character */ /* Extract entry for this variable from the header */ strncpy (line,vpos,80); /* Check for quoted value */ q1 = strsrch (line,squot); c1 = strsrch (line,slash); if (q1 != NULL) { if (c1 != NULL && q1 < c1) { q2 = strsrch (q1+1,squot); if (q2 == NULL) { q2 = c1 - 1; while (*q2 == space) q2--; q2++; } else if (c1 < q2) c1 = strsrch (q2,slash); } else if (c1 == NULL) { q2 = strsrch (q1+1,squot); if (q2 == NULL) { q2 = line + 79; while (*q2 == space) q2--; q2++; } } else q1 = NULL; } else { q1 = strsrch (line,dquot); if (q1 != NULL) { if (c1 != NULL && q1 < c1) { q2 = strsrch (q1+1,dquot); if (q2 == NULL) { q2 = c1 - 1; while (*q2 == space) q2--; q2++; } else if (c1 < q2) c1 = strsrch (q2,slash); } else if (c1 == NULL) { q2 = strsrch (q1+1,dquot); if (q2 == NULL) { q2 = line + 79; while (*q2 == space) q2--; q2++; } } else q1 = NULL; } else { q1 = NULL; q2 = line + 10; } } /* Extract value and remove excess spaces */ if (q1 != NULL) { v1 = q1 + 1; v2 = q2; } else { v1 = strsrch (line,"="); if (v1 == NULL) v1 = line + 9; else v1 = v1 + 1; c1 = strsrch (line,"/"); if (c1 != NULL) v2 = c1; else v2 = line + 79; } /* Ignore leading spaces if not multiline */ if (!multiline) { while (*v1 == ' ' && v1 < v2) { v1++; } } /* Drop trailing spaces */ *v2 = '\0'; if (!multiline) { v2--; while ((*v2 == ' ' || *v2 == (char) 13) && v2 > v1) { *v2 = '\0'; v2--; } } /* Convert -zero to just plain 0 */ if (!strcmp (v1, "-0")) v1++; strcpy (cval,v1); value = cval; /* If keyword has brackets, extract appropriate token from value */ if (brack1 != NULL) { brack2 = strsrch (brack1,rbracket); if (brack2 != NULL) *brack2 = '\0'; if (isnum (brack1)) { ipar = atoi (brack1); cwhite[0] = ' '; cwhite[1] = '\0'; if (ipar > 0) { for (i = 1; i <= ipar; i++) { cpar = strtok (v1,cwhite); v1 = NULL; } if (cpar != NULL) { strcpy (cval,cpar); value = cval; } else value = NULL; } /* If token counter is negative, include rest of value */ else if (ipar < 0) { for (i = 1; i < -ipar; i++) { v1 = strchr (v1, ' '); if (v1 == NULL) break; else v1 = v1 + 1; } if (v1 != NULL) { strcpy (cval, v1); value = cval; } else value = NULL; } } else { lkey = strlen (brack1); for (i = 0; i < lkey; i++) { if (brack1[i] > 64 && brack1[i] < 91) brack1[i] = brack1[i] + 32; } v1 = igetc (cval, brack1); if (v1) { strcpy (cval,v1); value = cval; } else value = NULL; } } return (value); #ifdef USE_SAOLIB } else { return(get_fits_head_str(keyword0, iel, ip, &nel, &np, &ier, hstring)); } #endif } /* Find beginning of fillable blank line before FITS header keyword line */ char * blsearch (hstring,keyword) /* Find entry for keyword keyword in FITS header string hstring. (the keyword may have a maximum of eight letters) NULL is returned if the keyword is not found */ const char *hstring; /* character string containing fits-style header information in the format = {/ } the default is that each entry is 80 characters long; however, lines may be of arbitrary length terminated by nulls, carriage returns or linefeeds, if packed is true. */ const char *keyword; /* character string containing the name of the variable to be returned. ksearch searches for a line beginning with this string. The string may be a character literal or a character variable terminated by a null or '$'. it is truncated to 8 characters. */ { const char *headlast; char *loc, *headnext, *pval, *lc, *line; char *bval; int icol, nextchar, lkey, nleft, lhstr; pval = 0; /* Search header string for variable name */ if (lhead0) lhstr = lhead0; else { lhstr = 0; while (lhstr < 256000 && hstring[lhstr] != 0) lhstr++; } headlast = hstring + lhstr; headnext = (char *) hstring; pval = NULL; while (headnext < headlast) { nleft = headlast - headnext; loc = strncsrch (headnext, keyword, nleft); /* Exit if keyword is not found */ if (loc == NULL) { break; } icol = (loc - hstring) % 80; lkey = strlen (keyword); nextchar = (int) *(loc + lkey); /* If this is not in the first 8 characters of a line, keep searching */ if (icol > 7) headnext = loc + 1; /* If parameter name in header is longer, keep searching */ else if (nextchar != 61 && nextchar > 32 && nextchar < 127) headnext = loc + 1; /* If preceeding characters in line are not blanks, keep searching */ else { line = loc - icol; for (lc = line; lc < loc; lc++) { if (*lc != ' ') headnext = loc + 1; } /* Return pointer to start of line if match */ if (loc >= headnext) { pval = line; break; } } } /* Return NULL to calling program if keyword is not found */ if (pval == NULL) return (pval); /* Return NULL if keyword is found at start of FITS header string */ if (pval == hstring) return (NULL); /* Find last nonblank in FITS header string line before requested keyword */ bval = pval - 80; while (!strncmp (bval," ",8) && bval >= hstring) bval = bval - 80; bval = bval + 80; /* Return pointer to calling program if blank lines found */ if (bval < pval && bval >= hstring) return (bval); else return (NULL); } /* Find FITS header line containing specified keyword */ /*** waj ***/ extern char* findit(char*,char*); char* ksearch(const char* hstring, const char* keyword) { return findit((char*)hstring, (char*)keyword); } char * ksearchh (hstring,keyword) /*** waj ***/ /* Find entry for keyword keyword in FITS header string hstring. (the keyword may have a maximum of eight letters) NULL is returned if the keyword is not found */ const char *hstring; /* character string containing fits-style header information in the format = {/ } the default is that each entry is 80 characters long; however, lines may be of arbitrary length terminated by nulls, carriage returns or linefeeds, if packed is true. */ const char *keyword; /* character string containing the name of the variable to be returned. ksearch searches for a line beginning with this string. The string may be a character literal or a character variable terminated by a null or '$'. it is truncated to 8 characters. */ { const char *headlast; char *loc, *headnext, *pval, *lc, *line; int icol, nextchar, lkey, nleft, lhead, lmax; #ifdef USE_SAOLIB int iel=1, ip=1, nel, np, ier; char *get_fits_head_str(); if( !use_saolib ){ #endif pval = 0; /* Find current length of header string */ if (lhead0) lmax = lhead0; else lmax = 256000; for (lhead = 0; lhead < lmax; lhead++) { if (hstring[lhead] <= (char) 0) break; } /* Search header string for variable name */ headlast = hstring + lhead; headnext = (char *) hstring; pval = NULL; while (headnext < headlast) { nleft = headlast - headnext; loc = strncsrch (headnext, keyword, nleft); /* Exit if keyword is not found */ if (loc == NULL) { break; } icol = (loc - hstring) % 80; lkey = strlen (keyword); nextchar = (int) *(loc + lkey); /* If this is not in the first 8 characters of a line, keep searching */ if (icol > 7) headnext = loc + 1; /* If parameter name in header is longer, keep searching */ else if (nextchar != 61 && nextchar > 32 && nextchar < 127) headnext = loc + 1; /* If preceeding characters in line are not blanks, keep searching */ else { line = loc - icol; for (lc = line; lc < loc; lc++) { if (*lc != ' ') headnext = loc + 1; } /* Return pointer to start of line if match */ if (loc >= headnext) { pval = line; break; } } } /* Return pointer to calling program */ return (pval); #ifdef USE_SAOLIB } else { if (get_fits_head_str(keyword,iel,ip,&nel,&np,&ier,hstring) != NULL) return(hstring); else return(NULL); } #endif } /* Return the right ascension in degrees from sexagesimal hours or decimal degrees */ double str2ra (in) const char *in; /* Character string of sexigesimal hours or decimal degrees */ { double ra; /* Right ascension in degrees (returned) */ ra = str2dec (in); if (strsrch (in,":")) ra = ra * 15.0; return (ra); } /* Return the declination in degrees from sexagesimal or decimal degrees */ double str2dec (in) const char *in; /* Character string of sexigesimal or decimal degrees */ { double dec; /* Declination in degrees (returned) */ double deg, min, sec, sign; char *value, *c1, *c2; int lval; char *dchar; dec = 0.0; /* Return 0.0 if string is null */ if (in == NULL) return (dec); /* Translate value from ASCII colon-delimited string to binary */ if (in[0]) { value = (char *) in; /* Remove leading spaces */ while (*value == ' ') value++; /* Save sign */ if (*value == '-') { sign = -1.0; value++; } else if (*value == '+') { sign = 1.0; value++; } else sign = 1.0; /* Turn comma into space */ if ((c1 = strsrch (value,",")) != NULL) *c1 = ' '; /* Remove trailing spaces */ lval = strlen (value); while (value[lval-1] == ' ') lval--; if ((c1 = strsrch (value,":")) == NULL) c1 = strnsrch (value," ",lval); if (c1 != NULL) { *c1 = 0; deg = (double) atoi (value); *c1 = ':'; value = c1 + 1; if ((c2 = strsrch (value,":")) == NULL) c2 = strsrch (value," "); if (c2 != NULL) { *c2 = 0; min = (double) atoi (value); *c2 = ':'; value = c2 + 1; sec = atof (value); } else { sec = 0.0; if ((c1 = strsrch (value,".")) != NULL) min = atof (value); if (strlen (value) > 0) min = (double) atoi (value); } dec = sign * (deg + (min / 60.0) + (sec / 3600.0)); } else if (isnum (value) == 2) { if ((dchar = strchr (value, 'D'))) *dchar = 'e'; if ((dchar = strchr (value, 'd'))) *dchar = 'e'; if ((dchar = strchr (value, 'E'))) *dchar = 'e'; dec = sign * atof (value); } else dec = sign * (double) atoi (value); } return (dec); } /* Find string s2 within null-terminated string s1 */ char * strsrch (s1, s2) const char *s1; /* String to search */ const char *s2; /* String to look for */ { int ls1; ls1 = strlen (s1); return (strnsrch (s1, s2, ls1)); } /* Find string s2 within string s1 */ char * strnsrch (s1, s2, ls1) const char *s1; /* String to search */ const char *s2; /* String to look for */ const int ls1; /* Length of string being searched */ { char *s,*s1e; char cfirst,clast; int i,ls2; /* Return null string if either pointer is NULL */ if (s1 == NULL || s2 == NULL) return (NULL); /* A zero-length pattern is found in any string */ ls2 = strlen (s2); if (ls2 ==0) return ((char *) s1); /* Only a zero-length string can be found in a zero-length string */ if (ls1 ==0) return (NULL); cfirst = (char) s2[0]; clast = (char) s2[ls2-1]; s1e = (char *) s1 + (int) ls1 - ls2 + 1; s = (char *) s1; while (s < s1e) { /* Search for first character in pattern string */ if (*s == cfirst) { /* If single character search, return */ if (ls2 == 1) return (s); /* Search for last character in pattern string if first found */ if (s[ls2-1] == clast) { /* If two-character search, return */ if (ls2 == 2) return (s); /* If 3 or more characters, check for rest of search string */ i = 1; while (i < ls2 && s[i] == s2[i]) i++; /* If entire string matches, return */ if (i >= ls2) return (s); } } s++; } return (NULL); } /* Find string s2 within null-terminated string s1 (case-free search) */ char * strcsrch (s1, s2) const char *s1; /* String to search */ const char *s2; /* String to look for */ { int ls1; ls1 = strlen ((char *) s1); return (strncsrch (s1, s2, ls1)); } /* Find string s2 within string s1 (case-free search) */ char * strncsrch (s1, s2, ls1) const char *s1; /* String to search */ const char *s2; /* String to look for */ const int ls1; /* Length of string being searched */ { char *s,*s1e, sl, *os2; char cfirst,ocfirst; char clast = ' '; char oclast = ' '; int i,ls2; /* Return null string if either pointer is NULL */ if (s1 == NULL || s2 == NULL) return (NULL); /* A zero-length pattern is found in any string */ ls2 = strlen (s2); if (ls2 ==0) return ((char *) s1); /* Only a zero-length string can be found in a zero-length string */ os2 = NULL; if (ls1 ==0) return (NULL); /* For one or two characters, set opposite case first and last letters */ if (ls2 < 3) { cfirst = (char) s2[0]; if (cfirst > 96 && cfirst < 123) ocfirst = cfirst - 32; else if (cfirst > 64 && cfirst < 91) ocfirst = cfirst + 32; else ocfirst = cfirst; if (ls2 > 1) { clast = s2[1]; if (clast > 96 && clast < 123) oclast = clast - 32; else if (clast > 64 && clast < 91) oclast = clast + 32; else oclast = clast; } } /* Else duplicate string with opposite case letters for comparison */ else { os2 = (char *) calloc (ls2, 1); for (i = 0; i < ls2; i++) { if (s2[i] > 96 && s2[i] < 123) os2[i] = s2[i] - 32; else if (s2[i] > 64 && s2[i] < 91) os2[i] = s2[i] + 32; else os2[i] = s2[i]; } cfirst = s2[0]; ocfirst = os2[0]; clast = s2[ls2-1]; oclast = os2[ls2-1]; } /* Loop through input string, character by character */ s = (char *) s1; s1e = s + (int) ls1 - ls2 + 1; while (s < s1e) { /* Search for first character in pattern string */ if (*s == cfirst || *s == ocfirst) { /* If single character search, return */ if (ls2 == 1) { if (os2 != NULL) free (os2); return (s); } /* Search for last character in pattern string if first found */ sl = s[ls2-1]; if (sl == clast || sl == oclast) { /* If two-character search, return */ if (ls2 == 2) { if (os2 != NULL) free (os2); return (s); } /* If 3 or more characters, check for rest of search string */ i = 1; while (i < ls2 && (s[i] == (char) s2[i] || s[i] == os2[i])) i++; /* If entire string matches, return */ if (i >= ls2) { if (os2 != NULL) free (os2); return (s); } } } s++; } if (os2 != NULL) free (os2); return (NULL); } int notnum (string) const char *string; /* Character string */ { if (isnum (string)) return (0); else return (1); } /* ISNUM-- Return 1 if string is an integer number, 2 if floating point, 3 if sexigesimal, with or without decimal point else 0 */ int isnum (string) const char *string; /* Character string */ { int lstr, i, nd, cl; char cstr, cstr1; int fpcode; /* Return 0 if string is NULL */ if (string == NULL) return (0); lstr = strlen (string); nd = 0; cl = 0; fpcode = 1; /* Return 0 if string starts with a D or E */ cstr = string[0]; if (cstr == 'D' || cstr == 'd' || cstr == 'E' || cstr == 'e') { return (0); } /* Remove trailing spaces */ while (string[lstr-1] == ' ') lstr--; /* Numeric strings contain 0123456789-+ and d or e for exponents */ for (i = 0; i < lstr; i++) { cstr = string[i]; if (cstr == '\n') break; /* Ignore leading spaces */ if (cstr == ' ' && nd == 0) continue; if ((cstr < 48 || cstr > 57) && cstr != '+' && cstr != '-' && cstr != 'D' && cstr != 'd' && cstr != 'E' && cstr != 'e' && cstr != ':' && cstr != '.') return (0); else if (cstr == '+' || cstr == '-') { if (string[i+1] == '-' || string[i+1] == '+') return (0); else if (i > 0) { cstr1 = string[i-1]; if (cstr1 != 'D' && cstr1 != 'd' && cstr1 != 'E' && cstr1 != 'e' && cstr1 != ':' && cstr1 != ' ') return (0); } } else if (cstr >= 47 && cstr <= 57) nd++; /* Check for colon */ else if (cstr == 58) cl++; if (cstr=='.' || cstr=='d' || cstr=='e' || cstr=='d' || cstr=='e') fpcode = 2; } if (nd > 0) { if (cl) fpcode = 3; return (fpcode); } else return (0); } /* NUMDEC -- Return number of decimal places in numeric string (-1 if not number) */ int numdec (string) const char *string; /* Numeric string */ { char *cdot; int lstr; if (notnum (string) && !strchr (string, ':')) return (-1); else { lstr = strlen (string); if ((cdot = strchr (string, '.')) == NULL) return (0); else return (lstr - (cdot - string) - 1); } } #ifdef USE_SAOLIB int set_saolib(hstring) void *hstring; { if( *((int *)hstring) == 142857 ) use_saolib = 1; else use_saolib = 0; } #endif /* Remove exponent, leading #, surrounding parentheses, and/or trailing zeroes, if reasonable */ void strfix (string, fillblank, dropzero) char *string; /* String to modify */ int fillblank; /* If nonzero, fill blanks with underscores */ int dropzero; /* If nonzero, drop trailing zeroes */ { char *sdot, *s, *strend, *str, ctemp, *slast; int ndek, lstr, i; /* If number, ignore leading # and remove trailing non-numeric character */ if (string[0] == '#') { strend = string + strlen (string); str = string + 1; strend = str + strlen (str) - 1; ctemp = *strend; if (!isnum (strend)) *strend = (char) 0; if (isnum (str)) { strend = string + strlen (string); for (str = string; str < strend; str++) *str = *(str + 1); } else *strend = ctemp; } /* Remove parentheses if they enclose the string */ if (string[0] == '(') { lstr = strlen (string); if (string[lstr-1] == ')') { string[lstr-1] = (char) 0; strend = string + lstr - 1; for (str = string; str < strend; str++) *str = *(str+1); string[lstr-2] = (char) 0; } } /* Remove positive exponent if there are enough digits given */ if (isnum (string) > 1 && strsrch (string, "E+") != NULL) { lstr = strlen (string); ndek = (int) (string[lstr-1] - 48); ndek = ndek + (10 * ((int) (string[lstr-2] - 48))); if (ndek < lstr - 7) { lstr = lstr - 4; string[lstr] = (char) 0; string[lstr+1] = (char) 0; string[lstr+2] = (char) 0; string[lstr+3] = (char) 0; sdot = strchr (string, '.'); if (ndek > 0 && sdot != NULL) { for (i = 1; i <= ndek; i++) { *sdot = *(sdot+1); sdot++; *sdot = '.'; } } } } /* Remove trailing zeroes if they are not significant */ if (dropzero) { if (isnum (string) > 1 && strchr (string, '.') != NULL && strsrch (string, "E-") == NULL && strsrch (string, "E+") == NULL && strsrch (string, "e-") == NULL && strsrch (string, "e+") == NULL) { lstr = strlen (string); s = string + lstr - 1; while (*s == '0' && lstr > 1) { if (*(s - 1) != '.') { *s = (char) 0; lstr --; } s--; } } } /* Remove trailing decimal point */ lstr = strlen (string); s = string + lstr - 1; if (*s == '.') *s = (char) 0; /* Replace embedded blanks with underscores, if requested to */ if (fillblank) { lstr = strlen (string); slast = string + lstr; for (s = string; s < slast; s++) { if (*s == ' ') *s = '_'; } } return; } /* Oct 28 1994 New program * * Mar 1 1995 Search for / after second quote, not first one * May 2 1995 Initialize line in HGETC; deal with logicals in HGETL better * May 4 1995 Declare STRSRCH in KSEARCH * Aug 7 1995 Fix line initialization in HGETC * Dec 22 1995 Add HGETRA and HGETDEC to get degrees from xx:xx:xx.xxx string * * Jan 26 1996 Fix HGETL to not crash when parameter is not present * Feb 1 1996 Fix HGETC to deal with quotes correctly * Feb 1 1996 Fix HGETDEG to deal with sign correctly * Feb 6 1996 Add HGETS to update character strings * Feb 8 1996 Fix STRSRCH to find final characters in string * Feb 23 1996 Add string to degree conversions * Apr 26 1996 Add HGETDATE to get fractional year from date string * May 22 1996 Fix documentation; return double from STR2RA and STR2DEC * May 28 1996 Fix string translation of RA and Dec when no seconds * Jun 10 1996 Remove unused variables after running lint * Jun 17 1996 Fix bug which failed to return single character strings * Jul 1 1996 Skip sign when reading declination after testing for it * Jul 19 1996 Do not divide by 15 if RA header value is already in degrees * Aug 5 1996 Add STRNSRCH to search strings which are not null-terminated * Aug 6 1996 Make minor changes after lint * Aug 8 1996 Fix ksearch bug which finds wrong keywords * Aug 13 1996 Fix sign bug in STR2DEC for degrees * Aug 26 1996 Drop unused variables ICOL0, NLINE, PREVCHAR from KSEARCH * Sep 10 1996 Fix header length setting code * Oct 15 1996 Clean up loops and fix ICOL assignment * Nov 13 1996 Handle integer degrees correctly in STR2DEC * Nov 21 1996 Make changes for Linux thanks to Sidik Isani * Dec 12 1996 Add ISNUM to check to see whether strings are numbers * * Jan 22 1997 Add ifdefs for Eric Mandel (SAOtng) * Jan 27 1997 Convert to integer through ATOF so exponents are recognized * Jul 25 1997 Implement FITS version of ISO date format * * Feb 24 1998 Implement code to return IRAF multiple-keyword strings * Mar 12 1998 Add subroutine NOTNUM * Mar 27 1998 Add changes to match SKYCAT version * Apr 30 1998 Add BLSEARCH() to find blank lines before END * May 27 1998 Add HGETNDEC() to get number of decimal places in entry * Jun 1 1998 Add VMS patch from Harry Payne at StSci * Jun 18 1998 Fix code which extracts tokens from string values * Jul 21 1998 Drop minus sign for values of -0 * Sep 29 1998 Treat hyphen-separated date as old format if 2-digit year * Oct 7 1998 Clean up search for last blank line * * Apr 5 1999 Check lengths of strings before copying them * May 5 1999 values.h -> POSIX limits.h: MAXINT->INT_MAX, MAXSHORT->SHRT_MAX * Jul 15 1999 Add hgetm() options of 1- or 2-digit keyword extensions * Oct 6 1999 Add gethlength() to return header length * Oct 14 1999 In ksearch(), search only to null not to end of buffer * Oct 15 1999 Return 1 from hgetndec() if successful * Oct 20 1999 Drop unused variable after lint (val in hgetndec) * Dec 3 1999 Fix isnum() to reject strings starting with a d or e * Dec 20 1999 Update hgetdate() to get minutes and seconds right * * Feb 10 2000 Parse RA and Dec with spaces as well as colons as separators * Feb 11 2000 Add null at end of multi-line keyword value character string * Feb 25 2000 Change max search string length from 57600 to 256000 * Mar 15 2000 Deal with missing second quotes in string values * Mar 17 2000 Return 2 from isnum() if number is floating point (.de) * Mar 17 2000 Ignore leading # for numeric values in header * Mar 21 2000 Implement -n to get string value starting with nth token * Apr 5 2000 Reject +- in isnum() * Jun 9 2000 Read keyword values even if no equal sign is present * Sep 20 2000 Ignore linefeed at end of number in isnum() * Oct 23 2000 Fix handling of embedded + or - in isnum() * * Jan 19 2000 Return 0 from isnum(), str2ra(), and str2dec() if string is null * Mar 30 2001 Fix header length finding algorithm in ksearch() * Jul 13 2001 Make val[] static int instead of int; drop unused variables * Sep 12 2001 Read yyyy/mm/dd dates as well as dd/mm/yyyy * Sep 20 2001 Ignore leading spaces in str2dec() * Sep 20 2001 Ignore trailing spaces in isnum() * * Apr 3 2002 Add hgetr8c(), hgeti4c(), and hgetsc() for multiple WCS handling * Apr 26 2002 Fix bug in hgetsc(), hgeti4c(), and hgetr8c() found by Bill Joye * Jun 26 2002 Do not drop leading or trailing spaces in multi-line values * Aug 6 2002 Add strcsrch() and strncsrch() for case-insensitive searches * Aug 30 2002 Fix bug so strcsrch() really is case-insensitive * Oct 20 2003 Add numdec() to return number of decimal places in a string * Dec 9 2003 Fix numdec() to return 0 if no digits after decimal point * * Feb 26 2004 Extract value from keyword=value strings within a keyword value * Apr 9 2004 Use strncsrch() in ksearch() to find differently-cased keywords * Apr 28 2004 Free os2 in strncsrch() only if it is allocated * Jul 13 2004 Accept D, d, E, or e as exponent delimiter in floating points * Aug 30 2004 Change numdec() to accept sexigesimal numbers (:'s) * * Jun 27 2005 Drop unused variables * Aug 30 2005 Adjust code in hlength() * * Jun 20 2006 Initialize uninitialized variables in strnsrch() * Jun 29 2006 Add new subroutine strfix() to clean strings for other uses * Jul 13 2006 Increase maximum number of multiline keywords from 20 to 500 * * Jan 4 2007 Declare header, keyword to be const * Jan 4 2007 Change WCS letter from char to char* * Feb 28 2007 If header length is not set in hlength, set it to 0 * May 31 2007 Add return value of 3 to isnum() if string has colon(s) * Aug 22 2007 If closing quote not found, make one up * * Nov 12 2009 In strfix(), if drop enclosing parantheses * * Apr 19 2011 In str2dec(), change comma to space * May 19 2011 In strncsrch() always free allocated memory before returning */