548 lines
16 KiB
C
548 lines
16 KiB
C
/* $Id: qfits_card.c,v 1.8 2006/02/20 09:45:25 yjung Exp $
|
|
*
|
|
* This file is part of the ESO QFITS Library
|
|
* Copyright (C) 2001-2004 European Southern Observatory
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
* $Author: yjung $
|
|
* $Date: 2006/02/20 09:45:25 $
|
|
* $Revision: 1.8 $
|
|
* $Name: qfits-6_1_0 $
|
|
*/
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Includes
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <unistd.h>
|
|
|
|
#include "qfits_card.h"
|
|
|
|
#include "qfits_tools.h"
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Defines
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/* Define the following to get zillions of debug messages */
|
|
/* #define DEBUG_FITSHEADER */
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Static functions
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
static char * expkey_strupc(const char *) ;
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
* @defgroup qfits_card Card handling functions
|
|
*
|
|
* This module contains various routines to help parsing a single FITS
|
|
* card into its components: key, value, comment.
|
|
*
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@{*/
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Function codes
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Write out a card to a string on 80 chars.
|
|
@param line Allocated output character buffer.
|
|
@param key Key to write.
|
|
@param val Value to write.
|
|
@param com Comment to write.
|
|
@return void
|
|
|
|
Write out a key, value and comment into an allocated character buffer.
|
|
The buffer must be at least 80 chars to receive the information.
|
|
Formatting is done according to FITS standard.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
void qfits_card_build(
|
|
char * line,
|
|
const char * key,
|
|
const char * val,
|
|
const char * com)
|
|
{
|
|
int len ;
|
|
int hierarch = 0 ;
|
|
char cval[81];
|
|
char cval2[81];
|
|
char cval_q[81];
|
|
char ccom[81];
|
|
char safe_line[512];
|
|
int i, j ;
|
|
|
|
if (line==NULL || key==NULL) return ;
|
|
|
|
/* Set the line with zeroes */
|
|
memset(line, ' ', 80);
|
|
if (key==NULL) return ;
|
|
|
|
/* END keyword*/
|
|
if (!strcmp(key, "END")) {
|
|
/* Write key and return */
|
|
sprintf(line, "END") ;
|
|
return ;
|
|
}
|
|
/* HISTORY, COMMENT and blank keywords */
|
|
if (!strcmp(key, "HISTORY") ||
|
|
!strcmp(key, "COMMENT") ||
|
|
!strncmp(key, " ", 8)) {
|
|
/* Write key */
|
|
sprintf(line, "%s ", key);
|
|
if (val==NULL) return ;
|
|
|
|
/* There is a value to write, copy it correctly */
|
|
len = strlen(val);
|
|
/* 72 is 80 (FITS line size) - 8 (sizeof COMMENT or HISTORY) */
|
|
if (len>72) len=72 ;
|
|
strncpy(line+8, val, len);
|
|
return ;
|
|
}
|
|
|
|
/* Check for NULL values */
|
|
if (val==NULL) cval[0]=(char)0;
|
|
else if (strlen(val)<1) cval[0]=(char)0;
|
|
else strcpy(cval, val);
|
|
|
|
/* Check for NULL comments */
|
|
if (com==NULL) strcpy(ccom, "no comment");
|
|
else strcpy(ccom, com);
|
|
|
|
/* Set hierarch flag */
|
|
if (!strncmp(key, "HIERARCH", 8)) hierarch ++ ;
|
|
|
|
/* Boolean, int, float or complex */
|
|
if (qfits_is_int(cval) ||
|
|
qfits_is_float(cval) ||
|
|
qfits_is_boolean(cval) ||
|
|
qfits_is_complex(cval)) {
|
|
if (hierarch) sprintf(safe_line, "%-29s= %s / %s", key, cval, ccom);
|
|
else sprintf(safe_line, "%-8.8s= %20s / %-48s", key, cval, ccom);
|
|
strncpy(line, safe_line, 80);
|
|
line[80]=(char)0;
|
|
return ;
|
|
}
|
|
|
|
/* Blank or NULL values */
|
|
if (cval[0]==0) {
|
|
if (hierarch) {
|
|
sprintf(safe_line, "%-29s= / %s", key, ccom);
|
|
} else {
|
|
sprintf(safe_line, "%-8.8s= / %-48s", key, ccom);
|
|
}
|
|
strncpy(line, safe_line, 80);
|
|
line[80]=(char)0;
|
|
return ;
|
|
}
|
|
|
|
/* Can only be a string - Make simple quotes ['] as double [''] */
|
|
memset(cval_q, 0, 81);
|
|
strcpy(cval2, qfits_pretty_string(cval));
|
|
j=0 ;
|
|
i=0 ;
|
|
while (cval2[i] != (char)0) {
|
|
if (cval2[i]=='\'') {
|
|
cval_q[j]='\'';
|
|
j++ ;
|
|
cval_q[j]='\'';
|
|
} else {
|
|
cval_q[j] = cval2[i];
|
|
}
|
|
i++ ;
|
|
j++ ;
|
|
}
|
|
|
|
if (hierarch) {
|
|
sprintf(safe_line, "%-29s= '%s' / %s", key, cval_q, ccom);
|
|
if (strlen(key) + strlen(cval_q) + 3 >= 80)
|
|
safe_line[79] = '\'';
|
|
} else {
|
|
sprintf(safe_line, "%-8.8s= '%-8s' / %s", key, cval_q, ccom);
|
|
}
|
|
strncpy(line, safe_line, 80);
|
|
|
|
/* Null-terminate in any case */
|
|
line[80]=(char)0;
|
|
return ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Find the keyword in a key card (80 chars)
|
|
@param line allocated 80-char line from a FITS header
|
|
@return statically allocated char *
|
|
|
|
Find out the part of a FITS line corresponding to the keyword.
|
|
Returns NULL in case of error. The returned pointer is statically
|
|
allocated in this function, so do not modify or try to free it.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
char * qfits_getkey(const char * line)
|
|
{
|
|
static char key[81];
|
|
int i ;
|
|
|
|
if (line==NULL) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getkey: NULL input line\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
|
|
/* Special case: blank keyword */
|
|
if (!strncmp(line, " ", 8)) {
|
|
strcpy(key, " ");
|
|
return key ;
|
|
}
|
|
/* Sort out special cases: HISTORY, COMMENT, END do not have = in line */
|
|
if (!strncmp(line, "HISTORY ", 8)) {
|
|
strcpy(key, "HISTORY");
|
|
return key ;
|
|
}
|
|
if (!strncmp(line, "COMMENT ", 8)) {
|
|
strcpy(key, "COMMENT");
|
|
return key ;
|
|
}
|
|
if (!strncmp(line, "END ", 4)) {
|
|
strcpy(key, "END");
|
|
return key ;
|
|
}
|
|
|
|
memset(key, 0, 81);
|
|
/* General case: look for the first equal sign */
|
|
i=0 ;
|
|
while (line[i]!='=' && i<80) i++ ;
|
|
if (i>=80) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getkey: cannot find equal sign\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
i-- ;
|
|
/* Equal sign found, now backtrack on blanks */
|
|
while (line[i]==' ' && i>=0) i-- ;
|
|
if (i<=0) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getkey: error backtracking on blanks\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
i++ ;
|
|
|
|
/* Copy relevant characters into output buffer */
|
|
strncpy(key, line, i) ;
|
|
/* Null-terminate the string */
|
|
key[i+1] = (char)0;
|
|
return key ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Find the value in a key card (80 chars)
|
|
@param line allocated 80-char line from a FITS header
|
|
@return statically allocated char *
|
|
|
|
Find out the part of a FITS line corresponding to the value.
|
|
Returns NULL in case of error, or if no value can be found. The
|
|
returned pointer is statically allocated in this function, so do not
|
|
modify or try to free it.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
char * qfits_getvalue(const char * line)
|
|
{
|
|
static char value[81] ;
|
|
int i ;
|
|
int from, to ;
|
|
int inq ;
|
|
|
|
if (line==NULL) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getvalue: NULL input line\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
|
|
/* Special cases */
|
|
|
|
/* END has no associated value */
|
|
if (!strncmp(line, "END ", 4)) {
|
|
return NULL ;
|
|
}
|
|
/*
|
|
* HISTORY has for value everything else on the line, stripping
|
|
* blanks before and after. Blank HISTORY is also accepted.
|
|
*/
|
|
memset(value, 0, 81);
|
|
|
|
if (!strncmp(line, "HISTORY ", 8) || !strncmp(line, " ", 8)) {
|
|
i=7 ;
|
|
/* Strip blanks from the left side */
|
|
while (line[i]==' ' && i<80) i++ ;
|
|
if (i>=80) return NULL ; /* Blank HISTORY */
|
|
from=i ;
|
|
|
|
/* Strip blanks from the right side */
|
|
to=79 ;
|
|
while (line[to]==' ') to-- ;
|
|
/* Copy relevant characters into output buffer */
|
|
strncpy(value, line+from, to-from+1);
|
|
/* Null-terminate the string */
|
|
value[to-from+1] = (char)0;
|
|
return value ;
|
|
} else if (!strncmp(line, "COMMENT ", 8)) {
|
|
/* COMMENT is like HISTORY */
|
|
/* Strip blanks from the left side */
|
|
i=7 ;
|
|
while (line[i]==' ' && i<80) i++ ;
|
|
if (i>=80) return NULL ;
|
|
from=i ;
|
|
|
|
/* Strip blanks from the right side */
|
|
to=79 ;
|
|
while (line[to]==' ') to-- ;
|
|
|
|
if (to<from) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getvalue: inconsistent value search in COMMENT\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
/* Copy relevant characters into output buffer */
|
|
strncpy(value, line+from, to-from+1);
|
|
/* Null-terminate the string */
|
|
value[to-from+1] = (char)0;
|
|
return value ;
|
|
}
|
|
/* General case - Get past the keyword */
|
|
i=0 ;
|
|
while (line[i]!='=' && i<80) i++ ;
|
|
if (i>80) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getvalue: no equal sign found on line\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
i++ ;
|
|
while (line[i]==' ' && i<80) i++ ;
|
|
if (i>80) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getvalue: no value past the equal sign\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
from=i;
|
|
|
|
/* Now value section: Look for the first slash '/' outside a string */
|
|
inq = 0 ;
|
|
while (i<80) {
|
|
if (line[i]=='\'')
|
|
inq=!inq ;
|
|
if (line[i]=='/')
|
|
if (!inq)
|
|
break ;
|
|
i++;
|
|
}
|
|
i-- ;
|
|
|
|
/* Backtrack on blanks */
|
|
while (line[i]==' ' && i>=0) i-- ;
|
|
if (i<0) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getvalue: error backtracking on blanks\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
to=i ;
|
|
|
|
if (to<from) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getvalue: from>to?\n");
|
|
printf("line=[%s]\n", line);
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
/* Copy relevant characters into output buffer */
|
|
strncpy(value, line+from, to-from+1);
|
|
/* Null-terminate the string */
|
|
value[to-from+1] = (char)0;
|
|
return value ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Find the comment in a key card (80 chars)
|
|
@param line allocated 80-char line from a FITS header
|
|
@return statically allocated char *
|
|
|
|
Find out the part of a FITS line corresponding to the comment.
|
|
Returns NULL in case of error, or if no comment can be found. The
|
|
returned pointer is statically allocated in this function, so do not
|
|
modify or try to free it.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
char * qfits_getcomment(const char * line)
|
|
{
|
|
static char comment[81];
|
|
int i ;
|
|
int from, to ;
|
|
int inq ;
|
|
|
|
if (line==NULL) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getcomment: null line in input\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
|
|
/* Special cases: END, HISTORY, COMMENT and blank have no comment */
|
|
if (!strncmp(line, "END ", 4)) return NULL ;
|
|
if (!strncmp(line, "HISTORY ", 8)) return NULL ;
|
|
if (!strncmp(line, "COMMENT ", 8)) return NULL ;
|
|
if (!strncmp(line, " ", 8)) return NULL ;
|
|
|
|
memset(comment, 0, 81);
|
|
/* Get past the keyword */
|
|
i=0 ;
|
|
while (line[i]!='=' && i<80) i++ ;
|
|
if (i>=80) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getcomment: no equal sign on line\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
i++ ;
|
|
|
|
/* Get past the value until the slash */
|
|
inq = 0 ;
|
|
while (i<80) {
|
|
if (line[i]=='\'')
|
|
inq = !inq ;
|
|
if (line[i]=='/')
|
|
if (!inq)
|
|
break ;
|
|
i++ ;
|
|
}
|
|
if (i>=80) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getcomment: no slash found on line\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
i++ ;
|
|
/* Get past the first blanks */
|
|
while (line[i]==' ') i++ ;
|
|
from=i ;
|
|
|
|
/* Now backtrack from the end of the line to the first non-blank char */
|
|
to=79 ;
|
|
while (line[to]==' ') to-- ;
|
|
|
|
if (to<from) {
|
|
#ifdef DEBUG_FITSHEADER
|
|
printf("qfits_getcomment: from>to?\n");
|
|
#endif
|
|
return NULL ;
|
|
}
|
|
/* Copy relevant characters into output buffer */
|
|
strncpy(comment, line+from, to-from+1);
|
|
/* Null-terminate the string */
|
|
comment[to-from+1] = (char)0;
|
|
return comment ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Expand a keyword from shortFITS to HIERARCH notation.
|
|
@param keyword Keyword to expand.
|
|
@return 1 pointer to statically allocated string.
|
|
|
|
This function expands a given keyword from shortFITS to HIERARCH
|
|
notation, bringing it to uppercase at the same time.
|
|
|
|
Examples:
|
|
|
|
@verbatim
|
|
det.dit expands to HIERARCH ESO DET DIT
|
|
ins.filt1.id expands to HIERARCH ESO INS FILT1 ID
|
|
@endverbatim
|
|
|
|
If the input keyword is a regular FITS keyword (i.e. it contains
|
|
not dots '.') the result is identical to the input.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
char * qfits_expand_keyword(const char * keyword)
|
|
{
|
|
static char expanded[81];
|
|
char ws[81];
|
|
char * token ;
|
|
|
|
/* Bulletproof entries */
|
|
if (keyword==NULL) return NULL ;
|
|
/* If regular keyword, copy the uppercased input and return */
|
|
if (strstr(keyword, ".")==NULL) {
|
|
strcpy(expanded, expkey_strupc(keyword));
|
|
return expanded ;
|
|
}
|
|
/* Regular shortFITS keyword */
|
|
sprintf(expanded, "HIERARCH ESO");
|
|
strcpy(ws, expkey_strupc(keyword));
|
|
token = strtok(ws, ".");
|
|
while (token!=NULL) {
|
|
strcat(expanded, " ");
|
|
strcat(expanded, token);
|
|
token = strtok(NULL, ".");
|
|
}
|
|
return expanded ;
|
|
}
|
|
|
|
/**@}*/
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Uppercase a string
|
|
@param s string
|
|
@return string
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static char * expkey_strupc(const char * s)
|
|
{
|
|
static char l[1024+1];
|
|
int i ;
|
|
|
|
if (s==NULL) return NULL ;
|
|
memset(l, 0, 1024+1);
|
|
i=0 ;
|
|
while (s[i] && i<1024) {
|
|
l[i] = (char)toupper((int)s[i]);
|
|
i++ ;
|
|
}
|
|
l[1024]=(char)0;
|
|
return l ;
|
|
}
|
|
|