diff options
Diffstat (limited to 'fitsy/fitshead.c')
-rw-r--r-- | fitsy/fitshead.c | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/fitsy/fitshead.c b/fitsy/fitshead.c new file mode 100644 index 0000000..01dfea2 --- /dev/null +++ b/fitsy/fitshead.c @@ -0,0 +1,483 @@ +/* Fitsy FITS routines to read and write FITS headers. + */ + +#include <xos.h> +#include "fitsy.h" + +#define MAX_COPY 1024 +static int ncopy_file=0; +static File copy_files[MAX_COPY]; + +static int GetWordType(fptr, tbuf, cflag) + char **fptr; + char *tbuf; + int *cflag; +{ + int alpha, digit, other, got; + char *f, *t; + + /* start out clean */ + *tbuf = '\0'; + + /* gather up characters until we have a delim */ + for(got=0, alpha=0, digit=0, other=0, f=*fptr, *tbuf='\0', t=tbuf; + (*f!='\0') && (*f!=',') && (*f!=']'); + got++){ + if( isdigit((unsigned int)*f) ){ + digit++; + *t++ = *f++; + } + else if( isalpha((unsigned int)*f) || (*f == '_') || (*f == '$') ){ + alpha++; + *t++ = *f++; + } + /* special case: extension or index ending with '+' means copy extension */ + else if( (*f=='+') && ((*(f+1)=='\0') || (*(f+1)==',') || (*(f+1)==']')) ){ + /* don't add '+' to output, but inc past it in input */ + f++; + /* we got the 'copy extension' flag */ + *cflag = 1; + } + else{ + /* - might be part of an extension */ + if( (*f=='-') && got && !other ) + alpha++; + else + other++; + *t++ = *f++; + } + } + /* null terminate working string */ + *t = '\0'; + + /* update pointer */ + *fptr = f; + + /* determine what sort of beast we have and return */ + if( got == 0 ) + return(0); + else if( other >0 ) + return(3); + else if( (digit>0) && (alpha==0) ) + return(2); + else + return(1); +} + + +/* + * + * ft_parsefilename -- break a string into name, extension, index, tail + * The possibilities are: + * + * name[extn], name[extn,index], name[index] + * name[extn,tail], name[extn,index,tail], name[index,tail] + * + * where: + * extn is composed of alphanumerics, index is numeric, tail is anything + * and commas are separators. + * + * returns 1 if 'copy flag' was set (+extn, extn+, +index, index+), else 0 + * + * + */ +int ft_parsefilename(filename, name, extn, nmaxlen, indx, tail, tmaxlen) + char *filename; + char *name; + char *extn; + int nmaxlen; + int *indx; + char *tail; + int tmaxlen; +{ + char *f, *t; + char *tbuf, *tbuf2; + int i, len; + int got; + int cflag; + + /* start out clean */ + *extn = '\0'; + *indx = -1; + *tail = '\0'; + cflag = 0; + + /* make sure we have something to work with */ + if( (filename == NULL) || (*filename == '\0') ) + return 0; + + /* handle pipe: specification specially */ + if( !strncasecmp(filename, "pipe:", 5) ){ + strncpy(name, filename, nmaxlen); + return 0; + } + + /* basic work buffers */ + tbuf = (char *)malloc(strlen(filename)+1); + tbuf2 = (char *)malloc(strlen(filename)+1); + + /* this will be our pointer into the filename buffer */ + f = filename; + + /* maxlen generally is 1 more than we can handle */ + nmaxlen--; + tmaxlen--; + + /* gather up the name */ + for(*tbuf='\0', t=tbuf; (*f!='\0') && (*f!='[') && (*f!=','); ) + *t++ = *f++; + /* null terminate working string */ + *t = '\0'; + /* copy max from the work buffer to the name buffer */ + strncpy(name, tbuf, nmaxlen); + name[nmaxlen] = '\0'; + /* check for done */ + if( *f == '\0' ) + goto cleanup; + /* or skip past '[' delim following the name */ + else + f++; + + /* get token and process type */ + switch(GetWordType(&f, tbuf, &cflag)){ + /* EOF */ + case 0: + break; + /* extn */ + case 1: + strcpy(extn, tbuf); + *tbuf = '\0'; + if( *f == ',' ){ + f++; + switch(GetWordType(&f, tbuf, &cflag)){ + case 2: + *indx = strtol(tbuf, NULL, 10); + *tbuf = '\0'; + if( *f == ',' ) + f++; + break; + default: + break; + } + } + break; + /* index */ + case 2: + *indx = strtol(tbuf, NULL, 10); + *tbuf = '\0'; + if( *f == ',' ) + f++; + break; + /* tail */ + case 3: + break; + } + + /* at this point, we are processing tail */ + strcpy(tbuf2, "["); + if( *tbuf != '\0' ) + strcat(tbuf2, tbuf); + if( *f != '\0' ) + strcat(tbuf2, f); + strncpy(tail, tbuf2, tmaxlen); + tail[tmaxlen] = '\0'; + /* get rid of any empty brackets */ + len = strlen(tail); + for(i=0; i<len; i++){ + if( (tail[i] == '[') && (i+2 < len) && (tail[i+1] == ']') ){ + strcpy(tbuf, &(tail[i+2])); + strcpy(&(tail[i]), tbuf); + } + } + /* but don't bother passing back completely null brackets */ + len = strlen(tail); + for(got=0, i=0; i<len; i++){ + if( (tail[i] != '[') && (tail[i] != ']') && (tail[i] != ' ') ){ + got = 1; + break; + } + } + if( !got ) *tail = '\0'; + + /* clean up */ +cleanup: + if( tbuf != NULL ) + free(tbuf); + if( tbuf2 != NULL ) + free(tbuf2); + return cflag; +} + +/* + * + * ft_cfile -- change the static copy_file handle + * This is used to set/unset the copy handle for when we open a fits file + * (There is no other good place to store this copy handle!) + * returns: old handle + * + */ +int ft_cfile(cfile) + File cfile; +{ + if( cfile ){ + if( ncopy_file >= MAX_COPY ) return -1; + copy_files[ncopy_file++] = cfile; + } + else{ + ncopy_file = 0; + } + return ncopy_file; +} + +/* Read a FITS header from the named file -- primitive of ft_fitsheadopen() + */ +File ft_fitsheadread(file, filename, header, mode, iline, ifd) + File file; + char *filename; /* FITS image file name. */ + FITSHead *header; + char *mode; + char iline[FT_CARDLEN]; + File *ifd; +{ + FITSHead prim = NULL; + FITSHead head = NULL; + char name[FT_FILENAME]; + char extn[FT_FILENAME]; + char tail[FT_FILENAME]; + char tbuf[FT_CARDLEN]; + char *e; + char *i; + char *tptr; + int indx = 0; + int len = FT_FILENAME; + int tlen; + int n; + int nc; + static int vlaerr=0; + + /* if the user called the wrong routine, fix it */ + if( !file ) return NULL; + + /* initialize return values */ + if( iline ) iline[0] = '\0'; + if( ifd ) *ifd = file; + + /* parse filename into extension, index, and tail */ + ft_parsefilename(filename, name, extn, len, &indx, tail, len); + + /* make sure this is a FITS file by looking at the first card */ + tptr = (iline ? iline : tbuf); + if( ( !ftGets(file, tptr, 10) ) || + (strncmp(tptr, "SIMPLE =", 9) && strncmp(tptr, "XTENSION=", 9)) ){ + /* pass back opened file so someone else can make an attempt */ + if( !ifd ) ftClose(file); + return NULL; + } + tlen = strlen(tptr); + if( ftRead(file, &tptr[tlen], FT_CARDLEN-tlen, 1) != 1 ){ + /* pass back opened file so someone else can make an attempt */ + if( !ifd ) ftClose(file); + return NULL; + } + + /* don't return anything anymore, both ifd and line were used already */ + if( iline ){ + memcpy(tbuf, iline, FT_CARDLEN); + iline[0] = '\0'; + } + if( ifd ) *ifd = NULL; + + /* read primary header */ + if ( (prim = ft_headread0(file, tbuf, FT_CARDLEN)) == NULL ){ + ftClose(file); + return NULL; + } + + /* Only look in the environment if the primary header + has no data and the user hasn't specified any thing + in the brackets. + */ + if ( ft_databytes(prim) == 0 && !*extn && indx == -1 ) { + if ( (e = (char *)getenv("FITS_EXTNAME")) ) { + strncpy(extn, e, len); + extn[len-1] = '\0'; + } + if ( (i = (char *)getenv("FITS_EXTNUM")) ) { + indx = atoi(i); + } + } + + head = prim; + if ( *extn ) { /* Extension and possible an index */ + do { + char *ext=NULL; + char *extcopy=(char *)strdup(extn); + for(ext=(char *)strtok(extcopy," :;,"); + ext!=NULL; + ext=(char *)strtok(NULL," :;,")){ + /* look for extname, then hduname, along with indx */ + if ( ((ft_name(head) && *ft_name(head) && + !strcasecmp(ext, ft_name(head))) || + (ft_hduname(head) && *ft_hduname(head) && + !strcasecmp(ext, ft_hduname(head)))) && + (indx == -1 || indx == ft_extn(head)) ) + break; + } + if( extcopy ) + free(extcopy); + /* if we matched an extension, we are done */ + if( ext ) + break; + + /* copy header, if necessary */ + if( ncopy_file ){ + for(nc=0; nc<ncopy_file; nc++) + ft_headwrite(copy_files[nc], head); + } + /* skip data, copying header if necessary */ + ft_dataskip(file, head, copy_files, ncopy_file); + + if ( head != prim ) ft_headfree(head, 1); + } while ( (head = ft_headread(file)) ); + + if ( !head ) { + ft_headfree(prim, 1); + ftClose(file); + return NULL; + } + } else if ( indx > 0 ) { /* Extension index, not == 0 */ + int i; + + /* copy header, if necessary */ + if( ncopy_file ){ + for(nc=0; nc<ncopy_file; nc++) + ft_headwrite(copy_files[nc], head); + } + ft_dataskip(file, prim, copy_files, ncopy_file); + + for ( i = 1; i <= indx; i++ ) { + if ( (head = ft_headread(file)) == NULL ) { + ft_headfree(prim, 1); + ftClose(file); + return NULL; + } + if( i != indx ){ + /* copy header, if necessary */ + if( ncopy_file ){ + for(nc=0; nc<ncopy_file; nc++) + ft_headwrite(copy_files[nc], head); + } + /* skip data, copying header if necessary */ + ft_dataskip(file, head, copy_files, ncopy_file); + ft_headfree(head, 1); + } + } + } + + if ( head != prim ){ + ft_primlink(prim, head); /* Link the primary to the header */ + /* this primary header only exists as part of head */ + prim->rfcount = 1; + } + + /* if this is a table and contains a variable length array, issue wanring */ + if( head && head->table && !vlaerr ){ + for ( n = 1; n <= head->table->tfields; n++ ) { + if ( head->table->col[n-1].vla ){ + fprintf(stderr, + "WARNING: The 'variable length array' is not part of the FITS Bintable standard. "); + fprintf(stderr, + "Funtools will pass it along, but will not process it.\n"); + vlaerr++; + break; + } + } + } + + if( header != NULL ){ + *header = head; + } + + return file; +} + +/* Read a FITS header from the named file. + */ +File ft_fitsheadopen(filename, header, tail, len, mode) + char *filename; /* FITS image file name. */ + FITSHead *header; + char *tail; + int len; + char *mode; +{ + return ft_fitsheadopenfd(filename, header, tail, len, mode, NULL, + NULL, NULL); +} + +/* Read a FITS header from the named file. + */ +File ft_fitsheadopenfd(filename, header, tail, len, mode, file, iline, ifd) + char *filename; /* FITS image file name. */ + FITSHead *header; + char *tail; + int len; + char *mode; + File file; + char iline[FT_CARDLEN]; + File *ifd; +{ + char *xmode; + char name[FT_FILENAME]; + char extn[FT_FILENAME]; + int indx = 0; + int cflag; + + /* initialize return values */ + if( iline ) iline[0] = '\0'; + if( ifd ) *ifd = NULL; + + /* parse filename into extension, index, and tail */ + cflag = ft_parsefilename(filename, name, extn, FT_FILENAME, &indx, + tail, len); + + /* set mode or use 'r' as default */ + if( mode ){ + xmode = mode; + } + else + xmode = "r"; + + /* see if 'CopyExtension' mode was explicitly set in the mode */ + if( strchr(xmode, 'C') ) + cflag = 1; + /* else see if it was set in the section and is permitted by the mode */ + else if( strchr(xmode, 'c') && cflag ) + cflag = 1; + /* else we do not copy */ + else + cflag = 0; + + if( !file ){ + if ( (file = ftOpen(name, xmode)) == NULL ) + return NULL; + } + + /* if the "copy extension" flag was set, we can exit here */ + if( cflag ){ + /* flag header was not created */ + if( header ) + *header = NULL; + return file; + } + + /* now read the file up to the specified extension */ + file = ft_fitsheadread(file, filename, header, xmode, iline, ifd); + + /* save filename */ + if( file && header && *header && *name ){ + if( (*header)->filename ) (void)Free((*header)->filename); + (*header)->filename = strdup(name); + } + + return file; +} |