diff options
Diffstat (limited to 'vendor/cfitsio/iraffits.c')
-rw-r--r-- | vendor/cfitsio/iraffits.c | 2073 |
1 files changed, 2073 insertions, 0 deletions
diff --git a/vendor/cfitsio/iraffits.c b/vendor/cfitsio/iraffits.c new file mode 100644 index 00000000..d8fc06b2 --- /dev/null +++ b/vendor/cfitsio/iraffits.c @@ -0,0 +1,2073 @@ +/*------------------------------------------------------------------------*/ +/* */ +/* These routines have been modified by William Pence for use by CFITSIO */ +/* The original files were provided by Doug Mink */ +/*------------------------------------------------------------------------*/ + +/* File imhfile.c + * August 6, 1998 + * By Doug Mink, based on Mike VanHilst's readiraf.c + + * Module: imhfile.c (IRAF .imh image file reading and writing) + * Purpose: Read and write IRAF image files (and translate headers) + * Subroutine: irafrhead (filename, lfhead, fitsheader, lihead) + * Read IRAF image header + * Subroutine: irafrimage (fitsheader) + * Read IRAF image pixels (call after irafrhead) + * Subroutine: same_path (pixname, hdrname) + * Put filename and header path together + * Subroutine: iraf2fits (hdrname, irafheader, nbiraf, nbfits) + * Convert IRAF image header to FITS image header + * Subroutine: irafgeti4 (irafheader, offset) + * Get 4-byte integer from arbitrary part of IRAF header + * Subroutine: irafgetc2 (irafheader, offset) + * Get character string from arbitrary part of IRAF v.1 header + * Subroutine: irafgetc (irafheader, offset) + * Get character string from arbitrary part of IRAF header + * Subroutine: iraf2str (irafstring, nchar) + * Convert 2-byte/char IRAF string to 1-byte/char string + * Subroutine: irafswap (bitpix,string,nbytes) + * Swap bytes in string in place, with FITS bits/pixel code + * Subroutine: irafswap2 (string,nbytes) + * Swap bytes in string in place + * Subroutine irafswap4 (string,nbytes) + * Reverse bytes of Integer*4 or Real*4 vector in place + * Subroutine irafswap8 (string,nbytes) + * Reverse bytes of Real*8 vector in place + + + * Copyright: 2000 Smithsonian Astrophysical Observatory + * You may do anything you like with this file except remove + * this copyright. The Smithsonian Astrophysical Observatory + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <stdio.h> /* define stderr, FD, and NULL */ +#include <stdlib.h> +#include <stddef.h> /* stddef.h is apparently needed to define size_t */ +#include <string.h> + +#define FILE_NOT_OPENED 104 + +/* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */ +#define SZ_IMPIXFILE 79 /* name of pixel storage file */ +#define SZ_IMHDRFILE 79 /* length of header storage file */ +#define SZ_IMTITLE 79 /* image title string */ +#define LEN_IMHDR 2052 /* length of std header */ + +/* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */ +#define SZ_IM2PIXFILE 255 /* name of pixel storage file */ +#define SZ_IM2HDRFILE 255 /* name of header storage file */ +#define SZ_IM2TITLE 383 /* image title string */ +#define LEN_IM2HDR 2046 /* length of std header */ + +/* Offsets into header in bytes for parameters in IRAF version 1 images */ +#define IM_HDRLEN 12 /* Length of header in 4-byte ints */ +#define IM_PIXTYPE 16 /* Datatype of the pixels */ +#define IM_NDIM 20 /* Number of dimensions */ +#define IM_LEN 24 /* Length (as stored) */ +#define IM_PHYSLEN 52 /* Physical length (as stored) */ +#define IM_PIXOFF 88 /* Offset of the pixels */ +#define IM_CTIME 108 /* Time of image creation */ +#define IM_MTIME 112 /* Time of last modification */ +#define IM_LIMTIME 116 /* Time of min,max computation */ +#define IM_MAX 120 /* Maximum pixel value */ +#define IM_MIN 124 /* Maximum pixel value */ +#define IM_PIXFILE 412 /* Name of pixel storage file */ +#define IM_HDRFILE 572 /* Name of header storage file */ +#define IM_TITLE 732 /* Image name string */ + +/* Offsets into header in bytes for parameters in IRAF version 2 images */ +#define IM2_HDRLEN 6 /* Length of header in 4-byte ints */ +#define IM2_PIXTYPE 10 /* Datatype of the pixels */ +#define IM2_SWAPPED 14 /* Pixels are byte swapped */ +#define IM2_NDIM 18 /* Number of dimensions */ +#define IM2_LEN 22 /* Length (as stored) */ +#define IM2_PHYSLEN 50 /* Physical length (as stored) */ +#define IM2_PIXOFF 86 /* Offset of the pixels */ +#define IM2_CTIME 106 /* Time of image creation */ +#define IM2_MTIME 110 /* Time of last modification */ +#define IM2_LIMTIME 114 /* Time of min,max computation */ +#define IM2_MAX 118 /* Maximum pixel value */ +#define IM2_MIN 122 /* Maximum pixel value */ +#define IM2_PIXFILE 126 /* Name of pixel storage file */ +#define IM2_HDRFILE 382 /* Name of header storage file */ +#define IM2_TITLE 638 /* Image name string */ + +/* Codes from iraf/unix/hlib/iraf.h */ +#define TY_CHAR 2 +#define TY_SHORT 3 +#define TY_INT 4 +#define TY_LONG 5 +#define TY_REAL 6 +#define TY_DOUBLE 7 +#define TY_COMPLEX 8 +#define TY_POINTER 9 +#define TY_STRUCT 10 +#define TY_USHORT 11 +#define TY_UBYTE 12 + +#define LEN_PIXHDR 1024 +#define MAXINT 2147483647 /* Biggest number that can fit in long */ + +static int isirafswapped(char *irafheader, int offset); +static int irafgeti4(char *irafheader, int offset); +static char *irafgetc2(char *irafheader, int offset, int nc); +static char *irafgetc(char *irafheader, int offset, int nc); +static char *iraf2str(char *irafstring, int nchar); +static char *irafrdhead(char *filename, int *lihead); +static int irafrdimage (char **buffptr, size_t *buffsize, + size_t *filesize, int *status); +static int iraftofits (char *hdrname, char *irafheader, int nbiraf, + char **buffptr, size_t *nbfits, size_t *fitssize, int *status); +static char *same_path(char *pixname, char *hdrname); + +static int swaphead=0; /* =1 to swap data bytes of IRAF header values */ +static int swapdata=0; /* =1 to swap bytes in IRAF data pixels */ + +static void irafswap(int bitpix, char *string, int nbytes); +static void irafswap2(char *string, int nbytes); +static void irafswap4(char *string, int nbytes); +static void irafswap8(char *string, int nbytes); +static int pix_version (char *irafheader); +static int irafncmp (char *irafheader, char *teststring, int nc); +static int machswap(void); +static int head_version (char *irafheader); +static int hgeti4(char* hstring, char* keyword, int* val); +static int hgets(char* hstring, char* keyword, int lstr, char* string); +static char* hgetc(char* hstring, char* keyword); +static char* ksearch(char* hstring, char* keyword); +static char *blsearch (char* hstring, char* keyword); +static char *strsrch (char* s1, char* s2); +static char *strnsrch ( char* s1,char* s2,int ls1); +static void hputi4(char* hstring,char* keyword, int ival); +static void hputs(char* hstring,char* keyword,char* cval); +static void hputcom(char* hstring,char* keyword,char* comment); +static void hputl(char* hstring,char* keyword,int lval); +static void hputc(char* hstring,char* keyword,char* cval); +static int getirafpixname (char *hdrname, char *irafheader, char *pixfilename, int *status); +int iraf2mem(char *filename, char **buffptr, size_t *buffsize, + size_t *filesize, int *status); + +void ffpmsg(const char *err_message); + +/*--------------------------------------------------------------------------*/ +int fits_delete_iraf_file(char *filename, /* name of input file */ + int *status) /* IO - error status */ + +/* + Delete the iraf .imh header file and the associated .pix data file +*/ +{ + char *irafheader; + int lenirafhead; + + char pixfilename[SZ_IM2PIXFILE+1]; + + /* read IRAF header into dynamically created char array (free it later!) */ + irafheader = irafrdhead(filename, &lenirafhead); + + if (!irafheader) + { + return(*status = FILE_NOT_OPENED); + } + + getirafpixname (filename, irafheader, pixfilename, status); + + /* don't need the IRAF header any more */ + free(irafheader); + + if (*status > 0) + return(*status); + + remove(filename); + remove(pixfilename); + + return(*status); +} + +/*--------------------------------------------------------------------------*/ +int iraf2mem(char *filename, /* name of input file */ + char **buffptr, /* O - memory pointer (initially NULL) */ + size_t *buffsize, /* O - size of mem buffer, in bytes */ + size_t *filesize, /* O - size of FITS file, in bytes */ + int *status) /* IO - error status */ + +/* + Driver routine that reads an IRAF image into memory, also converting + it into FITS format. +*/ +{ + char *irafheader; + int lenirafhead; + + *buffptr = NULL; + *buffsize = 0; + *filesize = 0; + + /* read IRAF header into dynamically created char array (free it later!) */ + irafheader = irafrdhead(filename, &lenirafhead); + + if (!irafheader) + { + return(*status = FILE_NOT_OPENED); + } + + /* convert IRAF header to FITS header in memory */ + iraftofits(filename, irafheader, lenirafhead, buffptr, buffsize, filesize, + status); + + /* don't need the IRAF header any more */ + free(irafheader); + + if (*status > 0) + return(*status); + + *filesize = (((*filesize - 1) / 2880 ) + 1 ) * 2880; /* multiple of 2880 */ + + /* append the image data onto the FITS header */ + irafrdimage(buffptr, buffsize, filesize, status); + + return(*status); +} + +/*--------------------------------------------------------------------------*/ +/* Subroutine: irafrdhead (was irafrhead in D. Mink's original code) + * Purpose: Open and read the iraf .imh file. + * Returns: NULL if failure, else pointer to IRAF .imh image header + * Notes: The imhdr format is defined in iraf/lib/imhdr.h, some of + * which defines or mimicked, above. + */ + +static char *irafrdhead ( + char *filename, /* Name of IRAF header file */ + int *lihead) /* Length of IRAF image header in bytes (returned) */ +{ + FILE *fd; + int nbr; + char *irafheader; + char errmsg[81]; + long nbhead; + int nihead; + + *lihead = 0; + + /* open the image header file */ + fd = fopen (filename, "rb"); + if (fd == NULL) { + ffpmsg("unable to open IRAF header file:"); + ffpmsg(filename); + return (NULL); + } + + /* Find size of image header file */ + if (fseek(fd, 0, 2) != 0) /* move to end of the file */ + { + ffpmsg("IRAFRHEAD: cannot seek in file:"); + ffpmsg(filename); + return(NULL); + } + + nbhead = ftell(fd); /* position = size of file */ + if (nbhead < 0) + { + ffpmsg("IRAFRHEAD: cannot get pos. in file:"); + ffpmsg(filename); + return(NULL); + } + + if (fseek(fd, 0, 0) != 0) /* move back to beginning */ + { + ffpmsg("IRAFRHEAD: cannot seek to beginning of file:"); + ffpmsg(filename); + return(NULL); + } + + /* allocate initial sized buffer */ + nihead = nbhead + 5000; + irafheader = (char *) calloc (1, nihead); + if (irafheader == NULL) { + sprintf(errmsg, "IRAFRHEAD Cannot allocate %d-byte header", + nihead); + ffpmsg(errmsg); + ffpmsg(filename); + return (NULL); + } + *lihead = nihead; + + /* Read IRAF header */ + nbr = fread (irafheader, 1, nbhead, fd); + fclose (fd); + + /* Reject if header less than minimum length */ + if (nbr < LEN_PIXHDR) { + sprintf(errmsg, "IRAFRHEAD header file: %d / %d bytes read.", + nbr,LEN_PIXHDR); + ffpmsg(errmsg); + ffpmsg(filename); + free (irafheader); + return (NULL); + } + + return (irafheader); +} +/*--------------------------------------------------------------------------*/ +static int irafrdimage ( + char **buffptr, /* FITS image header (filled) */ + size_t *buffsize, /* allocated size of the buffer */ + size_t *filesize, /* actual size of the FITS file */ + int *status) +{ + FILE *fd; + char *bang; + int nax = 1, naxis1 = 1, naxis2 = 1, naxis3 = 1, naxis4 = 1, npaxis1 = 1, npaxis2; + int bitpix, bytepix, i; + char *fitsheader, *image; + int nbr, nbimage, nbaxis, nbl, nbdiff; + char *pixheader; + char *linebuff; + int imhver, lpixhead = 0; + char pixname[SZ_IM2PIXFILE+1]; + char errmsg[81]; + size_t newfilesize; + + fitsheader = *buffptr; /* pointer to start of header */ + + /* Convert pixel file name to character string */ + hgets (fitsheader, "PIXFILE", SZ_IM2PIXFILE, pixname); + hgeti4 (fitsheader, "PIXOFF", &lpixhead); + + /* Open pixel file, ignoring machine name if present */ + if ((bang = strchr (pixname, '!')) != NULL ) + fd = fopen (bang + 1, "rb"); + else + fd = fopen (pixname, "rb"); + + /* Print error message and exit if pixel file is not found */ + if (!fd) { + ffpmsg("IRAFRIMAGE: Cannot open IRAF pixel file:"); + ffpmsg(pixname); + return (*status = FILE_NOT_OPENED); + } + + /* Read pixel header */ + pixheader = (char *) calloc (lpixhead, 1); + if (pixheader == NULL) { + ffpmsg("IRAFRIMAGE: Cannot alloc memory for pixel header"); + ffpmsg(pixname); + fclose (fd); + return (*status = FILE_NOT_OPENED); + } + nbr = fread (pixheader, 1, lpixhead, fd); + + /* Check size of pixel header */ + if (nbr < lpixhead) { + sprintf(errmsg, "IRAF pixel file: %d / %d bytes read.", + nbr,LEN_PIXHDR); + ffpmsg(errmsg); + free (pixheader); + fclose (fd); + return (*status = FILE_NOT_OPENED); + } + + /* check pixel header magic word */ + imhver = pix_version (pixheader); + if (imhver < 1) { + ffpmsg("File not valid IRAF pixel file:"); + ffpmsg(pixname); + free (pixheader); + fclose (fd); + return (*status = FILE_NOT_OPENED); + } + free (pixheader); + + /* Find number of bytes to read */ + hgeti4 (fitsheader,"NAXIS",&nax); + hgeti4 (fitsheader,"NAXIS1",&naxis1); + hgeti4 (fitsheader,"NPAXIS1",&npaxis1); + if (nax > 1) { + hgeti4 (fitsheader,"NAXIS2",&naxis2); + hgeti4 (fitsheader,"NPAXIS2",&npaxis2); + } + if (nax > 2) + hgeti4 (fitsheader,"NAXIS3",&naxis3); + if (nax > 3) + hgeti4 (fitsheader,"NAXIS4",&naxis4); + + hgeti4 (fitsheader,"BITPIX",&bitpix); + if (bitpix < 0) + bytepix = -bitpix / 8; + else + bytepix = bitpix / 8; + + nbimage = naxis1 * naxis2 * naxis3 * naxis4 * bytepix; + + newfilesize = *filesize + nbimage; /* header + data */ + newfilesize = (((newfilesize - 1) / 2880 ) + 1 ) * 2880; + + if (newfilesize > *buffsize) /* need to allocate more memory? */ + { + fitsheader = (char *) realloc (*buffptr, newfilesize); + if (fitsheader == NULL) { + sprintf(errmsg, "IRAFRIMAGE Cannot allocate %d-byte image buffer", + (int) (*filesize)); + ffpmsg(errmsg); + ffpmsg(pixname); + fclose (fd); + return (*status = FILE_NOT_OPENED); + } + } + + *buffptr = fitsheader; + *buffsize = newfilesize; + + image = fitsheader + *filesize; + *filesize = newfilesize; + + /* Read IRAF image all at once if physical and image dimensions are the same */ + if (npaxis1 == naxis1) + nbr = fread (image, 1, nbimage, fd); + + /* Read IRAF image one line at a time if physical and image dimensions differ */ + else { + nbdiff = (npaxis1 - naxis1) * bytepix; + nbaxis = naxis1 * bytepix; + linebuff = image; + nbr = 0; + if (naxis2 == 1 && naxis3 > 1) + naxis2 = naxis3; + for (i = 0; i < naxis2; i++) { + nbl = fread (linebuff, 1, nbaxis, fd); + nbr = nbr + nbl; + fseek (fd, nbdiff, 1); + linebuff = linebuff + nbaxis; + } + } + fclose (fd); + + /* Check size of image */ + if (nbr < nbimage) { + sprintf(errmsg, "IRAF pixel file: %d / %d bytes read.", + nbr,nbimage); + ffpmsg(errmsg); + ffpmsg(pixname); + return (*status = FILE_NOT_OPENED); + } + + /* Byte-reverse image, if necessary */ + if (swapdata) + irafswap (bitpix, image, nbimage); + + return (*status); +} +/*--------------------------------------------------------------------------*/ +/* Return IRAF image format version number from magic word in IRAF header*/ + +static int head_version ( + char *irafheader) /* IRAF image header from file */ + +{ + + /* Check header file magic word */ + if (irafncmp (irafheader, "imhdr", 5) != 0 ) { + if (strncmp (irafheader, "imhv2", 5) != 0) + return (0); + else + return (2); + } + else + return (1); +} + +/*--------------------------------------------------------------------------*/ +/* Return IRAF image format version number from magic word in IRAF pixel file */ + +static int pix_version ( + char *irafheader) /* IRAF image header from file */ +{ + + /* Check pixel file header magic word */ + if (irafncmp (irafheader, "impix", 5) != 0) { + if (strncmp (irafheader, "impv2", 5) != 0) + return (0); + else + return (2); + } + else + return (1); +} + +/*--------------------------------------------------------------------------*/ +/* Verify that file is valid IRAF imhdr or impix by checking first 5 chars + * Returns: 0 on success, 1 on failure */ + +static int irafncmp ( + +char *irafheader, /* IRAF image header from file */ +char *teststring, /* C character string to compare */ +int nc) /* Number of characters to compate */ + +{ + char *line; + + if ((line = iraf2str (irafheader, nc)) == NULL) + return (1); + if (strncmp (line, teststring, nc) == 0) { + free (line); + return (0); + } + else { + free (line); + return (1); + } +} +/*--------------------------------------------------------------------------*/ + +/* Convert IRAF image header to FITS image header, returning FITS header */ + +static int iraftofits ( + char *hdrname, /* IRAF header file name (may be path) */ + char *irafheader, /* IRAF image header */ + int nbiraf, /* Number of bytes in IRAF header */ + char **buffptr, /* pointer to the FITS header */ + size_t *nbfits, /* allocated size of the FITS header buffer */ + size_t *fitssize, /* Number of bytes in FITS header (returned) */ + /* = number of bytes to the end of the END keyword */ + int *status) +{ + char *objname; /* object name from FITS file */ + int lstr, i, j, k, ib, nax, nbits; + char *pixname, *newpixname, *bang, *chead; + char *fitsheader; + int nblock, nlines; + char *fhead, *fhead1, *fp, endline[81]; + char irafchar; + char fitsline[81]; + int pixtype; + int imhver, n, imu, pixoff, impixoff; +/* int immax, immin, imtime; */ + int imndim, imlen, imphyslen, impixtype; + char errmsg[81]; + + /* Set up last line of FITS header */ + (void)strncpy (endline,"END", 3); + for (i = 3; i < 80; i++) + endline[i] = ' '; + endline[80] = 0; + + /* Check header magic word */ + imhver = head_version (irafheader); + if (imhver < 1) { + ffpmsg("File not valid IRAF image header"); + ffpmsg(hdrname); + return(*status = FILE_NOT_OPENED); + } + if (imhver == 2) { + nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81); + imndim = IM2_NDIM; + imlen = IM2_LEN; + imphyslen = IM2_PHYSLEN; + impixtype = IM2_PIXTYPE; + impixoff = IM2_PIXOFF; +/* imtime = IM2_MTIME; */ +/* immax = IM2_MAX; */ +/* immin = IM2_MIN; */ + } + else { + nlines = 24 + ((nbiraf - LEN_IMHDR) / 162); + imndim = IM_NDIM; + imlen = IM_LEN; + imphyslen = IM_PHYSLEN; + impixtype = IM_PIXTYPE; + impixoff = IM_PIXOFF; +/* imtime = IM_MTIME; */ +/* immax = IM_MAX; */ +/* immin = IM_MIN; */ + } + + /* Initialize FITS header */ + nblock = (nlines * 80) / 2880; + *nbfits = (nblock + 5) * 2880 + 4; + fitsheader = (char *) calloc (*nbfits, 1); + if (fitsheader == NULL) { + sprintf(errmsg, "IRAF2FITS Cannot allocate %d-byte FITS header", + (int) (*nbfits)); + ffpmsg(hdrname); + return (*status = FILE_NOT_OPENED); + } + + fhead = fitsheader; + *buffptr = fitsheader; + (void)strncpy (fitsheader, endline, 80); + hputl (fitsheader, "SIMPLE", 1); + fhead = fhead + 80; + + /* check if the IRAF file is in big endian (sun) format (= 0) or not. */ + /* This is done by checking the 4 byte integer in the header that */ + /* represents the iraf pixel type. This 4-byte word is guaranteed to */ + /* have the least sig byte != 0 and the most sig byte = 0, so if the */ + /* first byte of the word != 0, then the file in little endian format */ + /* like on an Alpha machine. */ + + swaphead = isirafswapped(irafheader, impixtype); + if (imhver == 1) + swapdata = swaphead; /* vers 1 data has same swapness as header */ + else + swapdata = irafgeti4 (irafheader, IM2_SWAPPED); + + /* Set pixel size in FITS header */ + pixtype = irafgeti4 (irafheader, impixtype); + switch (pixtype) { + case TY_CHAR: + nbits = 8; + break; + case TY_UBYTE: + nbits = 8; + break; + case TY_SHORT: + nbits = 16; + break; + case TY_USHORT: + nbits = -16; + break; + case TY_INT: + case TY_LONG: + nbits = 32; + break; + case TY_REAL: + nbits = -32; + break; + case TY_DOUBLE: + nbits = -64; + break; + default: + sprintf(errmsg,"Unsupported IRAF data type: %d", pixtype); + ffpmsg(errmsg); + ffpmsg(hdrname); + return (*status = FILE_NOT_OPENED); + } + hputi4 (fitsheader,"BITPIX",nbits); + hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type"); + fhead = fhead + 80; + + /* Set image dimensions in FITS header */ + nax = irafgeti4 (irafheader, imndim); + hputi4 (fitsheader,"NAXIS",nax); + hputcom (fitsheader,"NAXIS", "IRAF .imh naxis"); + fhead = fhead + 80; + + n = irafgeti4 (irafheader, imlen); + hputi4 (fitsheader, "NAXIS1", n); + hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]"); + fhead = fhead + 80; + + if (nax > 1) { + n = irafgeti4 (irafheader, imlen+4); + hputi4 (fitsheader, "NAXIS2", n); + hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]"); + fhead = fhead + 80; + } + if (nax > 2) { + n = irafgeti4 (irafheader, imlen+8); + hputi4 (fitsheader, "NAXIS3", n); + hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]"); + fhead = fhead + 80; + } + if (nax > 3) { + n = irafgeti4 (irafheader, imlen+12); + hputi4 (fitsheader, "NAXIS4", n); + hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]"); + fhead = fhead + 80; + } + + /* Set object name in FITS header */ + if (imhver == 2) + objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE); + else + objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE); + if ((lstr = strlen (objname)) < 8) { + for (i = lstr; i < 8; i++) + objname[i] = ' '; + objname[8] = 0; + } + hputs (fitsheader,"OBJECT",objname); + hputcom (fitsheader,"OBJECT", "IRAF .imh title"); + free (objname); + fhead = fhead + 80; + + /* Save physical axis lengths so image file can be read */ + n = irafgeti4 (irafheader, imphyslen); + hputi4 (fitsheader, "NPAXIS1", n); + hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]"); + fhead = fhead + 80; + if (nax > 1) { + n = irafgeti4 (irafheader, imphyslen+4); + hputi4 (fitsheader, "NPAXIS2", n); + hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]"); + fhead = fhead + 80; + } + if (nax > 2) { + n = irafgeti4 (irafheader, imphyslen+8); + hputi4 (fitsheader, "NPAXIS3", n); + hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]"); + fhead = fhead + 80; + } + if (nax > 3) { + n = irafgeti4 (irafheader, imphyslen+12); + hputi4 (fitsheader, "NPAXIS4", n); + hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]"); + fhead = fhead + 80; + } + + /* Save image header filename in header */ + hputs (fitsheader,"IMHFILE",hdrname); + hputcom (fitsheader,"IMHFILE", "IRAF header file name"); + fhead = fhead + 80; + + /* Save image pixel file pathname in header */ + if (imhver == 2) + pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); + else + pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); + if (strncmp(pixname, "HDR", 3) == 0 ) { + newpixname = same_path (pixname, hdrname); + if (newpixname) { + free (pixname); + pixname = newpixname; + } + } + if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { + newpixname = same_path (pixname, hdrname); + if (newpixname) { + free (pixname); + pixname = newpixname; + } + } + + if ((bang = strchr (pixname, '!')) != NULL ) + hputs (fitsheader,"PIXFILE",bang+1); + else + hputs (fitsheader,"PIXFILE",pixname); + free (pixname); + hputcom (fitsheader,"PIXFILE", "IRAF .pix pixel file"); + fhead = fhead + 80; + + /* Save image offset from star of pixel file */ + pixoff = irafgeti4 (irafheader, impixoff); + pixoff = (pixoff - 1) * 2; + hputi4 (fitsheader, "PIXOFF", pixoff); + hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)"); + fhead = fhead + 80; + + /* Save IRAF file format version in header */ + hputi4 (fitsheader,"IMHVER",imhver); + hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)"); + fhead = fhead + 80; + + /* Save flag as to whether to swap IRAF data for this file and machine */ + if (swapdata) + hputl (fitsheader, "PIXSWAP", 1); + else + hputl (fitsheader, "PIXSWAP", 0); + hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T"); + fhead = fhead + 80; + + /* Add user portion of IRAF header to FITS header */ + fitsline[80] = 0; + if (imhver == 2) { + imu = LEN_IM2HDR; + chead = irafheader; + j = 0; + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + for (i = imu; i < nbiraf; i++) { + irafchar = chead[i]; + if (irafchar == 0) + break; + else if (irafchar == 10) { + (void)strncpy (fhead, fitsline, 80); + /* fprintf (stderr,"%80s\n",fitsline); */ + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + fhead = fhead + 80; + } + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + j = 0; + } + else { + if (j > 80) { + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + (void)strncpy (fhead, fitsline, 80); + /* fprintf (stderr,"%80s\n",fitsline); */ + j = 9; + fhead = fhead + 80; + } + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + } + if (irafchar > 32 && irafchar < 127) + fitsline[j] = irafchar; + j++; + } + } + } + else { + imu = LEN_IMHDR; + chead = irafheader; + if (swaphead == 1) + ib = 0; + else + ib = 1; + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + j = 0; + for (i = imu; i < nbiraf; i=i+2) { + irafchar = chead[i+ib]; + if (irafchar == 0) + break; + else if (irafchar == 10) { + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + (void)strncpy (fhead, fitsline, 80); + fhead = fhead + 80; + } + /* fprintf (stderr,"%80s\n",fitsline); */ + j = 0; + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + } + else { + if (j > 80) { + if (strncmp (fitsline, "OBJECT ", 7) != 0) { + (void)strncpy (fhead, fitsline, 80); + j = 9; + fhead = fhead + 80; + } + /* fprintf (stderr,"%80s\n",fitsline); */ + for (k = 0; k < 80; k++) + fitsline[k] = ' '; + } + if (irafchar > 32 && irafchar < 127) + fitsline[j] = irafchar; + j++; + } + } + } + + /* Add END to last line */ + (void)strncpy (fhead, endline, 80); + + /* Find end of last 2880-byte block of header */ + fhead = ksearch (fitsheader, "END") + 80; + nblock = *nbfits / 2880; + fhead1 = fitsheader + (nblock * 2880); + *fitssize = fhead - fitsheader; /* no. of bytes to end of END keyword */ + + /* Pad rest of header with spaces */ + strncpy (endline," ",3); + for (fp = fhead; fp < fhead1; fp = fp + 80) { + (void)strncpy (fp, endline,80); + } + + return (*status); +} +/*--------------------------------------------------------------------------*/ + +/* get the IRAF pixel file name */ + +static int getirafpixname ( + char *hdrname, /* IRAF header file name (may be path) */ + char *irafheader, /* IRAF image header */ + char *pixfilename, /* IRAF pixel file name */ + int *status) +{ + int imhver; + char *pixname, *newpixname, *bang; + + /* Check header magic word */ + imhver = head_version (irafheader); + if (imhver < 1) { + ffpmsg("File not valid IRAF image header"); + ffpmsg(hdrname); + return(*status = FILE_NOT_OPENED); + } + + /* get image pixel file pathname in header */ + if (imhver == 2) + pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); + else + pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); + + if (strncmp(pixname, "HDR", 3) == 0 ) { + newpixname = same_path (pixname, hdrname); + if (newpixname) { + free (pixname); + pixname = newpixname; + } + } + + if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { + newpixname = same_path (pixname, hdrname); + if (newpixname) { + free (pixname); + pixname = newpixname; + } + } + + if ((bang = strchr (pixname, '!')) != NULL ) + strcpy(pixfilename,bang+1); + else + strcpy(pixfilename,pixname); + + free (pixname); + + return (*status); +} + +/*--------------------------------------------------------------------------*/ +/* Put filename and header path together */ + +static char *same_path ( + +char *pixname, /* IRAF pixel file pathname */ +char *hdrname) /* IRAF image header file pathname */ + +{ + int len; + char *newpixname; + +/* WDP - 10/16/2007 - increased allocation to avoid possible overflow */ +/* newpixname = (char *) calloc (SZ_IM2PIXFILE, sizeof (char)); */ + + newpixname = (char *) calloc (2*SZ_IM2PIXFILE+1, sizeof (char)); + if (newpixname == NULL) { + ffpmsg("iraffits same_path: Cannot alloc memory for newpixname"); + return (NULL); + } + + /* Pixel file is in same directory as header */ + if (strncmp(pixname, "HDR$", 4) == 0 ) { + (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); + + /* find the end of the pathname */ + len = strlen (newpixname); +#ifndef VMS + while( (len > 0) && (newpixname[len-1] != '/') ) +#else + while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) +#endif + len--; + + /* add name */ + newpixname[len] = '\0'; + (void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE); + } + + /* Bare pixel file with no path is assumed to be same as HDR$filename */ + else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { + (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); + + /* find the end of the pathname */ + len = strlen (newpixname); +#ifndef VMS + while( (len > 0) && (newpixname[len-1] != '/') ) +#else + while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) +#endif + len--; + + /* add name */ + newpixname[len] = '\0'; + (void)strncat (newpixname, pixname, SZ_IM2PIXFILE); + } + + /* Pixel file has same name as header file, but with .pix extension */ + else if (strncmp (pixname, "HDR", 3) == 0) { + + /* load entire header name string into name buffer */ + (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); + len = strlen (newpixname); + newpixname[len-3] = 'p'; + newpixname[len-2] = 'i'; + newpixname[len-1] = 'x'; + } + + return (newpixname); +} + +/*--------------------------------------------------------------------------*/ +static int isirafswapped ( + +char *irafheader, /* IRAF image header */ +int offset) /* Number of bytes to skip before number */ + + /* check if the IRAF file is in big endian (sun) format (= 0) or not */ + /* This is done by checking the 4 byte integer in the header that */ + /* represents the iraf pixel type. This 4-byte word is guaranteed to */ + /* have the least sig byte != 0 and the most sig byte = 0, so if the */ + /* first byte of the word != 0, then the file in little endian format */ + /* like on an Alpha machine. */ + +{ + int swapped; + + if (irafheader[offset] != 0) + swapped = 1; + else + swapped = 0; + + return (swapped); +} +/*--------------------------------------------------------------------------*/ +static int irafgeti4 ( + +char *irafheader, /* IRAF image header */ +int offset) /* Number of bytes to skip before number */ + +{ + char *ctemp, *cheader; + int temp; + + cheader = irafheader; + ctemp = (char *) &temp; + + if (machswap() != swaphead) { + ctemp[3] = cheader[offset]; + ctemp[2] = cheader[offset+1]; + ctemp[1] = cheader[offset+2]; + ctemp[0] = cheader[offset+3]; + } + else { + ctemp[0] = cheader[offset]; + ctemp[1] = cheader[offset+1]; + ctemp[2] = cheader[offset+2]; + ctemp[3] = cheader[offset+3]; + } + return (temp); +} + +/*--------------------------------------------------------------------------*/ +/* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */ + +static char *irafgetc2 ( + +char *irafheader, /* IRAF image header */ +int offset, /* Number of bytes to skip before string */ +int nc) /* Maximum number of characters in string */ + +{ + char *irafstring, *string; + + irafstring = irafgetc (irafheader, offset, 2*(nc+1)); + string = iraf2str (irafstring, nc); + free (irafstring); + + return (string); +} + +/*--------------------------------------------------------------------------*/ +/* IRAFGETC -- Get character string from arbitrary part of IRAF header */ + +static char *irafgetc ( + +char *irafheader, /* IRAF image header */ +int offset, /* Number of bytes to skip before string */ +int nc) /* Maximum number of characters in string */ + +{ + char *ctemp, *cheader; + int i; + + cheader = irafheader; + ctemp = (char *) calloc (nc+1, 1); + if (ctemp == NULL) { + ffpmsg("IRAFGETC Cannot allocate memory for string variable"); + return (NULL); + } + for (i = 0; i < nc; i++) { + ctemp[i] = cheader[offset+i]; + if (ctemp[i] > 0 && ctemp[i] < 32) + ctemp[i] = ' '; + } + + return (ctemp); +} + +/*--------------------------------------------------------------------------*/ +/* Convert IRAF 2-byte/char string to 1-byte/char string */ + +static char *iraf2str ( + +char *irafstring, /* IRAF 2-byte/character string */ +int nchar) /* Number of characters in string */ +{ + char *string; + int i, j; + + string = (char *) calloc (nchar+1, 1); + if (string == NULL) { + ffpmsg("IRAF2STR Cannot allocate memory for string variable"); + return (NULL); + } + + /* the chars are in bytes 1, 3, 5, ... if bigendian format (SUN) */ + /* else in bytes 0, 2, 4, ... if little endian format (Alpha) */ + + if (irafstring[0] != 0) + j = 0; + else + j = 1; + + /* Convert appropriate byte of input to output character */ + for (i = 0; i < nchar; i++) { + string[i] = irafstring[j]; + j = j + 2; + } + + return (string); +} + +/*--------------------------------------------------------------------------*/ +/* IRAFSWAP -- Reverse bytes of any type of vector in place */ + +static void irafswap ( + +int bitpix, /* Number of bits per pixel */ + /* 16 = short, -16 = unsigned short, 32 = int */ + /* -32 = float, -64 = double */ +char *string, /* Address of starting point of bytes to swap */ +int nbytes) /* Number of bytes to swap */ + +{ + switch (bitpix) { + + case 16: + if (nbytes < 2) return; + irafswap2 (string,nbytes); + break; + + case 32: + if (nbytes < 4) return; + irafswap4 (string,nbytes); + break; + + case -16: + if (nbytes < 2) return; + irafswap2 (string,nbytes); + break; + + case -32: + if (nbytes < 4) return; + irafswap4 (string,nbytes); + break; + + case -64: + if (nbytes < 8) return; + irafswap8 (string,nbytes); + break; + + } + return; +} + +/*--------------------------------------------------------------------------*/ +/* IRAFSWAP2 -- Swap bytes in string in place */ + +static void irafswap2 ( + +char *string, /* Address of starting point of bytes to swap */ +int nbytes) /* Number of bytes to swap */ + +{ + char *sbyte, temp, *slast; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp = sbyte[0]; + sbyte[0] = sbyte[1]; + sbyte[1] = temp; + sbyte= sbyte + 2; + } + return; +} + +/*--------------------------------------------------------------------------*/ +/* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */ + +static void irafswap4 ( + +char *string, /* Address of Integer*4 or Real*4 vector */ +int nbytes) /* Number of bytes to reverse */ + +{ + char *sbyte, *slast; + char temp0, temp1, temp2, temp3; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp3 = sbyte[0]; + temp2 = sbyte[1]; + temp1 = sbyte[2]; + temp0 = sbyte[3]; + sbyte[0] = temp0; + sbyte[1] = temp1; + sbyte[2] = temp2; + sbyte[3] = temp3; + sbyte = sbyte + 4; + } + + return; +} + +/*--------------------------------------------------------------------------*/ +/* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */ + +static void irafswap8 ( + +char *string, /* Address of Real*8 vector */ +int nbytes) /* Number of bytes to reverse */ + +{ + char *sbyte, *slast; + char temp[8]; + + slast = string + nbytes; + sbyte = string; + while (sbyte < slast) { + temp[7] = sbyte[0]; + temp[6] = sbyte[1]; + temp[5] = sbyte[2]; + temp[4] = sbyte[3]; + temp[3] = sbyte[4]; + temp[2] = sbyte[5]; + temp[1] = sbyte[6]; + temp[0] = sbyte[7]; + sbyte[0] = temp[0]; + sbyte[1] = temp[1]; + sbyte[2] = temp[2]; + sbyte[3] = temp[3]; + sbyte[4] = temp[4]; + sbyte[5] = temp[5]; + sbyte[6] = temp[6]; + sbyte[7] = temp[7]; + sbyte = sbyte + 8; + } + return; +} + +/*--------------------------------------------------------------------------*/ +static int +machswap (void) + +{ + char *ctest; + int itest; + + itest = 1; + ctest = (char *)&itest; + if (*ctest) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------*/ +/* the following routines were originally in hget.c */ +/*--------------------------------------------------------------------------*/ + + +static int lhead0 = 0; + +/*--------------------------------------------------------------------------*/ + +/* Extract long value for variable from FITS header string */ + +static int +hgeti4 (hstring,keyword,ival) + +char *hstring; /* character string containing FITS header information + in the format <keyword>= <value> {/ <comment>} */ +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; +char val[30]; + +/* Get value and comment from header string */ + value = hgetc (hstring,keyword); + +/* Translate value from ASCII to binary */ + if (value != NULL) { + minint = -MAXINT - 1; + strcpy (val, value); + dval = atof (val); + if (dval+0.001 > MAXINT) + *ival = MAXINT; + 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 string value for variable from FITS header string */ + +static int +hgets (hstring, keyword, lstr, str) + +char *hstring; /* character string containing FITS header information + in the format <keyword>= <value> {/ <comment>} */ +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 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 character value for variable from FITS header string */ + +static char * +hgetc (hstring,keyword0) + +char *hstring; /* character string containing FITS header information + in the format <keyword>= <value> {/ <comment>} */ +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 keyword[81]; /* large for ESO hierarchical keywords */ + char line[100]; + char *vpos, *cpar = NULL; + char *q1, *q2 = NULL, *v1, *v2, *c1, *brack1, *brack2; + int ipar, i; + + squot[0] = 39; + squot[1] = 0; + dquot[0] = 34; + dquot[1] = 0; + lbracket[0] = 91; + lbracket[1] = 0; + comma[0] = 44; + comma[1] = 0; + rbracket[0] = 93; + rbracket[1] = 0; + slash[0] = 47; + slash[1] = 0; + +/* 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); + else if (c1 == NULL) + q2 = strsrch (q1+1,squot); + else + q1 = NULL; + } + else { + q1 = strsrch (line,dquot); + if (q1 != NULL) { + if (c1 != NULL && q1 < c1) + q2 = strsrch (q1+1,dquot); + else if (c1 == NULL) + q2 = strsrch (q1+1,dquot); + else + q1 = NULL; + } + else { + q1 = NULL; + q2 = line + 10; + } + } + +/* Extract value and remove excess spaces */ + if (q1 != NULL) { + v1 = q1 + 1; + v2 = q2; + c1 = strsrch (q2,"/"); + } + else { + v1 = strsrch (line,"=") + 1; + c1 = strsrch (line,"/"); + if (c1 != NULL) + v2 = c1; + else + v2 = line + 79; + } + +/* Ignore leading spaces */ + while (*v1 == ' ' && v1 < v2) { + v1++; + } + +/* Drop trailing spaces */ + *v2 = '\0'; + v2--; + while (*v2 == ' ' && v2 > v1) { + *v2 = '\0'; + v2--; + } + + 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'; + ipar = atoi (brack1); + if (ipar > 0) { + cwhite[0] = ' '; + cwhite[1] = '\0'; + for (i = 1; i <= ipar; i++) { + cpar = strtok (v1,cwhite); + v1 = NULL; + } + if (cpar != NULL) { + strcpy (cval,cpar); + } + else + value = NULL; + } + } + + return (value); +} + + +/*-------------------------------------------------------------------*/ +/* Find beginning of fillable blank line before FITS header keyword line */ + +static 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 */ + +char *hstring; /* character string containing fits-style header + information in the format <keyword>= <value> {/ <comment>} + 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. */ +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. */ +{ + char *loc, *headnext, *headlast, *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 < 57600 && hstring[lhstr] != 0) + lhstr++; + } + headlast = hstring + lhstr; + headnext = hstring; + pval = NULL; + while (headnext < headlast) { + nleft = headlast - headnext; + loc = strnsrch (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 if keyword is found at start of FITS header string */ + if (pval == NULL) + return (pval); + + /* Return NULL if found the first keyword in the header */ + if (pval == hstring) + return (NULL); + + /* Find last nonblank line before requested keyword */ + bval = pval - 80; + while (!strncmp (bval," ",8)) + bval = bval - 80; + bval = bval + 80; + + /* Return pointer to calling program if blank lines found */ + if (bval < pval) + return (bval); + else + return (NULL); +} + + +/*-------------------------------------------------------------------*/ +/* Find FITS header line containing specified keyword */ + +static char *ksearch (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 */ + +char *hstring; /* character string containing fits-style header + information in the format <keyword>= <value> {/ <comment>} + 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. */ +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. */ +{ + char *loc, *headnext, *headlast, *pval, *lc, *line; + int icol, nextchar, lkey, nleft, lhstr; + + pval = 0; + +/* Search header string for variable name */ + if (lhead0) + lhstr = lhead0; + else { + lhstr = 0; + while (lhstr < 57600 && hstring[lhstr] != 0) + lhstr++; + } + headlast = hstring + lhstr; + headnext = hstring; + pval = NULL; + while (headnext < headlast) { + nleft = headlast - headnext; + loc = strnsrch (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); + +} + +/*-------------------------------------------------------------------*/ +/* Find string s2 within null-terminated string s1 */ + +static char * +strsrch (s1, s2) + +char *s1; /* String to search */ +char *s2; /* String to look for */ + +{ + int ls1; + ls1 = strlen (s1); + return (strnsrch (s1, s2, ls1)); +} + +/*-------------------------------------------------------------------*/ +/* Find string s2 within string s1 */ + +static char * +strnsrch (s1, s2, ls1) + +char *s1; /* String to search */ +char *s2; /* String to look for */ +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 (s1); + + /* Only a zero-length string can be found in a zero-length string */ + if (ls1 ==0) + return (NULL); + + cfirst = s2[0]; + clast = s2[ls2-1]; + s1e = s1 + ls1 - ls2 + 1; + s = 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); +} + +/*-------------------------------------------------------------------*/ +/* the following routines were originally in hget.c */ +/*-------------------------------------------------------------------*/ +/* HPUTI4 - Set int keyword = ival in FITS header string */ + +static void +hputi4 (hstring,keyword,ival) + + char *hstring; /* character string containing FITS-style header + information in the format + <keyword>= <value> {/ <comment>} + each entry is padded with spaces to 80 characters */ + + char *keyword; /* character string containing the name of the variable + to be returned. hput searches for a line beginning + with this string, and if there isn't one, creates one. + The first 8 characters of keyword must be unique. */ + int ival; /* int number */ +{ + char value[30]; + + /* Translate value from binary to ASCII */ + sprintf (value,"%d",ival); + + /* Put value into header string */ + hputc (hstring,keyword,value); + + /* Return to calling program */ + return; +} + +/*-------------------------------------------------------------------*/ + +/* HPUTL - Set keyword = F if lval=0, else T, in FITS header string */ + +static void +hputl (hstring, keyword,lval) + +char *hstring; /* FITS header */ +char *keyword; /* Keyword name */ +int lval; /* logical variable (0=false, else true) */ +{ + char value[8]; + + /* Translate value from binary to ASCII */ + if (lval) + strcpy (value, "T"); + else + strcpy (value, "F"); + + /* Put value into header string */ + hputc (hstring,keyword,value); + + /* Return to calling program */ + return; +} + +/*-------------------------------------------------------------------*/ + +/* HPUTS - Set character string keyword = 'cval' in FITS header string */ + +static void +hputs (hstring,keyword,cval) + +char *hstring; /* FITS header */ +char *keyword; /* Keyword name */ +char *cval; /* character string containing the value for variable + keyword. trailing and leading blanks are removed. */ +{ + char squot = 39; + char value[70]; + int lcval; + + /* find length of variable string */ + + lcval = strlen (cval); + if (lcval > 67) + lcval = 67; + + /* Put quotes around string */ + value[0] = squot; + strncpy (&value[1],cval,lcval); + value[lcval+1] = squot; + value[lcval+2] = 0; + + /* Put value into header string */ + hputc (hstring,keyword,value); + + /* Return to calling program */ + return; +} + +/*---------------------------------------------------------------------*/ +/* HPUTC - Set character string keyword = value in FITS header string */ + +static void +hputc (hstring,keyword,value) + +char *hstring; +char *keyword; +char *value; /* character string containing the value for variable + keyword. trailing and leading blanks are removed. */ +{ + char squot = 39; + char line[100]; + char newcom[50]; + char blank[80]; + char *v, *vp, *v1, *v2, *q1, *q2, *c1, *ve; + int lkeyword, lcom, lval, lc, i; + + for (i = 0; i < 80; i++) + blank[i] = ' '; + + /* find length of keyword and value */ + lkeyword = strlen (keyword); + lval = strlen (value); + + /* If COMMENT or HISTORY, always add it just before the END */ + if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || + strncmp (keyword,"HISTORY",7) == 0)) { + + /* Find end of header */ + v1 = ksearch (hstring,"END"); + v2 = v1 + 80; + + /* Move END down one line */ + strncpy (v2, v1, 80); + + /* Insert keyword */ + strncpy (v1,keyword,7); + + /* Pad with spaces */ + for (vp = v1+lkeyword; vp < v2; vp++) + *vp = ' '; + + /* Insert comment */ + strncpy (v1+9,value,lval); + return; + } + + /* Otherwise search for keyword */ + else + v1 = ksearch (hstring,keyword); + + /* If parameter is not found, find a place to put it */ + if (v1 == NULL) { + + /* First look for blank lines before END */ + v1 = blsearch (hstring, "END"); + + /* Otherwise, create a space for it at the end of the header */ + if (v1 == NULL) { + ve = ksearch (hstring,"END"); + v1 = ve; + v2 = v1 + 80; + strncpy (v2, ve, 80); + } + else + v2 = v1 + 80; + lcom = 0; + newcom[0] = 0; + } + + /* Otherwise, extract the entry for this keyword from the header */ + else { + strncpy (line, v1, 80); + line[80] = 0; + v2 = v1 + 80; + + /* check for quoted value */ + q1 = strchr (line, squot); + if (q1 != NULL) + q2 = strchr (q1+1,squot); + else + q2 = line; + + /* extract comment and remove trailing spaces */ + + c1 = strchr (q2,'/'); + if (c1 != NULL) { + lcom = 80 - (c1 - line); + strncpy (newcom, c1+1, lcom); + vp = newcom + lcom - 1; + while (vp-- > newcom && *vp == ' ') + *vp = 0; + lcom = strlen (newcom); + } + else { + newcom[0] = 0; + lcom = 0; + } + } + + /* Fill new entry with spaces */ + for (vp = v1; vp < v2; vp++) + *vp = ' '; + + /* Copy keyword to new entry */ + strncpy (v1, keyword, lkeyword); + + /* Add parameter value in the appropriate place */ + vp = v1 + 8; + *vp = '='; + vp = v1 + 9; + *vp = ' '; + vp = vp + 1; + if (*value == squot) { + strncpy (vp, value, lval); + if (lval+12 > 31) + lc = lval + 12; + else + lc = 30; + } + else { + vp = v1 + 30 - lval; + strncpy (vp, value, lval); + lc = 30; + } + + /* Add comment in the appropriate place */ + if (lcom > 0) { + if (lc+2+lcom > 80) + lcom = 78 - lc; + vp = v1 + lc + 2; /* Jul 16 1997: was vp = v1 + lc * 2 */ + *vp = '/'; + vp = vp + 1; + strncpy (vp, newcom, lcom); + for (v = vp + lcom; v < v2; v++) + *v = ' '; + } + + return; +} + +/*-------------------------------------------------------------------*/ +/* HPUTCOM - Set comment for keyword or on line in FITS header string */ + +static void +hputcom (hstring,keyword,comment) + + char *hstring; + char *keyword; + char *comment; +{ + char squot; + char line[100]; + int lkeyword, lcom; + char *vp, *v1, *v2, *c0 = NULL, *c1, *q1, *q2; + + squot = 39; + +/* Find length of variable name */ + lkeyword = strlen (keyword); + +/* If COMMENT or HISTORY, always add it just before the END */ + if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || + strncmp (keyword,"HISTORY",7) == 0)) { + + /* Find end of header */ + v1 = ksearch (hstring,"END"); + v2 = v1 + 80; + strncpy (v2, v1, 80); + + /* blank out new line and insert keyword */ + for (vp = v1; vp < v2; vp++) + *vp = ' '; + strncpy (v1, keyword, lkeyword); + } + +/* search header string for variable name */ + else { + v1 = ksearch (hstring,keyword); + v2 = v1 + 80; + + /* if parameter is not found, return without doing anything */ + if (v1 == NULL) { + return; + } + + /* otherwise, extract entry for this variable from the header */ + strncpy (line, v1, 80); + + /* check for quoted value */ + q1 = strchr (line,squot); + if (q1 != NULL) + q2 = strchr (q1+1,squot); + else + q2 = NULL; + + if (q2 == NULL || q2-line < 31) + c0 = v1 + 31; + else + c0 = v1 + (q2-line) + 2; /* allan: 1997-09-30, was c0=q2+2 */ + + strncpy (c0, "/ ",2); + } + +/* create new entry */ + lcom = strlen (comment); + + if (lcom > 0) { + c1 = c0 + 2; + if (c1+lcom > v2) + lcom = v2 - c1; + strncpy (c1, comment, lcom); + } + +} |