2102 lines
56 KiB
C
2102 lines
56 KiB
C
/*------------------------------------------------------------------------*/
|
|
/* */
|
|
/* 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 "fitsio2.h"
|
|
#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(const 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, const 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 (const 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);
|
|
|
|
/* CFITS_API is defined below for use on Windows systems. */
|
|
/* It is used to identify the public functions which should be exported. */
|
|
/* This has no effect on non-windows platforms where "WIN32" is not defined */
|
|
|
|
/* this is only needed to export the "fits_delete_iraf_file" symbol, which */
|
|
/* is called in fpackutil.c (and perhaps in other applications programs) */
|
|
|
|
#if defined (WIN32)
|
|
#if defined(cfitsio_EXPORTS)
|
|
#define CFITS_API __declspec(dllexport)
|
|
#else
|
|
#define CFITS_API //__declspec(dllimport)
|
|
#endif /* CFITS_API */
|
|
#else /* defined (WIN32) */
|
|
#define CFITS_API
|
|
#endif
|
|
|
|
int CFITS_API fits_delete_iraf_file(const char *filename, int *status);
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int fits_delete_iraf_file(const 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 (
|
|
const 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[FLEN_ERRMSG];
|
|
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) {
|
|
snprintf(errmsg, FLEN_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) {
|
|
snprintf(errmsg, FLEN_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[FLEN_ERRMSG];
|
|
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) {
|
|
snprintf(errmsg, FLEN_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) {
|
|
snprintf(errmsg, FLEN_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) {
|
|
snprintf(errmsg, FLEN_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[FLEN_ERRMSG];
|
|
|
|
/* 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) {
|
|
snprintf(errmsg, FLEN_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:
|
|
snprintf(errmsg,FLEN_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 (
|
|
const 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 */
|
|
const 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;
|
|
if (strlen(value) > 29)
|
|
return(0);
|
|
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);
|
|
str[lstr-1]=0;
|
|
}
|
|
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;
|
|
char *saveptr;
|
|
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);
|
|
keyword[80]=0;
|
|
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 = ffstrtok (v1,cwhite,&saveptr);
|
|
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 */
|
|
snprintf (value,30,"%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);
|
|
}
|
|
|
|
}
|