1
0
Fork 0

Add bits from qfits

qfits
Jeff Moe 2022-08-06 20:55:07 -06:00
parent fb339194c1
commit 28dd111b0f
25 changed files with 13938 additions and 0 deletions

3
qfits/AUTHORS 100644
View File

@ -0,0 +1,3 @@
Nicolas Devillard ndevilla@eso.org
Yves Jung yjung@eso.org

View File

@ -0,0 +1,22 @@
Copyright (c) 1995-2002, European Southern Observatory
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

163
qfits/Makefile 100644
View File

@ -0,0 +1,163 @@
#
# qfits Makefile
#
include config.make
AR = ar
ARFLAGS = rcs
RM = rm -f
CP = cp -f
# Implicit rules
SUFFIXES = .o .c .h .a .so .sl
COMPILE.c=$(CC) $(CFLAGS) -Iinclude $(RELOC) -c
.c.o:
@(echo "compiling $< ...")
@($(COMPILE.c) -o $@ $<)
SRCS = src/byteswap.c \
src/cache.c \
src/expkey.c \
src/fits_h.c \
src/fits_md5.c \
src/fits_p.c \
src/fits_rw.c \
src/get_name.c \
src/ieeefp-compat.c \
src/md5.c \
src/pafs.c \
src/pixio.c \
src/qerror.c \
src/simple.c \
src/t_iso8601.c \
src/tfits.c \
src/version.c \
src/xmemory.c
OBJS = $(SRCS:.c=.o)
default: all
all: $(TARGETS) progs
check:
@(if test -d ./test ; then\
(echo "Executing test programs..." ; cd test ; $(MAKE) ; \
./test_qfits ;\
./test_pixio ;\
./test_tfits ;) ; \
else (true) fi)
static: lib/libqfits.a
dynamic: lib/libqfits.$(DYNSUF)
lib/libqfits.a: $(OBJS)
@(echo "Building static library...")
@($(AR) $(ARFLAGS) lib/libqfits.a $(OBJS))
lib/libqfits.$(DYNSUF): $(OBJS)
@(echo "Building shared library...")
@(ld $(SHARED) -o lib/libqfits.$(DYNSUF) $(OBJS) -lc)
install:
@(echo "Installing library in " $(prefix))
mkdir -p $(prefix)
mkdir -p $(prefix)/lib
mkdir -p $(prefix)/include
mkdir -p $(prefix)/bin
@(if test -f ./include/qfits.h ; then\
($(CP) include/qfits.h $(prefix)/include); \
else (true) fi)
@(if test -f ./include/xmemory.h ; then\
($(CP) include/xmemory.h $(prefix)/include); \
else (true) fi)
@(if test -f ./lib/libqfits.a ; then\
($(CP) lib/libqfits.a $(prefix)/lib); \
else (true) fi)
@(if test -f ./lib/libqfits.$(DYNSUF) ; then\
($(CP) lib/libqfits.$(DYNSUF) $(prefix)/lib); \
else (true) fi)
@(if test -f ./bin/dfits ; then\
($(CP) bin/dfits $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/dtfits ; then\
($(CP) bin/dtfits $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/fitsmd5 ; then\
($(CP) bin/fitsmd5 $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/fitsort ; then\
($(CP) bin/fitsort $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/flipx ; then\
($(CP) bin/flipx $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/hierarch28 ; then\
($(CP) bin/hierarch28 $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/iofits ; then\
($(CP) bin/iofits $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/replacekey ; then\
($(CP) bin/replacekey $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/qextract ; then\
($(CP) bin/qextract $(prefix)/bin); \
else (true) fi)
@(if test -f ./bin/frameq ; then\
($(CP) bin/frameq $(prefix)/bin); \
else (true) fi)
clean:
$(RM) $(OBJS)
veryclean:
$(RM) $(OBJS) lib/libqfits.a lib/libqfits.$(DYNSUF)
$(RM) -r build
@(if test -d ./test ; then \
(cd test ; $(MAKE) veryclean ; cd ..) \
else (true) fi)
cd main ; $(MAKE) veryclean ; cd ..
cd saft ; $(MAKE) veryclean ; cd ..
$(RM) config.make
#
# Build example and stand-alone programs
#
progs:
cd main ; $(MAKE) ; cd ..
cd saft ; $(MAKE) ; cd ..
#
# Building qfits as a Python module.
#
# type:
# % python setup.py build
# % python setup.py install
#
docs:
@(echo "Building HTML documentation...")
@(cd doc ; $(MAKE))

19
qfits/configure vendored 100755
View File

@ -0,0 +1,19 @@
#!/bin/sh
#
# Bootstrap script: it tries to compile a simple C script using cc or
# gcc and launches it to create config.h and config.make files.
#
echo "configuring qfits..."
if (cc -o sysconf sysconf.c 2> /dev/null) ; then
echo "compiled sysconf successfully"
elif (gcc -o sysconf sysconf.c 2> /dev/null) ; then
echo "compiled sysconf successfully"
else echo "cannot find cc or gcc: aborting" ; exit
fi
./sysconf $*
mv config.h ./src
rm -f sysconf

2222
qfits/include/qfits.h 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
/*----------------------------------------------------------------------------*/
/**
@file xmemory.h
@author Nicolas Devillard
@date Oct 2000
@version $Revision: 1.24 $
@brief POSIX-compatible extended memory handling.
xmemory is a small and efficient module offering memory extension
capabitilies to ANSI C programs running on POSIX-compliant systems. It
offers several useful features such as memory leak detection, protection for
free on NULL or unallocated pointers, and virtually unlimited memory space.
xmemory requires the @c mmap() system call to be implemented in the local C
library to function. This module has been tested on a number of current Unix
flavours and is reported to work fine.
The current limitation is the limited number of pointers it can handle at
the same time.
See the documentation attached to this module for more information.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: xmemory.h,v 1.24 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.24 $
*/
#ifndef XMEMORY_H
#define XMEMORY_H
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/* To know if the current module has been linked against xmemory.c or not */
#define _XMEMORY_ 1
/*-----------------------------------------------------------------------------
Macros
-----------------------------------------------------------------------------*/
/* Protect strdup redefinition on systems which #define it */
#ifdef strdup
#undef strdup
#endif
#define malloc(s) xmemory_malloc(s, __FILE__,__LINE__)
#define calloc(n,s) xmemory_calloc(n,s, __FILE__,__LINE__)
#define realloc(p,s) xmemory_realloc(p,s, __FILE__,__LINE__)
#define free(p) xmemory_free(p, __FILE__,__LINE__)
#define strdup(s) xmemory_strdup(s, __FILE__,__LINE__)
#define falloc(f,o,s) xmemory_falloc(f,o,s, __FILE__,__LINE__)
#define fdealloc(f,o,s) xmemory_fdealloc(f,o,s, __FILE__,__LINE__)
#define xmemory_status() xmemory_status_(__FILE__,__LINE__)
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
void * xmemory_malloc(size_t, const char *, int) ;
void * xmemory_calloc(size_t, size_t, const char *, int) ;
void * xmemory_realloc(void *, size_t, const char *, int) ;
void xmemory_free(void *, const char *, int) ;
char * xmemory_strdup(const char *, const char *, int) ;
char * xmemory_falloc(char *, size_t, size_t *, const char *, int) ;
void xmemory_fdealloc(void *, size_t, size_t, const char *, int) ;
void xmemory_status_(const char * filename, int lineno) ;
#endif

View File

@ -0,0 +1,140 @@
/*----------------------------------------------------------------------------*/
/**
@file byteswap.c
@author N. Devillard
@date Sep 1999
@version $Revision: 1.7 $
@brief Low-level byte-swapping routines
This module offers access to byte-swapping routines.
Generic routines are offered that should work everywhere.
Assembler is also included for x86 architectures, and dedicated
assembler calls for processors > 386.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: byteswap.c,v 1.7 2003/01/23 08:38:09 yjung Exp $
$Author: yjung $
$Date: 2003/01/23 08:38:09 $
$Revision: 1.7 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include "config.h"
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/** Potential tracing feature for gcc > 2.95 */
#if (__GNUC__>2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ > 95))
#define __NOTRACE__ __attribute__((__no_instrument_function__))
#else
#define __NOTRACE__
#endif
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Swap a 16-bit number
@param w A 16-bit (short) number to byte-swap.
@return The swapped version of w, w is untouched.
This function swaps a 16-bit number, returned the swapped value without
modifying the passed argument. Assembler included for x86 architectures.
*/
/*----------------------------------------------------------------------------*/
unsigned short __NOTRACE__ swap_bytes_16(unsigned short w)
{
#ifdef CPU_X86
__asm("xchgb %b0,%h0" :
"=q" (w) :
"0" (w));
return w ;
#else
return (((w) & 0x00ff) << 8 | ((w) & 0xff00) >> 8);
#endif
}
/*----------------------------------------------------------------------------*/
/**
@brief Swap a 32-bit number
@param dw A 32-bit (long) number to byte-swap.
@return The swapped version of dw, dw is untouched.
This function swaps a 32-bit number, returned the swapped value without
modifying the passed argument. Assembler included for x86 architectures
and optimized for processors above 386.
*/
/*----------------------------------------------------------------------------*/
unsigned int __NOTRACE__ swap_bytes_32(unsigned int dw)
{
#ifdef CPU_X86
#if CPU_X86 > 386
__asm("bswap %0":
"=r" (dw) :
#else
__asm("xchgb %b0,%h0\n"
" rorl $16,%0\n"
" xchgb %b0,%h0":
"=q" (dw) :
#endif
"0" (dw));
return dw ;
#else
return ((((dw) & 0xff000000) >> 24) | (((dw) & 0x00ff0000) >> 8) |
(((dw) & 0x0000ff00) << 8) | (((dw) & 0x000000ff) << 24));
#endif
}
/*----------------------------------------------------------------------------*/
/**
@fn swap_bytes
@brief Swaps bytes in a variable of given size
@param p pointer to void (generic pointer)
@param s size of the element to swap, pointed to by p
@return void
This byte-swapper is portable and works for any even variable size.
It is not truly the most efficient ever, but does its job fine
everywhere this file compiles.
*/
/*----------------------------------------------------------------------------*/
void __NOTRACE__ swap_bytes(void * p, int s)
{
unsigned char tmp, *a, *b ;
a = (unsigned char*)p ;
b = a + s ;
while (a<b) {
tmp = *a ;
*a++ = *--b ;
*b = tmp ;
}
}
/*----------------------------------------------------------------------------*/
/**
@brief Find out if the local machine is big or little endian
@return int 1 if local machine needs byteswapping (INTEL), 0 else.
This function determines at run-time the endian-ness of the local
machine. An INTEL-like processor needs byte-swapping, a
MOTOROLA-like one does not.
*/
/*----------------------------------------------------------------------------*/
int need_byteswapping(void)
{
short ps = 0xFF ;
return ((*((char*)(&ps))) ? 1 : 0 ) ;
}
/* vim: set ts=4 et sw=4 tw=75 */

767
qfits/src/cache.c 100644
View File

@ -0,0 +1,767 @@
/*----------------------------------------------------------------------------*/
/**
@file cache.c
@author N. Devillard
@date Mar 2001
@version $Revision: 1.19 $
@brief FITS caching capabilities
This modules implements a cache for FITS access routines.
The first time a FITS file is seen by the library, all corresponding
pointers are cached here. This speeds up multiple accesses to large
files by magnitudes.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: cache.c,v 1.19 2005/07/19 15:38:52 yjung Exp $
$Author: yjung $
$Date: 2005/07/19 15:38:52 $
$Revision: 1.19 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "static_sz.h"
#include "xmemory.h"
#include "cache.h"
#include "fits_p.h"
#include "fits_std.h"
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/** Define this symbol to get debug symbols -- not recommended! */
#define QFITS_CACHE_DEBUG 0
#if QFITS_CACHE_DEBUG
#define qdebug( code ) { code }
#else
#define qdebug( code )
#endif
/**
* Cache size:
* Maximum number of FITS file informations stored in the cache.
*/
#define QFITS_CACHESZ 128
/**
* This static definition declares the maximum possible number of
* extensions in a FITS file. It only has effects in the qfits_cache_add
* function where a table is statically allocated for efficiency reasons.
* If the number of extensions grows over this limit, change the value of
* this constant. If the number of extensions is a priori unknown but can
* grow much larger than a predictable value, the best solution is to
* implement a dynamic memory allocation in qfits_cache_add.
*/
#define QFITS_MAX_EXTS 128
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Cache cell (private)
This structure stores all informations about a given FITS file.
It is strictly internal to this module.
*/
/*----------------------------------------------------------------------------*/
typedef struct _qfits_cache_cell_ {
char * name ; /* File name */
ino_t inode ; /* Inode */
time_t mtime; /* Last modification date */
int filesize; /* File size in bytes */
time_t ctime; /* Last modification date */
int exts ; /* # of extensions in file */
int * ohdr ; /* Offsets to headers */
int * shdr ; /* Header sizes */
int * data ; /* Offsets to data */
int * dsiz ; /* Data sizes */
int fsize ; /* File size in blocks (2880 bytes) */
} qfits_cache_cell ;
static qfits_cache_cell qfits_cache[QFITS_CACHESZ] ;
static int qfits_cache_last = -1 ;
static int qfits_cache_entries = 0 ;
static int qfits_cache_init = 0 ;
/*-----------------------------------------------------------------------------
Functions prototypes
-----------------------------------------------------------------------------*/
static void qfits_cache_activate(void);
static int qfits_is_cached(char * filename);
static int qfits_cache_add(char * name);
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief initialize cache buffer with minimum size
*/
/*----------------------------------------------------------------------------*/
static void qfits_cache_activate(void)
{
int i ;
qdebug(
printf("qfits: activating cache...\n");
);
/* Set all slots to NULL */
for (i=0 ; i<QFITS_CACHESZ ; i++) {
qfits_cache[i].name = NULL ;
}
/* Register purge function with atexit */
atexit(qfits_cache_purge);
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Purge the qfits cache.
@return void
This function is useful for programs running for a long period,
to clean up the cache. Ideally in a daemon, it should be called
by a timer at regular intervals. Notice that since the cache is
fairly small, you should not need to care too much about this.
*/
/*----------------------------------------------------------------------------*/
void qfits_cache_purge(void)
{
int i ;
qdebug(
printf("qfits: purging cache...\n");
);
for (i=0 ; i<QFITS_CACHESZ; i++) {
if (qfits_cache[i].name!=NULL) {
free(qfits_cache[i].name);
qfits_cache[i].name = NULL ;
free(qfits_cache[i].ohdr);
free(qfits_cache[i].data);
free(qfits_cache[i].shdr);
free(qfits_cache[i].dsiz);
qfits_cache_entries -- ;
}
}
if (qfits_cache_entries!=0) {
qdebug(
printf("qfits: internal error in cache consistency\n");
);
exit(-1);
}
qfits_cache_last = -1 ;
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Find out if a file is in the cache already
@param filename file name
@return int 1 if in the cache, 0 if not
*/
/*----------------------------------------------------------------------------*/
static int qfits_is_cached(char * filename)
{
int i, n ;
struct stat sta ;
/* Stat input file */
if (stat(filename, &sta)!=0) {
return -1 ;
}
n=0 ;
/* Loop over all cache entries */
for (i=0 ; i<QFITS_CACHESZ ; i++) {
/* If entry is valid (name is not NULL) */
if (qfits_cache[i].name!=NULL) {
/* One more entry found */
n++ ;
/* If inode is the same */
if ((qfits_cache[i].inode == sta.st_ino) &&
(qfits_cache[i].mtime == sta.st_mtime) &&
(qfits_cache[i].filesize == sta.st_size) &&
(qfits_cache[i].ctime == sta.st_ctime)) {
/* This is the requested file */
return i ;
}
}
/* Early exit: all entries have been browsed */
if (n>=qfits_cache_entries) {
return -1 ;
}
}
return -1 ;
}
#if QFITS_CACHE_DEBUG
void qfits_cache_dump(void)
{
int i, j ;
printf("qfits: dumping cache...\n");
printf("cache contains %d entries\n", qfits_cache_entries);
for (i=0 ; i<QFITS_CACHESZ ; i++) {
if (qfits_cache[i].name!=NULL) {
printf("qfits: -----> entry: %d\n", i);
printf("qfits: name %s\n", qfits_cache[i].name);
printf("qfits: exts %d\n", qfits_cache[i].exts);
printf("qfits: size %d\n", qfits_cache[i].fsize);
printf("qfits: ohdr %d\n"
"qfits: shdr %d\n"
"qfits: data %d\n"
"qfits: dsiz %d\n",
qfits_cache[i].ohdr[0],
qfits_cache[i].shdr[0],
qfits_cache[i].data[0],
qfits_cache[i].dsiz[0]);
if (qfits_cache[i].exts>0) {
for (j=1 ; j<=qfits_cache[i].exts ; j++) {
printf("qfits: %s [%d]\n", qfits_cache[i].name, j);
printf("qfits: ohdr %d\n"
"qfits: shdr %d\n"
"qfits: data %d\n"
"qfits: dsiz %d\n",
qfits_cache[i].ohdr[j],
qfits_cache[i].shdr[j],
qfits_cache[i].data[j],
qfits_cache[i].dsiz[j]);
}
}
}
}
return ;
}
#endif
/*----------------------------------------------------------------------------*/
/**
@brief Query a FITS file offset from the cache.
@param filename Name of the file to examine.
@param what What should be queried (see below).
@return an integer offset, or -1 if an error occurred.
This function queries the cache for FITS offset information. If the
requested file name has never been seen before, it is completely parsed
to extract all offset informations, which are then stored in the cache.
The next query will get the informations from the cache, avoiding
a complete re-parsing of the file. This is especially useful for large
FITS files with lots of extensions, because querying the extensions
is an expensive operation.
This operation has side-effects: the cache is an automatically
allocated structure in memory, that can only grow. Every request
on a new FITS file will make it grow. The structure is pretty
light-weight in memory, but nonetheless this is an issue for daemon-type
programs which must run over long periods. The solution is to clean
the cache using qfits_cache_purge() at regular intervals. This is left
to the user of this library.
To request information about a FITS file, you must pass an integer
built from the following symbols:
- @c QFITS_QUERY_N_EXT
- @c QFITS_QUERY_HDR_START
- @c QFITS_QUERY_DAT_START
- @c QFITS_QUERY_HDR_SIZE
- @c QFITS_QUERY_DAT_SIZE
Querying the number of extensions present in a file is done
simply with:
@code
next = qfits_query(filename, QFITS_QUERY_N_EXT);
@endcode
Querying the offset to the i-th extension header is done with:
@code
off = qfits_query(filename, QFITS_QUERY_HDR_START | i);
@endcode
i.e. you must OR (|) the extension number with the
@c QFITS_QUERY_HDR_START symbol. Requesting offsets to extension data is
done in the same way:
@code
off = qfits_query(filename, QFITS_QUERY_DAT_START | i);
@endcode
Notice that extension 0 is the main header and main data part
of the FITS file.
*/
/*----------------------------------------------------------------------------*/
int qfits_query(char * filename, int what)
{
int rank ;
int which ;
int answer ;
qdebug(
printf("qfits: cache req %s\n", filename);
);
if ((rank=qfits_is_cached(filename))==-1) {
rank = qfits_cache_add(filename);
}
if (rank==-1) {
qdebug(
printf("qfits: error adding %s to cache\n", filename);
);
return -1 ;
}
/* See what was requested */
answer=-1 ;
if (what & QFITS_QUERY_N_EXT) {
answer = qfits_cache[rank].exts ;
qdebug(
printf("qfits: query n_exts\n");
printf("qfits: -> %d\n", answer);
);
} else if (what & QFITS_QUERY_HDR_START) {
which = what & (~QFITS_QUERY_HDR_START);
if (which>=0 && which<=qfits_cache[rank].exts) {
answer = qfits_cache[rank].ohdr[which] * FITS_BLOCK_SIZE ;
}
qdebug(
printf("qfits: query offset to header %d\n", which);
printf("qfits: -> %d (%d bytes)\n", answer/2880, answer);
);
} else if (what & QFITS_QUERY_DAT_START) {
which = what & (~QFITS_QUERY_DAT_START);
if (which>=0 && which<=qfits_cache[rank].exts) {
answer = qfits_cache[rank].data[which] * FITS_BLOCK_SIZE ;
}
qdebug(
printf("qfits: query offset to data %d\n", which);
printf("qfits: -> %d (%d bytes)\n", answer/2880, answer);
);
} else if (what & QFITS_QUERY_HDR_SIZE) {
which = what & (~QFITS_QUERY_HDR_SIZE);
if (which>=0 && which<=qfits_cache[rank].exts) {
answer = qfits_cache[rank].shdr[which] * FITS_BLOCK_SIZE ;
}
qdebug(
printf("qfits: query sizeof header %d\n", which);
printf("qfits: -> %d (%d bytes)\n", answer/2880, answer);
);
} else if (what & QFITS_QUERY_DAT_SIZE) {
which = what & (~QFITS_QUERY_DAT_SIZE);
if (which>=0 && which<=qfits_cache[rank].exts) {
answer = qfits_cache[rank].dsiz[which] * FITS_BLOCK_SIZE ;
}
qdebug(
printf("qfits: query sizeof data %d\n", which);
printf("qfits: -> %d (%d bytes)\n", answer/2880, answer);
);
}
return answer ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Add pointer information about a file into the qfits cache.
@param filename Name of the file to examine.
@return index to the file information in the cache, or -1 if failure.
This function picks a file name, and examines the corresponding FITS file
to deduce all relevant pointers in the file (byte offsets). These byte
offsets are later used to speed up header lookups. Example: requesting
some keyword information in the header of the n-th extension will first
fseek the file to the header start, then search from this position
onwards. This means that the input FITS file is only parsed for extension
positions once.
What this function does is:
- Open the file, read the first FITS block (@c FITS_BLOCK_SIZE bytes)
- Check the file is FITS (must have SIMPLE = at top)
- Register start of first header at offset 0.
- Look for END keyword, register start of first data section
if NAXIS>0.
- If the EXTEND=T line was found, continue looking for extensions.
- For each consecutive extension, register extension header start
and extension data start.
*/
/*----------------------------------------------------------------------------*/
static int qfits_cache_add(char * filename)
{
FILE * in ;
int off_hdr[QFITS_MAX_EXTS];
int off_dat[QFITS_MAX_EXTS];
char buf[FITS_BLOCK_SIZE] ;
char * buf_c ;
int n_blocks ;
int found_it ;
int xtend ;
int naxis ;
char * read_val ;
int last ;
int end_of_file ;
int data_bytes ;
int skip_blocks ;
struct stat sta ;
int seeked ;
int i ;
qfits_cache_cell * qc ;
/* Initialize cache if not done yet (done only once) */
if (qfits_cache_init==0) {
qfits_cache_init++ ;
qfits_cache_activate();
}
/* Stat file to get its size */
if (stat(filename, &sta)!=0) {
qdebug(
printf("qfits: cannot stat file %s\n", filename);
);
return -1 ;
}
/* Open input file */
if ((in=fopen(filename, "r"))==NULL) {
qdebug(
printf("qfits: cannot open file %s\n", filename);
);
return -1 ;
}
/* Read first block in */
if (fread(buf, 1, FITS_BLOCK_SIZE, in)!=FITS_BLOCK_SIZE) {
qdebug(
printf("qfits: error reading first block from %s\n", filename);
);
fclose(in);
return -1 ;
}
/* Identify FITS magic number */
if (buf[0]!='S' ||
buf[1]!='I' ||
buf[2]!='M' ||
buf[3]!='P' ||
buf[4]!='L' ||
buf[5]!='E' ||
buf[6]!=' ' ||
buf[7]!=' ' ||
buf[8]!='=') {
qdebug(
printf("qfits: file %s is not FITS\n", filename);
);
fclose(in);
return -1 ;
}
/*
* Browse through file to identify primary HDU size and see if there
* might be some extensions. The size of the primary data zone will
* also be estimated from the gathering of the NAXIS?? values and
* BITPIX.
*/
/* Rewind input file, END card might be in first block */
rewind(in);
/* Initialize all counters */
n_blocks = 0 ;
found_it = 0 ;
xtend = 0 ;
naxis = 0 ;
data_bytes = 1 ;
/* Start looking for END card */
while (found_it==0) {
/* Read one FITS block */
if (fread(buf, 1, FITS_BLOCK_SIZE, in)!=FITS_BLOCK_SIZE) {
qdebug(
printf("qfits: error reading file %s\n", filename);
);
fclose(in);
return -1 ;
}
n_blocks ++ ;
/* Browse through current block */
buf_c = buf ;
for (i=0 ; i<FITS_NCARDS ; i++) {
/* Look for BITPIX keyword */
if (buf_c[0]=='B' &&
buf_c[1]=='I' &&
buf_c[2]=='T' &&
buf_c[3]=='P' &&
buf_c[4]=='I' &&
buf_c[5]=='X' &&
buf_c[6]==' ') {
read_val = qfits_getvalue(buf_c);
data_bytes *= (int)atoi(read_val) / 8 ;
if (data_bytes<0) data_bytes *= -1 ;
} else
/* Look for NAXIS keyword */
if (buf_c[0]=='N' &&
buf_c[1]=='A' &&
buf_c[2]=='X' &&
buf_c[3]=='I' &&
buf_c[4]=='S') {
if (buf_c[5]==' ') {
/* NAXIS keyword */
read_val = qfits_getvalue(buf_c);
naxis = (int)atoi(read_val);
} else {
/* NAXIS?? keyword (axis size) */
read_val = qfits_getvalue(buf_c);
data_bytes *= (int)atoi(read_val);
}
} else
/* Look for EXTEND keyword */
if (buf_c[0]=='E' &&
buf_c[1]=='X' &&
buf_c[2]=='T' &&
buf_c[3]=='E' &&
buf_c[4]=='N' &&
buf_c[5]=='D' &&
buf_c[6]==' ') {
/* The EXTEND keyword is present: might be some extensions */
read_val = qfits_getvalue(buf_c);
if (read_val[0]=='T' || read_val[0]=='1') {
xtend=1 ;
}
} else
/* Look for END keyword */
if (buf_c[0] == 'E' &&
buf_c[1] == 'N' &&
buf_c[2] == 'D' &&
buf_c[3] == ' ') {
found_it = 1 ;
}
buf_c += FITS_LINESZ ;
}
}
/*
* Prepare qfits cache for addition of a new entry
*/
qfits_cache_last++ ;
/* Rotate buffer if needed */
if (qfits_cache_last >= QFITS_CACHESZ) {
qfits_cache_last = 0 ;
}
/* Alias to current pointer in cache for easier reading */
qc = &(qfits_cache[qfits_cache_last]);
/* Clean cache cell if needed */
if (qc->name!=NULL) {
free(qc->name) ;
qc->name = NULL ;
free(qc->ohdr);
free(qc->data);
free(qc->shdr);
free(qc->dsiz);
qfits_cache_entries -- ;
}
/* Initialize cache cell */
qc->exts=0 ;
qc->name = strdup(filename);
qc->inode= sta.st_ino ;
/* Set first HDU offsets */
off_hdr[0] = 0 ;
off_dat[0] = n_blocks ;
/* Last is the pointer to the last added extension, plus one. */
last = 1 ;
if (xtend) {
/* Look for extensions */
qdebug(
printf("qfits: searching for extensions in %s\n", filename);
);
/*
* Register all extension offsets
*/
end_of_file = 0 ;
while (end_of_file==0) {
/*
* Skip the previous data section if pixels were declared
*/
if (naxis>0) {
/* Skip as many blocks as there are declared pixels */
skip_blocks = data_bytes/FITS_BLOCK_SIZE ;
if ((data_bytes % FITS_BLOCK_SIZE)!=0) {
skip_blocks ++ ;
}
seeked = fseek(in, skip_blocks*FITS_BLOCK_SIZE, SEEK_CUR);
if (seeked<0) {
qdebug(
printf("qfits: error seeking file %s\n", filename);
);
free(qc->name);
fclose(in);
return -1 ;
}
/* Increase counter of current seen blocks. */
n_blocks += skip_blocks ;
}
/* Look for extension start */
found_it=0 ;
while ((found_it==0) && (end_of_file==0)) {
if (fread(buf,1,FITS_BLOCK_SIZE,in)!=FITS_BLOCK_SIZE) {
/* Reached end of file */
end_of_file=1 ;
break ;
}
n_blocks ++ ;
/* Search for XTENSION at block top */
if (buf[0]=='X' &&
buf[1]=='T' &&
buf[2]=='E' &&
buf[3]=='N' &&
buf[4]=='S' &&
buf[5]=='I' &&
buf[6]=='O' &&
buf[7]=='N' &&
buf[8]=='=') {
/* Got an extension */
found_it=1 ;
off_hdr[last] = n_blocks-1 ;
}
}
if (end_of_file) break ;
/*
* Look for extension END
* Rewind one block backwards, END might be in same section as
* XTENSION start.
*/
if (fseek(in, -FITS_BLOCK_SIZE, SEEK_CUR)==-1) {
qdebug(
printf("qfits: error fseeking file backwards\n");
) ;
free(qc->name);
fclose(in);
return -1 ;
}
n_blocks -- ;
found_it=0 ;
data_bytes = 1 ;
naxis = 0 ;
while ((found_it==0) && (end_of_file==0)) {
if (fread(buf,1,FITS_BLOCK_SIZE,in)!=FITS_BLOCK_SIZE) {
qdebug(
printf("qfits: XTENSION without END in %s\n", filename);
);
end_of_file=1;
break ;
}
n_blocks++ ;
/* Browse current block */
buf_c = buf ;
for (i=0 ; i<FITS_NCARDS ; i++) {
/* Look for BITPIX keyword */
if (buf_c[0]=='B' &&
buf_c[1]=='I' &&
buf_c[2]=='T' &&
buf_c[3]=='P' &&
buf_c[4]=='I' &&
buf_c[5]=='X' &&
buf_c[6]==' ') {
read_val = qfits_getvalue(buf_c);
data_bytes *= (int)atoi(read_val) / 8 ;
if (data_bytes<0) data_bytes *= -1 ;
} else
/* Look for NAXIS keyword */
if (buf_c[0]=='N' &&
buf_c[1]=='A' &&
buf_c[2]=='X' &&
buf_c[3]=='I' &&
buf_c[4]=='S') {
if (buf_c[5]==' ') {
/* NAXIS keyword */
read_val = qfits_getvalue(buf_c);
naxis = (int)atoi(read_val);
} else {
/* NAXIS?? keyword (axis size) */
read_val = qfits_getvalue(buf_c);
data_bytes *= (int)atoi(read_val);
}
} else
/* Look for END keyword */
if (buf_c[0]=='E' &&
buf_c[1]=='N' &&
buf_c[2]=='D' &&
buf_c[3]==' ') {
/* Got the END card */
found_it=1 ;
/* Update registered extension list */
off_dat[last] = n_blocks ;
last ++ ;
qc->exts ++ ;
break ;
}
buf_c+=FITS_LINESZ ;
}
}
}
}
/* Close file */
fclose(in);
/* Allocate buffers in cache */
qc->ohdr = malloc(last * sizeof(int));
qc->data = malloc(last * sizeof(int));
qc->shdr = malloc(last * sizeof(int));
qc->dsiz = malloc(last * sizeof(int));
/* Store retrieved pointers in the cache */
for (i=0 ; i<last ; i++) {
/* Offsets to start */
qc->ohdr[i] = off_hdr[i];
qc->data[i] = off_dat[i];
/* Sizes */
qc->shdr[i] = off_dat[i] - off_hdr[i] ;
if (i==last-1) {
qc->dsiz[i] = (sta.st_size/FITS_BLOCK_SIZE) - off_dat[i] ;
} else {
qc->dsiz[i] = off_hdr[i+1] - off_dat[i] ;
}
}
qc->fsize = sta.st_size / FITS_BLOCK_SIZE ;
/* Add last modification date */
qc->mtime = sta.st_mtime ;
qc->filesize = sta.st_size ;
qc->ctime = sta.st_ctime ;
qfits_cache_entries ++ ;
qdebug(
qfits_cache_dump();
);
/* Return index of the added file in the cache */
return qfits_cache_last ;
}
/* vim: set ts=4 et sw=4 tw=75 */

103
qfits/src/expkey.c 100644
View File

@ -0,0 +1,103 @@
/*----------------------------------------------------------------------------*/
/**
@file expkey.c
@author N. Devillard
@date Feb 2001
@version $Revisions$
@brief Expand keyword from shortFITS to HIERARCH notation
This module offers a function that is reused in a number of different
places.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: expkey.c,v 1.6 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.6 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "static_sz.h"
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Uppercase a string
@param s string
@return string
*/
/*----------------------------------------------------------------------------*/
static char * expkey_strupc(const char * s)
{
static char l[ASCIILINESZ+1];
int i ;
if (s==NULL) return NULL ;
memset(l, 0, ASCIILINESZ+1);
i=0 ;
while (s[i] && i<ASCIILINESZ) {
l[i] = (char)toupper((int)s[i]);
i++ ;
}
l[ASCIILINESZ]=(char)0;
return l ;
}
/*----------------------------------------------------------------------------*/
/**
@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 ;
}
/* vim: set ts=4 et sw=4 tw=75 */

1334
qfits/src/fits_h.c 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_md5.c
@author N. Devillard
@date May 2001
@version $Revision: 1.8 $
@brief FITS data block MD5 computation routine.
This module offers MD5 computation over all data areas of a FITS file.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_md5.c,v 1.8 2003/01/23 09:13:18 yjung Exp $
$Author: yjung $
$Date: 2003/01/23 09:13:18 $
$Revision: 1.8 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "md5.h"
#include "fits_std.h"
#include "qerror.h"
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/** Size of an MD5 hash in bytes (32 bytes are 128 bits) */
#define MD5HASHSZ 32
/*-----------------------------------------------------------------------------
Function code
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Compute the MD5 hash of data zones in a FITS file.
@param filename Name of the FITS file to examine.
@return 1 statically allocated character string, or NULL.
This function expects the name of a FITS file.
It will compute the MD5 hash on all data blocks in the main data section
and possibly extensions (including zero-padding blocks if necessary) and
return it as a string suitable for inclusion into a FITS keyword.
The returned string is statically allocated inside this function,
so do not free it or modify it. This function returns NULL in case
of error.
*/
/*----------------------------------------------------------------------------*/
char * qfits_datamd5(char * filename)
{
static char datamd5[MD5HASHSZ+1] ;
struct MD5Context ctx ;
unsigned char digest[16] ;
FILE * in ;
char buf[FITS_BLOCK_SIZE];
char * buf_c ;
int i ;
int in_header ;
int check_fits ;
/* Check entries */
if (filename==NULL) return NULL ;
/* Open input file */
if ((in=fopen(filename, "r"))==NULL) {
qfits_error("cannot open file %s", filename);
return NULL ;
}
/* Initialize all variables */
MD5Init(&ctx);
in_header=1 ;
check_fits=0 ;
/* Loop over input file */
while (fread(buf, 1, FITS_BLOCK_SIZE, in)==FITS_BLOCK_SIZE) {
/* First time in the loop: check the file is FITS */
if (check_fits==0) {
/* Examine first characters in block */
if (buf[0]!='S' ||
buf[1]!='I' ||
buf[2]!='M' ||
buf[3]!='P' ||
buf[4]!='L' ||
buf[5]!='E' ||
buf[6]!=' ' ||
buf[7]!=' ' ||
buf[8]!='=') {
qfits_error("file [%s] is not FITS\n", filename);
fclose(in);
return NULL ;
} else {
check_fits=1 ;
}
}
if (in_header) {
buf_c = buf ;
for (i=0 ; i<FITS_NCARDS ; i++) {
if (buf_c[0]=='E' &&
buf_c[1]=='N' &&
buf_c[2]=='D' &&
buf_c[3]==' ') {
in_header=0 ;
break ;
}
buf_c += FITS_LINESZ ;
}
} else {
/* If current block is a data block */
/* Try to locate an extension header */
if (buf[0]=='X' &&
buf[1]=='T' &&
buf[2]=='E' &&
buf[3]=='N' &&
buf[4]=='S' &&
buf[5]=='I' &&
buf[6]=='O' &&
buf[7]=='N' &&
buf[8]=='=') {
in_header=1 ;
buf_c = buf ;
for (i=0 ; i<FITS_NCARDS ; i++) {
/* Try to find an END marker in this block */
if (buf_c[0]=='E' &&
buf_c[1]=='N' &&
buf_c[2]=='D' &&
buf_c[3]==' ') {
/* Found END marker in same block as XTENSION */
in_header=0;
break ;
}
buf_c += FITS_LINESZ ;
}
} else {
MD5Update(&ctx, (unsigned char *)buf, FITS_BLOCK_SIZE);
}
}
}
fclose(in);
if (check_fits==0) {
/* Never went through the read loop: file is not FITS */
qfits_error("file [%s] is not FITS", filename);
return NULL ;
}
/* Got to the end of file: summarize */
MD5Final(digest, &ctx);
/* Write digest into a string */
sprintf(datamd5,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[ 0],
digest[ 1],
digest[ 2],
digest[ 3],
digest[ 4],
digest[ 5],
digest[ 6],
digest[ 7],
digest[ 8],
digest[ 9],
digest[10],
digest[11],
digest[12],
digest[13],
digest[14],
digest[15]);
return datamd5 ;
}
/* vim: set ts=4 et sw=4 tw=75 */

326
qfits/src/fits_p.c 100644
View File

@ -0,0 +1,326 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_p.c
@author N. Devillard
@date Mar 2000
@version $Revision: 1.4 $
@brief FITS parser for a single card
This module contains various routines to help parsing a single FITS
card into its components: key, value, comment.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_p.c,v 1.4 2003/01/23 09:18:54 yjung Exp $
$Author: yjung $
$Date: 2003/01/23 09:18:54 $
$Revision: 1.4 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "simple.h"
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/* Define the following to get zillions of debug messages */
/* #define DEBUG_FITSHEADER */
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@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(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(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(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 ;
}
/* vim: set ts=4 et sw=4 tw=75 */

408
qfits/src/fits_rw.c 100644
View File

@ -0,0 +1,408 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_rw.c
@author N. Devillard
@date Mar 2000
@version $Revision: 1.21 $
@brief FITS header reading/writing.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_rw.c,v 1.21 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.21 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fits_rw.h"
#include "fits_h.h"
#include "fits_p.h"
#include "simple.h"
#include "xmemory.h"
#include "qerror.h"
/*-----------------------------------------------------------------------------
Private to this module
-----------------------------------------------------------------------------*/
static int is_blank_line(char * s)
{
int i ;
for (i=0 ; i<(int)strlen(s) ; i++) {
if (s[i]!=' ') return 0 ;
}
return 1 ;
}
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Read a FITS header from a file to an internal structure.
@param filename Name of the file to be read
@return Pointer to newly allocated qfits_header or NULL in error case.
This function parses a FITS (main) header, and returns an allocated
qfits_header object. The qfits_header object contains a linked-list of
key "tuples". A key tuple contains:
- A keyword
- A value
- A comment
- An original FITS line (as read from the input file)
Direct access to the structure is not foreseen, use accessor
functions in fits_h.h
Value, comment, and original line might be NULL pointers.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_read(char * filename)
{
/* Forward job to readext */
return qfits_header_readext(filename, 0);
}
/*----------------------------------------------------------------------------*/
/**
@brief Read a FITS header from a 'hdr' file.
@param filename Name of the file to be read
@return Pointer to newly allocated qfits_header or NULL in error case
This function parses a 'hdr' file, and returns an allocated qfits_header
object. A hdr file is an ASCII format were the header is written with a
carriage return after each line. The command dfits typically displays
a hdr file.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_read_hdr(char * filename)
{
qfits_header * hdr ;
FILE * in ;
char line[81];
char * key,
* val,
* com ;
int i, j ;
/* Check input */
if (filename==NULL) return NULL ;
/* Initialise */
key = val = com = NULL ;
/* Open the file */
if ((in=fopen(filename, "r"))==NULL) {
qfits_error("cannot read [%s]", filename) ;
return NULL ;
}
/* Create the header */
hdr = qfits_header_new() ;
/* Go through the file */
while (fgets(line, 81, in)!=NULL) {
for (i=0 ; i<81 ; i++) {
if (line[i] == '\n') {
for (j=i ; j<81 ; j++) line[j] = ' ' ;
line[80] = (char)0 ;
break ;
}
}
if (!strcmp(line, "END")) {
line[3] = ' ';
line[4] = (char)0 ;
}
/* Rule out blank lines */
if (!is_blank_line(line)) {
/* Get key, value, comment for the current line */
key = qfits_getkey(line);
val = qfits_getvalue(line);
com = qfits_getcomment(line);
/* If key or value cannot be found, trigger an error */
if (key==NULL) {
qfits_header_destroy(hdr);
fclose(in) ;
return NULL ;
}
/* Append card to linked-list */
qfits_header_append(hdr, key, val, com, NULL);
}
}
fclose(in) ;
/* The last key should be 'END' */
if (strlen(key)!=3) {
qfits_header_destroy(hdr);
return NULL ;
}
if (key[0]!='E' || key[1]!='N' || key[2]!='D') {
qfits_header_destroy(hdr);
return NULL ;
}
return hdr ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Read a FITS header from a 'hdr' string
@param hdr_str String containing the hdr file
@param nb_char Number of characters in the string
@return Pointer to newly allocated qfits_header or NULL in error case
This function parses a 'hdr' string, and returns an allocated qfits_header
object.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_read_hdr_string(
unsigned char * hdr_str,
int nb_char)
{
qfits_header * hdr ;
char line[81];
char * key,
* val,
* com ;
int ind ;
int i, j ;
/* Check input */
if (hdr_str==NULL) return NULL ;
/* Initialise */
key = val = com = NULL ;
/* Create the header */
hdr = qfits_header_new() ;
/* Go through the file */
ind = 0 ;
while (ind <= nb_char - 80) {
strncpy(line, (char*)hdr_str + ind, 80) ;
line[80] = (char)0 ;
for (i=0 ; i<81 ; i++) {
if (line[i] == '\n') {
for (j=i ; j<81 ; j++) line[j] = ' ' ;
line[80] = (char)0 ;
break ;
}
}
if (!strcmp(line, "END")) {
line[3] = ' ';
line[4] = (char)0 ;
}
/* Rule out blank lines */
if (!is_blank_line(line)) {
/* Get key, value, comment for the current line */
key = qfits_getkey(line);
val = qfits_getvalue(line);
com = qfits_getcomment(line);
/* If key or value cannot be found, trigger an error */
if (key==NULL) {
qfits_header_destroy(hdr);
return NULL ;
}
/* Append card to linked-list */
qfits_header_append(hdr, key, val, com, NULL);
}
ind += 80 ;
}
/* The last key should be 'END' */
if (strlen(key)!=3) {
qfits_header_destroy(hdr);
return NULL ;
}
if (key[0]!='E' || key[1]!='N' || key[2]!='D') {
qfits_header_destroy(hdr);
return NULL ;
}
return hdr ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Read an extension header from a FITS file.
@param filename Name of the FITS file to read
@param xtnum Extension number to read, starting from 0.
@return Newly allocated qfits_header structure.
Strictly similar to qfits_header_read() but reads headers from
extensions instead. If the requested xtension is 0, this function
returns the main header.
Returns NULL in case of error.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_readext(char * filename, int xtnum)
{
qfits_header* hdr ;
int n_ext ;
char line[81];
char * where ;
char * start ;
char * key,
* val,
* com ;
int seg_start ;
int seg_size ;
size_t size ;
/* Check input */
if (filename==NULL || xtnum<0)
return NULL ;
/* Check that there are enough extensions */
if (xtnum>0) {
n_ext = qfits_query_n_ext(filename);
if (xtnum>n_ext) {
return NULL ;
}
}
/* Get offset to the extension header */
if (qfits_get_hdrinfo(filename, xtnum, &seg_start, &seg_size)!=0) {
return NULL ;
}
/* Memory-map the input file */
start = falloc(filename, seg_start, &size) ;
if (start==NULL) return NULL ;
hdr = qfits_header_new() ;
where = start ;
while (1) {
memcpy(line, where, 80);
line[80] = (char)0;
/* Rule out blank lines */
if (!is_blank_line(line)) {
/* Get key, value, comment for the current line */
key = qfits_getkey(line);
val = qfits_getvalue(line);
com = qfits_getcomment(line);
/* If key or value cannot be found, trigger an error */
if (key==NULL) {
qfits_header_destroy(hdr);
hdr = NULL ;
break ;
}
/* Append card to linked-list */
qfits_header_append(hdr, key, val, com, line);
/* Check for END keyword */
if (strlen(key)==3)
if (key[0]=='E' &&
key[1]=='N' &&
key[2]=='D')
break ;
}
where += 80 ;
/* If reaching the end of file, trigger an error */
if ((int)(where-start)>=(int)(seg_size+80)) {
qfits_header_destroy(hdr);
hdr = NULL ;
break ;
}
}
fdealloc(start, seg_start, size) ;
return hdr ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Pad an existing file with zeros to a multiple of 2880.
@param filename Name of the file to pad.
@return void
This function simply pads an existing file on disk with enough zeros
for the file size to reach a multiple of 2880, as required by FITS.
*/
/*----------------------------------------------------------------------------*/
void qfits_zeropad(char * filename)
{
struct stat sta ;
int size ;
int remaining;
FILE * out ;
char * buf;
if (filename==NULL) return ;
/* Get file size in bytes */
if (stat(filename, &sta)!=0) {
return ;
}
size = (int)sta.st_size ;
/* Compute number of zeros to pad */
remaining = size % FITS_BLOCK_SIZE ;
if (remaining==0) return ;
remaining = FITS_BLOCK_SIZE - remaining ;
/* Open file, dump zeros, exit */
if ((out=fopen(filename, "a"))==NULL)
return ;
buf = calloc(remaining, sizeof(char));
fwrite(buf, 1, remaining, out);
fclose(out);
free(buf);
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a file is a FITS file.
@param filename name of the file to check
@return int 0, 1, or -1
Returns 1 if the file name looks like a valid FITS file. Returns
0 else. If the file does not exist, returns -1.
*/
/*----------------------------------------------------------------------------*/
int is_fits_file(char *filename)
{
FILE * fp ;
char * magic ;
int isfits ;
if (filename==NULL) return -1 ;
if ((fp = fopen(filename, "r"))==NULL) {
qfits_error("cannot open file [%s]", filename) ;
return -1 ;
}
magic = calloc(FITS_MAGIC_SZ+1, sizeof(char)) ;
fread(magic, 1, FITS_MAGIC_SZ, fp) ;
fclose(fp) ;
magic[FITS_MAGIC_SZ] = (char)0 ;
if (strstr(magic, FITS_MAGIC)!=NULL)
isfits = 1 ;
else
isfits = 0 ;
free(magic) ;
return isfits ;
}
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,256 @@
/*----------------------------------------------------------------------------*/
/**
@file get_name.c
@author Y. Jung
@date Jan 2004
@version $Revision: 1.6 $
@brief Get various names (filenames, dir names, login name, etc...)
The following functions are useful to cut out a filename into its components.
All functions work with statically allocated memory, i.e. the pointers they
return are not permanent but likely to be overwritten at each function call.
If you need a returned value later on, you should store it into a local
variable.
Example:
@code
char * s ;
s = qfits_get_dir_name("/mnt/cdrom/data/image.fits")
@endcode
s contains now "/mnt/cdrom/data" but will loose these contents at the next
function call. To retain its value, you can either do:
@code
char s[1024];
strcpy(s, qfits_get_dir_name("/mnt/cdrom/data/image.fits"));
@endcode
or:
@code
char * s;
s = strdup(qfits_get_dir_name("/mnt/cdrom/data/image.fits"));
...
free(s);
@endcode
*/
/*----------------------------------------------------------------------------*/
/*
$Id: get_name.c,v 1.6 2004/05/26 09:10:49 yjung Exp $
$Author: yjung $
$Date: 2004/05/26 09:10:49 $
$Revision: 1.6 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include "get_name.h"
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
/** Maximum size of a filename buffer */
#define MAXNAMESZ 4096
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Find the directory name in the given string.
@param filename Full path name to scan.
@return Pointer to statically allocated string.
Provide a full path name and you get in return a pointer to a statically
allocated string containing the name of the directory only, without trailing
slash. If the input string does not contain a slash (i.e. it is not a full
path), the returned string is '.', corresponding to the current working
directory. Since the returned string is statically allocated, do not try to
free it or modify it.
This function does not check for the existence of the path or the file.
Examples:
@verbatim
qfits_get_dir_name("/cdrom/data/image.fits") returns "/cdrom/data"
qfits_get_dir_name("filename.fits") returns "."
@endverbatim
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_dir_name(char * filename)
{
static char path[MAXNAMESZ];
char *last_slash;
if (strlen(filename)>MAXNAMESZ) return NULL ;
strcpy(path, filename);
/* Find last '/'. */
last_slash = path != NULL ? strrchr (path, '/') : NULL;
if (last_slash == path)
/* The last slash is the first character in the string. We have to
return "/". */
++last_slash;
else if (last_slash != NULL && last_slash[1] == '\0')
/* The '/' is the last character, we have to look further. */
last_slash = memchr (path, last_slash - path, '/');
if (last_slash != NULL)
/* Terminate the path. */
last_slash[0] = '\0';
else
/* This assignment is ill-designed but the XPG specs require to
return a string containing "." in any case no directory part is
found and so a static and constant string is required. */
strcpy(path, ".");
return path;
}
/*----------------------------------------------------------------------------*/
/**
@brief Find out the base name of a file (i.e. without prefix path)
@param filename Full path name to scan.
@return Pointer to char within the input string.
Provide a full path name and you get in return a pointer to a statically
allocated string containing the name of the file only, without prefixing
directory names. If the input string does not contain a slash (i.e. it is
not a full path), the returned string is a copy of the input string.
This function does not check for the existence of the path or the file.
Examples:
@verbatim
qfits_get_base_name("/cdrom/data/image.fits") returns "image.fits"
qfits_get_base_name("filename.fits") returns "filename.fits"
@endverbatim
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_base_name(const char *filename)
{
char *p ;
p = strrchr (filename, '/');
return p ? p + 1 : (char *) filename;
}
/*----------------------------------------------------------------------------*/
/**
@brief Find out the root part of a basename (name without extension).
@param filename File name to scan.
@return Pointer to statically allocated string.
Find out the root part of a file name, i.e. the file name without extension.
Since in Unix a file name can have several dots, only a number of extensions
are supported. This includes:
- .fits and .FITS
- .tfits and .TFITS
- .paf and .PAF
- .ascii and .ASCII
- .dat and .DAT
- .txt and .TXT
This function does not check for the existence of the path or the file.
Examples:
@verbatim
qfits_get_root_name("/cdrom/filename.fits") returns "/cdrom/filename"
qfits_get_root_name("filename.paf") returns "filename"
qfits_get_root_name("filename") returns "filename"
qfits_get_root_name("filename.ext") returns "filename.ext"
@endverbatim
Since the returned string is statically allocated in this module, do not try
to free it or modify its contents.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_root_name(char * filename)
{
static char path[MAXNAMESZ+1];
char * lastdot ;
if (strlen(filename)>MAXNAMESZ) return NULL ;
memset(path, MAXNAMESZ, 0);
strcpy(path, filename);
lastdot = strrchr(path, '.');
if (lastdot == NULL) return path ;
if ((!strcmp(lastdot, ".fits")) || (!strcmp(lastdot, ".FITS")) ||
(!strcmp(lastdot, ".paf")) || (!strcmp(lastdot, ".PAF")) ||
(!strcmp(lastdot, ".dat")) || (!strcmp(lastdot, ".DAT")) ||
(!strcmp(lastdot, ".txt")) || (!strcmp(lastdot, ".TXT")) ||
(!strcmp(lastdot, ".tfits")) || (!strcmp(lastdot, ".TFITS")) ||
(!strcmp(lastdot, ".ascii")) || (!strcmp(lastdot, ".ASCII")))
{
lastdot[0] = (char)0;
}
return path ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Find out the extension of a file name
@param filename File name without path prefix.
@return Pointer to char within the input string.
Find out the extension of a given file name. Notice that the input character
string must not contain a path prefix (typically, you feed in the output of
@c qfits_get_base_name).
Works with all kinds of extensions: returns the part of the string after the
last dot. If no dot is found in the input string, NULL is returned.
Examples:
@verbatim
qfits_get_ext_name("filename.fits") returns "fits"
qfits_get_ext_name("hello.c") returns "c"
qfits_get_ext_name("readme") returns NULL
@endverbatim
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_ext_name(char * filename)
{
char * p;
p = strrchr(filename, '.');
return p ? p+1 : NULL ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Returns the user login name.
@return Pointer to statically allocated character string.
Finds out what the login name of the current user is. The result is placed in
a static character string inside this module and a pointer to the first
character in this string is returned. Do not modify or free the returned
string!
If the user name cannot be determined, the returned pointer will point to a
string which first character is a null character.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_login_name(void)
{
struct passwd * pw ;
static char name[32];
pw = getpwuid(getuid());
if (pw!=NULL) {
strcpy(name, pw->pw_name);
} else {
name[0]=0 ;
}
return name ;
}

View File

@ -0,0 +1,220 @@
/*----------------------------------------------------------------------------*/
/**
@file ieeefp-compat.c
@author N. Devillard
@date Feb 2002
@version $Revision: 2.7 $
@brief This module implements the isnan() and isinf() macros.
The isnan() and isinf() macros are unfortunately not yet part of
the standard C math library everywhere. They can usually be found
in different places, if they are offered at all, and require the
application to link against the math library. To avoid portability
problems and linking against -lm, this module implements a fast
and portable way of finding out whether a floating-point value
(float or double) is a NaN or an Inf.
Instead of calling isnan() and isinf(), the programmer including
this file should call qfits_isnan() and qfits_isinf().
*/
/*----------------------------------------------------------------------------*/
/*
$Id: ieeefp-compat.c,v 2.7 2003/01/23 09:27:55 yjung Exp $
$Author: yjung $
$Date: 2003/01/23 09:27:55 $
$Revision: 2.7 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include "config.h"
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
#ifndef WORDS_BIGENDIAN
/* Little endian ordering */
typedef union _ieee_double_pattern_ {
double d ;
struct {
unsigned int lsw ;
unsigned int msw ;
} p ;
} ieee_double_pattern ;
#else
/* Big endian ordering */
typedef union _ieee_double_pattern_ {
double d ;
struct {
unsigned int msw ;
unsigned int lsw ;
} p ;
} ieee_double_pattern ;
#endif
typedef union _ieee_float_pattern_ {
float f ;
int i ;
} ieee_float_pattern ;
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
int _qfits_isnanf(float f)
{
ieee_float_pattern ip ;
int ix ;
ip.f = f ;
ix = ip.i ;
ix &= 0x7fffffff ;
ix = 0x7f800000 - ix ;
return (int)(((unsigned int)(ix))>>31);
}
int _qfits_isinff(float f)
{
ieee_float_pattern ip ;
int ix, t ;
ip.f = f ;
ix = ip.i ;
t = ix & 0x7fffffff;
t ^= 0x7f800000;
t |= -t;
return ~(t >> 31) & (ix >> 30);
}
int _qfits_isnand(double d)
{
ieee_double_pattern id ;
int hx, lx ;
id.d = d ;
lx = id.p.lsw ;
hx = id.p.msw ;
hx &= 0x7fffffff;
hx |= (unsigned int)(lx|(-lx))>>31;
hx = 0x7ff00000 - hx;
return (int)(((unsigned int)hx)>>31);
}
int _qfits_isinfd(double d)
{
ieee_double_pattern id ;
int hx, lx ;
id.d = d ;
lx = id.p.lsw ;
hx = id.p.msw ;
lx |= (hx & 0x7fffffff) ^ 0x7ff00000;
lx |= -lx;
return ~(lx >> 31) & (hx >> 30);
}
/*
* Test program to validate the above functions
* Compile with:
* % cc -o ieeefp-compat ieeefp-compat.c -DTEST
*/
#ifdef TEST
#include <stdio.h>
#include <string.h>
#include "ieeefp-compat.h"
#ifndef WORDS_BIGENDIAN
/* Little endian patterns */
static unsigned char fnan_pat[] = {0, 0, 0xc0, 0x7f};
static unsigned char dnan_pat[] = {0, 0, 0, 0, 0, 0, 0xf8, 0x7f};
static unsigned char finf_pat[] = {0, 0, 0x80, 0x7f};
static unsigned char dinf_pat[] = {0, 0, 0, 0, 0, 0, 0xf0, 0x7f};
static unsigned char fminf_pat[] = {0, 0, 0x80, 0xff};
/* static unsigned char dminf_pat[] = {0, 0, 0, 0, 0, 0, 0xf0, 0xff}; */
static unsigned char dminf_pat[] = {0, 0, 0, 0, 0, 0, 0xf0, 0x7f};
#else
/* Big endian patterns */
static unsigned char fnan_pat[] = {0x7f, 0xc0, 0, 0};
static unsigned char dnan_pat[] = {0x7f, 0xf8, 0, 0, 0, 0, 0, 0};
static unsigned char finf_pat[] = {0x7f, 0x80, 0, 0};
static unsigned char dinf_pat[] = {0x7f, 0xf0, 0, 0, 0, 0, 0, 0};
static unsigned char fminf_pat[] = {0xff, 0x80, 0, 0};
static unsigned char dminf_pat[] = {0xff, 0xf0, 0, 0, 0, 0, 0, 0};
#endif
static void hexdump(void * p, int s)
{
unsigned char * c ;
int i ;
c=(unsigned char*)p ;
#ifndef WORDS_BIGENDIAN
for (i=s-1 ; i>=0 ; i--) {
#else
for (i=0 ; i<s ; i++) {
#endif
printf("%02x", c[i]);
}
printf("\n");
}
int main(void)
{
float f ;
double d ;
printf("Testing Nan...\n");
memcpy(&f, fnan_pat, 4);
memcpy(&d, dnan_pat, 8);
printf("f=%g d=%g\n", f, d);
hexdump(&f, sizeof(float));
hexdump(&d, sizeof(double));
if (qfits_isnan(f)) {
printf("f is NaN\n");
}
if (qfits_isnan(d)) {
printf("d is NaN\n");
}
printf("Testing +Inf...\n");
memcpy(&f, finf_pat, 4);
memcpy(&d, dinf_pat, 8);
printf("f=%g d=%g\n", f, d);
hexdump(&f, sizeof(float));
hexdump(&d, sizeof(double));
if (qfits_isinf(f)) {
printf("f is Inf\n");
}
if (qfits_isinf(d)) {
printf("d is Inf\n");
}
printf("Testing -Inf...\n");
memcpy(&f, fminf_pat, 4);
memcpy(&d, dminf_pat, 8);
printf("f=%g d=%g\n", f, d);
hexdump(&f, sizeof(float));
hexdump(&d, sizeof(double));
if (qfits_isinf(f)) {
printf("f is (-)Inf\n");
}
if (qfits_isinf(d)) {
printf("d is (-)Inf\n");
}
return 0 ;
}
#endif
/* vim: set ts=4 et sw=4 tw=75 */

267
qfits/src/md5.c 100644
View File

@ -0,0 +1,267 @@
/*----------------------------------------------------------------------------*/
/**
@file md5.c
@author N. Devillard
@date July 2001
@version $Revision: 1.3 $
@brief MD5 message-digest algorithm
The algorithm is due to Ron Rivest. This code was written by Colin Plumb
in 1993, no copyright is claimed. This code is in the public domain; do
with it what you wish.
Equivalent code is available from RSA Data Security, Inc. This code has
been tested against that, and is equivalent, except that you don't need to
include two pages of legalese with every copy.
To compute the message digest of a chunk of bytes, declare an MD5Context
structure, pass it to MD5Init, call MD5Update as needed on buffers full of
bytes, and then call MD5Final, which will fill a supplied 16-byte array with
the digest.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: md5.c,v 1.3 2003/01/23 09:35:57 yjung Exp $
$Author: yjung $
$Date: 2003/01/23 09:35:57 $
$Revision: 1.3 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include "md5.h"
#include <string.h>
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static void byteReverse(unsigned char *buf, unsigned longs) ;
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*
* Note: this code is harmless on little-endian machines.
*/
static void byteReverse(unsigned char *buf, unsigned longs)
{
word32 t;
do {
t = (word32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(word32 *) buf = t;
buf += 4;
} while (--longs);
}
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{
register word32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((word32) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memmove(p, buf, len);
return;
}
memmove(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (word32 *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memmove(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (word32 *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memmove(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
{
unsigned int count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (word32 *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((word32 *) ctx->in)[14] = ctx->bits[0];
((word32 *) ctx->in)[15] = ctx->bits[1];
MD5Transform(ctx->buf, (word32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memmove(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(word32 buf[4], word32 const in[16])
{
register word32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/* vim: set ts=4 et sw=4 tw=75 */

235
qfits/src/pafs.c 100644
View File

@ -0,0 +1,235 @@
/*----------------------------------------------------------------------------*/
/**
@file pafs.c
@author Nicolas Devillard
@date February 1999
@version $Revision: 1.5 $
@brief paf format I/O
*/
/*----------------------------------------------------------------------------*/
/*
$Id: pafs.c,v 1.5 2003/01/23 09:40:03 yjung Exp $
$Author: yjung $
$Date: 2003/01/23 09:40:03 $
$Revision: 1.5 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include "qerror.h"
#include "pafs.h"
#include "t_iso8601.h"
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
#define PAF_MAGIC "PAF.HDR.START"
#define PAF_MAGIC_SZ 13
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static char * qfits_strcrop(char * s) ;
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Open a new PAF file, output a default header.
@param filename Name of the file to create.
@param paf_id PAF identificator.
@param paf_desc PAF description.
@param login_name Login name
@param datetime Date
@return Opened file pointer.
This function creates a new PAF file with the requested file name.
If another file already exists with the same name, it will be
overwritten (if the file access rights allow it).
A default header is produced according to the VLT DICB standard. You
need to provide an identificator (paf_id) of the producer of the
file. Typically, something like "ISAAC/zero_point".
The PAF description (paf_desc) is meant for humans. Typically,
something like "Zero point computation results".
This function returns an opened file pointer, ready to receive more
data through fprintf's. The caller is responsible for fclose()ing
the file.
*/
/*----------------------------------------------------------------------------*/
FILE * qfits_paf_print_header(
char * filename,
char * paf_id,
char * paf_desc,
char * login_name,
char * datetime)
{
FILE * paf ;
if ((paf=fopen(filename, "w"))==NULL) {
qfits_error("cannot create PAF file [%s]", filename);
return NULL ;
}
fprintf(paf, "PAF.HDR.START ;# start of header\n");
fprintf(paf, "PAF.TYPE \"pipeline product\" ;\n");
fprintf(paf, "PAF.ID \"%s\"\n", paf_id);
fprintf(paf, "PAF.NAME \"%s\"\n", filename);
fprintf(paf, "PAF.DESC \"%s\"\n", paf_desc);
fprintf(paf, "PAF.CRTE.NAME \"%s\"\n", login_name) ;
fprintf(paf, "PAF.CRTE.DAYTIM \"%s\"\n", datetime) ;
fprintf(paf, "PAF.LCHG.NAME \"%s\"\n", login_name) ;
fprintf(paf, "PAF.LCHG.DAYTIM \"%s\"\n", datetime) ;
fprintf(paf, "PAF.CHCK.CHECKSUM \"\"\n");
fprintf(paf, "PAF.HDR.END ;# end of header\n");
fprintf(paf, "\n");
return paf ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Query a PAF file for a value.
@param filename Name of the PAF to query.
@param key Name of the key to query.
@return 1 pointer to statically allocated string, or NULL.
This function parses a PAF file and returns the value associated to a
given key, as a pointer to an internal statically allocated string.
Do not try to free or modify the contents of the returned string!
If the key is not found, this function returns NULL.
*/
/*----------------------------------------------------------------------------*/
char * qfits_paf_query(
char * filename,
char * key)
{
static char value[ASCIILINESZ];
FILE * paf ;
char line[ASCIILINESZ+1];
char val[ASCIILINESZ+1];
char head[ASCIILINESZ+1];
int found ;
int len ;
/* Check inputs */
if (filename==NULL || key==NULL) return NULL ;
/* Check PAF validity */
if (qfits_is_paf_file(filename)!=1) {
qfits_error("not a PAF file: [%s]", filename);
return NULL ;
}
/* Open file and read it */
paf = fopen(filename, "r");
if (paf==NULL) {
qfits_error("opening [%s]", filename);
return NULL ;
}
found = 0 ;
while (fgets(line, ASCIILINESZ, paf)!=NULL) {
sscanf(line, "%[^ ]", head);
if (!strcmp(head, key)) {
/* Get value */
sscanf(line, "%*[^ ] %[^;]", value);
found ++ ;
break ;
}
}
if (!found) return NULL ;
/* Remove trailing blanks */
strcpy(val, qfits_strcrop(value));
/* Get rid of possible quotes */
len = strlen(val);
if (val[0]=='\"' && val[len-1]=='\"') {
strncpy(value, val+1, len-2);
value[len-2]=(char)0;
} else {
strcpy(value, val);
}
return value ;
}
/*----------------------------------------------------------------------------*/
/**
@brief returns 1 if file is in PAF format, 0 else
@param filename name of the file to check
@return int 0, 1, or -1
Returns 1 if the file name corresponds to a valid PAF file. Returns
0 else. If the file does not exist, returns -1. Validity of the PAF file
is checked with the presence of PAF.HDR.START at the beginning
*/
/*----------------------------------------------------------------------------*/
int qfits_is_paf_file(char * filename)
{
FILE * fp ;
int is_paf ;
char line[ASCIILINESZ] ;
if (filename==NULL) return -1 ;
/* Initialize is_paf */
is_paf = 0 ;
/* Open file */
if ((fp = fopen(filename, "r"))==NULL) {
qfits_error("cannot open file [%s]", filename) ;
return -1 ;
}
/* Parse file */
while (fgets(line, ASCIILINESZ, fp) != NULL) {
if (line[0] != '#') {
if (!strncmp(line, PAF_MAGIC, PAF_MAGIC_SZ)) is_paf = 1 ;
(void)fclose(fp) ;
return is_paf ;
}
}
(void)fclose(fp) ;
return is_paf ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Remove blanks at the end of a string.
@param s String to parse.
@return ptr to statically allocated string.
This function returns a pointer to a statically allocated string,
which is identical to the input string, except that all blank
characters at the end of the string have been removed.
Do not free or modify the returned string! Since the returned string
is statically allocated, it will be modified at each function call
(not re-entrant).
*/
/*----------------------------------------------------------------------------*/
static char * qfits_strcrop(char * s)
{
static char l[ASCIILINESZ+1];
char * last ;
if (s==NULL) return NULL ;
memset(l, 0, ASCIILINESZ+1);
strcpy(l, s);
last = l + strlen(l);
while (last > l) {
if (!isspace((int)*(last-1)))
break ;
last -- ;
}
*last = (char)0;
return l ;
}
/* vim: set ts=4 et sw=4 tw=75 */

1309
qfits/src/pixio.c 100644

File diff suppressed because it is too large Load Diff

198
qfits/src/qerror.c 100644
View File

@ -0,0 +1,198 @@
/*----------------------------------------------------------------------------*/
/**
@file qerror.c
@author N. Devillard
@date Aug 2001
@version $Revision: 1.9 $
@brief
This module is responsible for error message display. It allows
to re-direct all messages to a given set of functions for display.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: qerror.c,v 1.9 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.9 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/* Max number of error handling functions registered */
#define QFITS_ERR_MAXERRDISP 8
/* Max size of an error message */
#define QFITS_ERR_MSGSIZE 1024
/*-----------------------------------------------------------------------------
Private stuff
-----------------------------------------------------------------------------*/
/* Type of a display function only defined for legibility here */
typedef void (*qfits_err_dispfunc)(char *) ;
/* Default display function prints out msg to stderr */
static void qfits_err_display_stderr(char * s)
{ fprintf(stderr, "qfits: %s\n", s); }
/* Static control structure, completely private */
static struct {
qfits_err_dispfunc disp[QFITS_ERR_MAXERRDISP] ;
int n ;
int active ;
} qfits_err_control = {{qfits_err_display_stderr}, 1, 0} ;
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief used for message display
@param msg message
@return nothing
It calls registered display functions one after another.
*/
/*----------------------------------------------------------------------------*/
static void qfits_err_main_display(char * msg)
{
int i ;
/* Check if there is a message in input */
if (msg==NULL)
return ;
/* Loop on all registered functions and call them */
for (i=0 ; i<qfits_err_control.n ; i++) {
if (qfits_err_control.disp[i]) {
qfits_err_control.disp[i](msg);
}
}
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Get the current status of error display.
@return int 1 if error display is active, 0 if not.
This function returns the current error display status. If it returns 1,
it means that all calls to qfits_error/qfits_warning will display
messages using the registered functions, otherwise they do nothing.
*/
/*----------------------------------------------------------------------------*/
int qfits_err_statget(void)
{
return qfits_err_control.active ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Set the current status of error display.
@param sta New status to be set.
@return int giving the previous display status.
This function sets the current error display status to the required
value, and returns the previous value. It is useful to store the
previous value, in view of restoring it afterwards, e.g. to make a
function silent on all its errors. Example:
@code
int prev_stat = qfits_err_statset(0) ;
function_call() ;
qfits_err_statset(prev_stat);
@endcode
*/
/*----------------------------------------------------------------------------*/
int qfits_err_statset(int sta)
{
int prev ;
prev = qfits_err_control.active ;
qfits_err_control.active=sta ;
return prev ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Register a function to display error/warning messages.
@param dispfn Display function (see doc below).
@return int 0 if function was registered, -1 if not.
This function registers a display function into the error-handling
module. Display functions have the following prototype:
@code
void display_function(char * msg);
@endcode
They are simple functions that expect a ready-made error message
and return void. They can do whatever they want with the message
(log it to a file, send it to a GUI, to the syslog, ...). The
message is built using a printf-like statement in qfits_error and
qfits_warning, then passed to all registered display functions.
A maximum of QFITS_ERR_MAXERRDISP can be registered (see source code).
If the limit has been reached, this function will signal it by
returning -1.
*/
/*----------------------------------------------------------------------------*/
int qfits_err_register(qfits_err_dispfunc dispfn)
{
if (qfits_err_control.n==QFITS_ERR_MAXERRDISP) {
/* Cannot register any more function */
return -1 ;
}
qfits_err_control.disp[qfits_err_control.n] = dispfn ;
qfits_err_control.n ++ ;
return 0 ;
}
/* Public warning/error functions */
void qfits_warning(const char *fmt, ...)
{
char msg[QFITS_ERR_MSGSIZE] ;
char all[QFITS_ERR_MSGSIZE] ;
va_list ap ;
/* Check if display is activated */
if (qfits_err_control.active==0) {
return ;
}
va_start(ap, fmt) ;
vsprintf(msg, fmt, ap) ;
va_end(ap);
sprintf(all, "*** %s", msg);
qfits_err_main_display(all);
return ;
}
void qfits_error(const char *fmt, ...)
{
char msg[QFITS_ERR_MSGSIZE] ;
char all[QFITS_ERR_MSGSIZE] ;
va_list ap ;
/* Check if display is activated */
if (qfits_err_control.active==0) {
return ;
}
va_start(ap, fmt) ;
vsprintf(msg, fmt, ap) ;
va_end(ap);
sprintf(all, "error: %s", msg);
qfits_err_main_display(all);
return ;
}
/* vim: set ts=4 et sw=4 tw=75 */

712
qfits/src/simple.c 100644
View File

@ -0,0 +1,712 @@
/*----------------------------------------------------------------------------*/
/**
@file simple.c
@author N. Devillard
@date Jan 1999
@version $Revision: 1.18 $
@brief Simple FITS access routines.
This module offers a number of very basic low-level FITS access
routines.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: simple.c,v 1.18 2005/07/20 14:31:22 yjung Exp $
$Author: yjung $
$Date: 2005/07/20 14:31:22 $
$Revision: 1.18 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <regex.h>
#include "simple.h"
#include "fits_p.h"
#include "expkey.h"
#include "cache.h"
#include "fits_std.h"
#include "qerror.h"
#include "xmemory.h"
/*-----------------------------------------------------------------------------
Global variables
-----------------------------------------------------------------------------*/
/*
* The following global variables are only used for regular expression
* matching of integers and floats. These definitions are private to
* this module.
*/
/** A regular expression matching a floating-point number */
static char regex_float[] =
"^[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+)([eEdD][+-]?[0-9]+)?$";
/** A regular expression matching an integer */
static char regex_int[] = "^[+-]?[0-9]+$";
/** A regular expression matching a complex number (int or float) */
static char regex_cmp[] =
"^[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+)([eEdD][+-]?[0-9]+)?[ ]+[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+)([eEdD][+-]?[0-9]+)?$";
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve the value of a key in a FITS header
@param filename Name of the FITS file to browse
@param keyword Name of the keyword to find
@return pointer to statically allocated character string
Provide the name of a FITS file and a keyword to look for. The input
file is memory-mapped and the first keyword matching the requested one is
located. The value corresponding to this keyword is copied to a
statically allocated area, so do not modify it or free it.
The input keyword is first converted to upper case and expanded to
the HIERARCH scheme if given in the shortFITS notation.
This function is pretty fast due to the mmapping. Due to buffering
on most Unixes, it is possible to call many times this function in a
row on the same file and do not suffer too much from performance
problems. If the file contents are already in the cache, the file
will not be re-opened every time.
It is possible, though, to modify this function to perform several
searches in a row. See the source code.
Returns NULL in case the requested keyword cannot be found.
*/
/*----------------------------------------------------------------------------*/
char * qfits_query_hdr(char * filename, const char * keyword)
{
return qfits_query_ext(filename, keyword, 0);
}
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve the value of a keyin a FITS extension header.
@param filename name of the FITS file to browse.
@param keyword name of the FITS key to look for.
@param xtnum xtension number
@return pointer to statically allocated character string
Same as qfits_query_hdr but for extensions. xtnum starts from 1 to
the number of extensions. If xtnum is zero, this function is
strictly identical to qfits_query_hdr().
*/
/*----------------------------------------------------------------------------*/
char * qfits_query_ext(char * filename, const char * keyword, int xtnum)
{
char * exp_key ;
char * where ;
char * start ;
char * value ;
char test1, test2 ;
int i ;
int len ;
int different ;
int seg_start ;
int seg_size ;
long bufcount ;
size_t size ;
/* Bulletproof entries */
if (filename==NULL || keyword==NULL || xtnum<0) return NULL ;
/* Expand keyword */
exp_key = qfits_expand_keyword(keyword);
/*
* Find out offsets to the required extension
* Record the xtension start and stop offsets
*/
if (qfits_get_hdrinfo(filename, xtnum, &seg_start, &seg_size)==-1) {
return NULL ;
}
/*
* Get a hand on requested buffer
*/
start = falloc(filename, seg_start, &size);
if (start==NULL) return NULL ;
/*
* Look for keyword in header
*/
bufcount=0 ;
where = start ;
len = (int)strlen(exp_key);
while (1) {
different=0 ;
for (i=0 ; i<len ; i++) {
if (where[i]!=exp_key[i]) {
different++ ;
break ;
}
}
if (!different) {
/* Get 2 chars after keyword */
test1=where[len];
test2=where[len+1];
/* If first subsequent character is the equal sign, bingo. */
if (test1=='=') break ;
/* If subsequent char is equal sign, bingo */
if (test1==' ' && (test2=='=' || test2==' '))
break ;
}
/* Watch out for header end */
if ((where[0]=='E') &&
(where[1]=='N') &&
(where[2]=='D') &&
(where[3]==' ')) {
/* Detected header end */
fdealloc(start, seg_start, size) ;
return NULL ;
}
/* Forward one line */
where += 80 ;
bufcount += 80 ;
if (bufcount>seg_size) {
/* File is damaged or not FITS: bailout */
fdealloc(start, seg_start, size) ;
return NULL ;
}
}
/* Found the keyword, now get its value */
value = qfits_getvalue(where);
fdealloc(start, seg_start, size) ;
return value;
}
/*----------------------------------------------------------------------------*/
/**
@brief Counts the number of extensions in a FITS file
@param filename Name of the FITS file to browse.
@return int
Counts how many extensions are in the file. Returns 0 if no
extension is found, and -1 if an error occurred.
*/
/*----------------------------------------------------------------------------*/
int qfits_query_n_ext(char * filename)
{
return qfits_query(filename, QFITS_QUERY_N_EXT);
}
/*----------------------------------------------------------------------------*/
/**
@brief Counts the number of planes in a FITS extension.
@param filename Name of the FITS file to browse.
@param exnum Extensin number
@return int
Counts how many planes are in the extension. Returns 0 if no plane is found,
and -1 if an error occurred.
*/
/*----------------------------------------------------------------------------*/
int qfits_query_nplanes(char * filename, int extnum)
{
char * sval ;
int next ;
int naxes ;
int nplanes ;
/* Check file existence */
if (filename == NULL) return -1 ;
/* Check validity of extnum */
next = qfits_query_n_ext(filename) ;
if (extnum>next) {
qfits_error("invalid extension specified") ;
return -1 ;
}
/* Find the number of axes */
naxes = 0 ;
if ((sval = qfits_query_ext(filename, "NAXIS", extnum)) == NULL) {
qfits_error("missing key in header: NAXIS");
return -1 ;
}
naxes = atoi(sval) ;
/* Check validity of naxes */
if ((naxes < 2) || (naxes > 3)) return -1 ;
/* Two dimensions cube */
if (naxes == 2) nplanes = 1 ;
else {
/* For 3D cubes, get the third dimension size */
if ((sval = qfits_query_ext(filename, "NAXIS3", extnum))==NULL) {
qfits_error("missing key in header: NAXIS3");
return -1 ;
}
nplanes = atoi(sval);
if (nplanes < 1) nplanes = 0 ;
}
return nplanes ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Clean out a FITS string value.
@param s pointer to allocated FITS value string.
@return pointer to statically allocated character string
From a string FITS value like 'marvin o''hara', remove head and tail
quotes, replace double '' with simple ', trim blanks on each side,
and return the result in a statically allocated area.
Examples:
- ['o''hara'] becomes [o'hara]
- [' H '] becomes [H]
- ['1.0 '] becomes [1.0]
*/
/*----------------------------------------------------------------------------*/
#define PRETTY_STRING_STATICBUFS 8
char * qfits_pretty_string(char * s)
{
static char pretty_buf[PRETTY_STRING_STATICBUFS][81] ;
static int flip=0 ;
char * pretty ;
int i,j ;
/* bulletproof */
if (s==NULL) return NULL ;
/* Switch between static buffers */
pretty = pretty_buf[flip];
flip++ ;
if (flip==PRETTY_STRING_STATICBUFS)
flip=0 ;
pretty[0] = (char)0 ;
if (s[0]!='\'') return s ;
/* skip first quote */
i=1 ;
j=0 ;
/* trim left-side blanks */
while (s[i]==' ') {
if (i==(int)strlen(s)) break ;
i++ ;
}
if (i>=(int)(strlen(s)-1)) return pretty ;
/* copy string, changing double quotes to single ones */
while (i<(int)strlen(s)) {
if (s[i]=='\'') {
i++ ;
}
pretty[j]=s[i];
i++ ;
j++ ;
}
/* NULL-terminate the pretty string */
pretty[j+1]=(char)0;
/* trim right-side blanks */
j = (int)strlen(pretty)-1;
while (pretty[j]==' ') j-- ;
pretty[j+1]=(char)0;
return pretty;
}
#undef PRETTY_STRING_STATICBUFS
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is boolean
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is boolean.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_boolean(char * s)
{
if (s==NULL) return 0 ;
if (s[0]==0) return 0 ;
if ((int)strlen(s)>1) return 0 ;
if (s[0]=='T' || s[0]=='F') return 1 ;
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is an int.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is an integer.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_int(char * s)
{
regex_t re_int ;
int status ;
if (s==NULL) return 0 ;
if (s[0]==0) return 0 ;
if (regcomp(&re_int, &regex_int[0], REG_EXTENDED|REG_NOSUB)!=0) {
qfits_error("internal error: compiling int rule");
exit(-1);
}
status = regexec(&re_int, s, 0, NULL, 0) ;
regfree(&re_int) ;
return (status) ? 0 : 1 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is float.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is float.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_float(char * s)
{
regex_t re_float;
int status ;
if (s==NULL) return 0 ;
if (s[0]==0) return 0 ;
if (regcomp(&re_float, &regex_float[0], REG_EXTENDED|REG_NOSUB)!=0) {
qfits_error("internal error: compiling float rule");
exit(-1);
}
status = regexec(&re_float, s, 0, NULL, 0) ;
regfree(&re_float) ;
return (status) ? 0 : 1 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is complex.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is complex.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_complex(char * s)
{
regex_t re_cmp ;
int status ;
if (s==NULL) return 0 ;
if (s[0]==0) return 0 ;
if (regcomp(&re_cmp, &regex_cmp[0], REG_EXTENDED|REG_NOSUB)!=0) {
qfits_error("internal error: compiling complex rule");
exit(-1);
}
status = regexec(&re_cmp, s, 0, NULL, 0) ;
regfree(&re_cmp) ;
return (status) ? 0 : 1 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is string.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is a string.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_string(char * s)
{
if (s==NULL) return 0 ;
if (s[0]=='\'') return 1 ;
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Identify the type of a FITS value given as a string.
@param s FITS value as a string
@return integer naming the FITS type
Returns the following value:
- QFITS_UNKNOWN (0) for an unknown type.
- QFITS_BOOLEAN (1) for a boolean type.
- QFITS_INT (2) for an integer type.
- QFITS_FLOAT (3) for a floating-point type.
- QFITS_COMPLEX (4) for a complex number.
- QFITS_STRING (5) for a FITS string.
*/
/*----------------------------------------------------------------------------*/
int qfits_get_type(char * s)
{
if (s==NULL) return QFITS_UNKNOWN ;
if (qfits_is_boolean(s)) return QFITS_BOOLEAN ;
if (qfits_is_int(s)) return QFITS_INT ;
if (qfits_is_float(s)) return QFITS_FLOAT ;
if (qfits_is_complex(s)) return QFITS_COMPLEX ;
return QFITS_STRING ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve offset to start and size of a header in a FITS file.
@param filename Name of the file to examine
@param xtnum Extension number (0 for main)
@param seg_start Segment start in bytes (output)
@param seg_size Segment size in bytes (output)
@return int 0 if Ok, -1 otherwise.
This function retrieves the two most important informations about
a header in a FITS file: the offset to its beginning, and the size
of the header in bytes. Both values are returned in the passed
pointers to ints. It is Ok to pass NULL for any pointer if you do
not want to retrieve the associated value.
You must provide an extension number for the header, 0 meaning the
main header in the file.
*/
/*----------------------------------------------------------------------------*/
int qfits_get_hdrinfo(
char * filename,
int xtnum,
int * seg_start,
int * seg_size)
{
if (filename==NULL || xtnum<0 || (seg_start==NULL && seg_size==NULL)) {
return -1 ;
}
if (seg_start!=NULL) {
*seg_start = qfits_query(filename, QFITS_QUERY_HDR_START | xtnum);
if (*seg_start<0)
return -1 ;
}
if (seg_size!=NULL) {
*seg_size = qfits_query(filename, QFITS_QUERY_HDR_SIZE | xtnum);
if (*seg_size<0)
return -1 ;
}
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve offset to start and size of a data section in a file.
@param filename Name of the file to examine.
@param xtnum Extension number (0 for main).
@param seg_start Segment start in bytes (output).
@param seg_size Segment size in bytes (output).
@return int 0 if Ok, -1 otherwise.
This function retrieves the two most important informations about
a data section in a FITS file: the offset to its beginning, and the size
of the section in bytes. Both values are returned in the passed
pointers to ints. It is Ok to pass NULL for any pointer if you do
not want to retrieve the associated value.
You must provide an extension number for the header, 0 meaning the
main header in the file.
*/
/*----------------------------------------------------------------------------*/
int qfits_get_datinfo(
char * filename,
int xtnum,
int * seg_start,
int * seg_size)
{
if (filename==NULL || xtnum<0 || (seg_start==NULL && seg_size==NULL)) {
return -1 ;
}
if (seg_start!=NULL) {
*seg_start = qfits_query(filename, QFITS_QUERY_DAT_START | xtnum);
if (*seg_start<0)
return -1 ;
}
if (seg_size!=NULL) {
*seg_size = qfits_query(filename, QFITS_QUERY_DAT_SIZE | xtnum);
if (*seg_size<0)
return -1 ;
}
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Query a card in a FITS (main) header by a given key
@param filename Name of the FITS file to check.
@param keyword Where to read a card in the header.
@return Allocated string containing the card or NULL
*/
/*----------------------------------------------------------------------------*/
char * qfits_query_card(
char * filename,
char * keyword)
{
char * exp_key ;
int fd ;
char * buf ;
char * buf2 ;
char * where ;
int hs ;
char * card ;
/* Bulletproof entries */
if (filename==NULL || keyword==NULL) return NULL ;
/* Expand keyword */
exp_key = qfits_expand_keyword(keyword) ;
/* Memory-map the FITS header of the input file */
qfits_get_hdrinfo(filename, 0, NULL, &hs) ;
if (hs < 1) {
qfits_error("error getting FITS header size for %s", filename);
return NULL ;
}
fd = open(filename, O_RDWR) ;
if (fd == -1) return NULL ;
buf = (char*)mmap(0,
hs,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0) ;
if (buf == (char*)-1) {
perror("mmap") ;
close(fd) ;
return NULL ;
}
/* Apply search for the input keyword */
buf2 = malloc(hs+1) ;
memcpy(buf2, buf, hs) ;
buf2[hs] = (char)0 ;
where = buf2 ;
do {
where = strstr(where, exp_key);
if (where == NULL) {
close(fd);
munmap(buf,hs);
free(buf2) ;
return NULL ;
}
if ((where-buf2)%80) where++ ;
} while ((where-buf2)%80) ;
where = buf + (int)(where - buf2) ;
/* Create the card */
card = malloc(81*sizeof(char)) ;
strncpy(card, where, 80) ;
card[80] = (char)0 ;
/* Free and return */
close(fd) ;
munmap(buf, hs) ;
free(buf2) ;
return card ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Replace a card in a FITS (main) header by a given card
@param filename Name of the FITS file to modify.
@param keyword Where to substitute a card in the header.
@param substitute What to replace the line with.
@return int 0 if Ok, -1 otherwise
Replaces a whole card (80 chars) in a FITS header by a given FITS
line (80 chars). The replacing line is assumed correctly formatted
and containing at least 80 characters. The file is modified: it must
be accessible in read/write mode.
The input keyword is first converted to upper case and expanded to
the HIERARCH scheme if given in the shortFITS notation.
Returns 0 if everything worked Ok, -1 otherwise.
*/
/*----------------------------------------------------------------------------*/
int qfits_replace_card(
char * filename,
const char * keyword,
char * substitute)
{
char * exp_key ;
int fd ;
char * buf ;
char * buf2 ;
char * where ;
int hs ;
/* Bulletproof entries */
if (filename==NULL || keyword==NULL || substitute==NULL) return -1 ;
/* Expand keyword */
exp_key = qfits_expand_keyword(keyword);
/*
* Memory-map the FITS header of the input file
*/
qfits_get_hdrinfo(filename, 0, NULL, &hs) ;
if (hs < 1) {
qfits_error("error getting FITS header size for %s", filename);
return -1 ;
}
fd = open(filename, O_RDWR) ;
if (fd == -1) {
return -1 ;
}
buf = (char*)mmap(0,
hs,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0) ;
if (buf == (char*)-1) {
perror("mmap") ;
close(fd) ;
return -1 ;
}
/* Apply search and replace for the input keyword lists */
buf2 = malloc(hs+1) ;
memcpy(buf2, buf, hs) ;
buf2[hs] = (char)0 ;
where = buf2 ;
do {
where = strstr(where, exp_key);
if (where == NULL) {
close(fd);
munmap(buf,hs);
free(buf2) ;
return -1 ;
}
if ((where-buf2)%80) where++ ;
} while ((where-buf2)%80) ;
where = buf + (int)(where - buf2) ;
/* Replace current placeholder by blanks */
memset(where, ' ', 80);
/* Copy substitute into placeholder */
memcpy(where, substitute, strlen(substitute));
close(fd) ;
munmap(buf, hs) ;
free(buf2) ;
return 0 ;
}
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,261 @@
/*----------------------------------------------------------------------------*/
/**
@file t_iso8601.c
@author N. Devillard
@date Aug 1999
@version $Revision: 1.6 $
@brief Get date/time, possibly in ISO8601 format.
This module contains various utilities to get the current date/time,
and possibly format it according to the ISO 8601 format.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: t_iso8601.c,v 1.6 2004/01/20 11:47:59 yjung Exp $
$Author: yjung $
$Date: 2004/01/20 11:47:59 $
$Revision: 1.6 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/time.h>
#include "t_iso8601.h"
/*-----------------------------------------------------------------------------
Macros
-----------------------------------------------------------------------------*/
/** Get century from a date in long format */
#define GET_CENTURY(d) (int) ( (d) / 1000000L)
/** Get century year from a date in long format */
#define GET_CCYEAR(d) (int) ( (d) / 10000L)
/** Get year from a date in long format */
#define GET_YEAR(d) (int) (((d) % 1000000L) / 10000L)
/** Get month from a date in long format */
#define GET_MONTH(d) (int) (((d) % 10000L) / 100)
/** Get day from a date in long format */
#define GET_DAY(d) (int) ( (d) % 100)
/** Get hours from a date in long format */
#define GET_HOUR(t) (int) ( (t) / 1000000L)
/** Get minutes from a date in long format */
#define GET_MINUTE(t) (int) (((t) % 1000000L) / 10000L)
/** Get seconds from a date in long format */
#define GET_SECOND(t) (int) (((t) % 10000L) / 100)
/** Get centi-seconds from a date in long format */
#define GET_CENTI(t) (int) ( (t) % 100)
/** Make date in long format from its components */
#define MAKE_DATE(c,y,m,d) (long) (c) * 1000000L + \
(long) (y) * 10000L + \
(long) (m) * 100 + (d)
/** Make time in long format from its components */
#define MAKE_TIME(h,m,s,c) (long) (h) * 1000000L + \
(long) (m) * 10000L + \
(long) (s) * 100 + (c)
/** Interval values, specified in centiseconds */
#define INTERVAL_CENTI 1
#define INTERVAL_SEC 100
#define INTERVAL_MIN 6000
#define INTERVAL_HOUR 360000L
#define INTERVAL_DAY 8640000L
/*-----------------------------------------------------------------------------
Private to this module
-----------------------------------------------------------------------------*/
static long timer_to_date(time_t time_secs) ;
static long timer_to_time(time_t time_secs) ;
/*-----------------------------------------------------------------------------
Static Function code
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current date as a long (CCYYMMDD).
@return The current date as a long number.
Returns the current date as a long value (CCYYMMDD). Since most
system clocks do not return a century, this function assumes that
all years 80 and above are in the 20th century, and all years 00 to
79 are in the 21st century. For best results, consume before 1 Jan
2080.
Example: 19 Oct 2000 is returned as 20001019
*/
/*----------------------------------------------------------------------------*/
long qfits_date_now (void)
{
return (timer_to_date (time (NULL)));
}
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current time as a long (HHMMSSCC).
@return The current time as a long number.
Returns the current time as a long value (HHMMSSCC). If the system
clock does not return centiseconds, these are set to zero.
Example: 15:36:12.84 is returned as 15361284
*/
/*----------------------------------------------------------------------------*/
long qfits_time_now(void)
{
struct timeval time_struct;
gettimeofday (&time_struct, 0);
return (timer_to_time (time_struct.tv_sec)
+ time_struct.tv_usec / 10000);
}
/*----------------------------------------------------------------------------*/
/**
@brief Converts a timer value to a date.
@param time_secs Current time definition in seconds.
@return Current date as a long (CCYYMMDD).
Converts the supplied timer value into a long date value. Dates are
stored as long values: CCYYMMDD. If the supplied value is zero,
returns zero. If the supplied value is out of range, returns 1
January, 1970 (19700101). The timer value is assumed to be UTC
(GMT).
*/
/*----------------------------------------------------------------------------*/
static long timer_to_date(time_t time_secs)
{
struct tm *time_struct;
if (time_secs == 0) {
return 0;
} else {
/* Convert into a long value CCYYMMDD */
time_struct = localtime (&time_secs);
if (time_struct) {
time_struct-> tm_year += 1900;
return (MAKE_DATE ( time_struct-> tm_year / 100,
time_struct-> tm_year % 100,
time_struct-> tm_mon + 1,
time_struct-> tm_mday));
} else {
return (19700101);
}
}
}
/*----------------------------------------------------------------------------*/
/**
@brief Convert a timer value to a time.
@param time_secs Current time definition in seconds.
@return Current time as a long.
Converts the supplied timer value into a long time value. Times are
stored as long values: HHMMSS00. Since the timer value does not
hold centiseconds, these are set to zero. If the supplied value was
zero or invalid, returns zero. The timer value is assumed to be UTC
(GMT).
*/
/*----------------------------------------------------------------------------*/
static long timer_to_time(time_t time_secs)
{
struct tm *time_struct;
if (time_secs == 0) {
return 0;
} else {
/* Convert into a long value HHMMSS00 */
time_struct = localtime (&time_secs);
if (time_struct) {
return (MAKE_TIME (time_struct-> tm_hour,
time_struct-> tm_min,
time_struct-> tm_sec,
0));
} else {
return 0;
}
}
}
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current date as a static string.
@return Pointer to statically allocated string.
Build and return a string containing the date of today in ISO8601
format. The returned pointer points to a statically allocated string
in the function, so no need to free it.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_date_iso8601(void)
{
static char date_iso8601[20] ;
long curdate ;
curdate = qfits_date_now() ;
sprintf(date_iso8601, "%04d-%02d-%02d",
GET_CCYEAR(curdate),
GET_MONTH(curdate),
GET_DAY(curdate));
return date_iso8601 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current date and time as a static string.
@return Pointer to statically allocated string
Build and return a string containing the date of today and the
current time in ISO8601 format. The returned pointer points to a
statically allocated string in the function, so no need to free it.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_datetime_iso8601(void)
{
static char date_iso8601[20] ;
long curdate ;
long curtime ;
curdate = qfits_date_now() ;
curtime = qfits_time_now() ;
sprintf(date_iso8601, "%04d-%02d-%02dT%02d:%02d:%02d",
GET_CCYEAR(curdate),
GET_MONTH(curdate),
GET_DAY(curdate),
GET_HOUR(curtime),
GET_MINUTE(curtime),
GET_SECOND(curtime));
return date_iso8601 ;
}
#ifdef TEST
int main(int argc, char *argv[])
{
printf( "date now %ld\n"
"time now %ld\n"
"date iso8601 %s\n"
"date/time iso 8601 %s\n",
qfits_date_now(),
qfits_time_now(),
qfits_get_date_iso8601(),
qfits_get_datetime_iso8601());
return 0 ;
}
#endif
/* vim: set ts=4 et sw=4 tw=75 */

2405
qfits/src/tfits.c 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
/* Library version */
static const char *
_qfits_version = "5.4.0" ;
const char * qfits_version(void)
{
return _qfits_version ;
}

1449
qfits/src/xmemory.c 100644

File diff suppressed because it is too large Load Diff

853
qfits/sysconf.c 100644
View File

@ -0,0 +1,853 @@
/*----------------------------------------------------------------------------*/
/**
@file sysconf.c
@author Nicolas Devillard
@date February 2001
@version $Revision: 1.33 $
@brief configure-like in C.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: sysconf.c,v 1.33 2005/02/24 15:59:59 yjung Exp $
$Author: yjung $
$Date: 2005/02/24 15:59:59 $
$Revision: 1.33 $
*/
/*---------------------------------------------------------------------------
Includes
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAXSTRSZ 512
#define MACROS_FILE "config.make"
#define HEADER_FILE "config.h"
#define PREFIX_DEFAULT "/usr/local"
#define COMPILER_AUTO 0
#define COMPILER_CC 1
#define COMPILER_GCC 2
#define XMEMDEBUG " -DXMEMORY_DEBUG=1"
/* Global variable */
struct {
/* List of supported OS's */
enum {
os_linux,
os_cygwin,
os_hp08,
os_hp09,
os_hp10,
os_hp11,
os_solaris,
os_irix,
os_aix,
os_dec,
os_bsd,
os_darwin
} local_os ;
char sysname[MAXSTRSZ];
char release[MAXSTRSZ];
char machine[MAXSTRSZ];
/* Bits per byte on this machine */
int bits_per_byte ;
/* Big endian machine? */
int big_endian ;
/* x86 architecture? */
int arch_x86 ;
/* CPU type: 386, 486, 586, 686 */
int cpu_x86 ;
/* Compile with debug options on */
int debug_compile ;
/* Compile with warnings on */
int lint_compile ;
/* Compiler type: native cc or gcc */
int compiler ;
/* Compile with threads */
int with_threads ;
/* Number of detected CPUs */
int ncpus ;
/* Compile static library */
int lib_static ;
/* Compile dynamic library */
int lib_dynamic ;
/* Prefix for installation */
char * prefix ;
/* With or without xmemory handling */
int xmemory_mode ;
/* Maximum number of pointers allowed */
int max_ptrs ;
} config ;
/*
* Check that all files present in the list of names are
* somewhere present in the list of paths.
*/
int config_findfiles(paths, names)
char ** paths ;
char ** names ;
{
struct stat sta ;
char spath[MAXSTRSZ];
int i, j ;
int nfound ;
/* Loop on all paths */
i=0 ;
while (paths[i]) {
printf("searching in %s...\n", paths[i]);
/* Loop on all file names */
j=0 ;
nfound=0 ;
while (names[j]) {
sprintf(spath, "%s/%s", paths[i], names[j]);
if (stat(spath, &sta)==0) {
nfound++ ;
}
j++ ;
}
if (j==nfound) {
printf("found in %s\n", paths[i]);
return i ;
}
i++ ;
}
return -1 ;
}
/* Guess local OS name and potentially release number */
void detect_config()
{
struct utsname name ;
int i ;
unsigned char c ;
int x ;
if (config.sysname[0]==0) {
printf("detecting local OS............. ");
/* Get machine OS type and release number */
if (uname(&name)==-1) {
printf("error calling uname\n");
exit(-1);
}
printf("%s %s", name.sysname, name.release);
strcpy(config.sysname, name.sysname);
strcpy(config.release, name.release);
strcpy(config.machine, name.machine);
} else {
printf("forcing config for OS.......... %s %s",
config.sysname,
config.release);
}
/* Lowercase everything */
i=0 ;
while(config.sysname[i]!=0) {
config.sysname[i] = tolower(config.sysname[i]);
i++ ;
}
i=0 ;
while(config.release[i]!=0) {
config.release[i] = tolower(config.release[i]);
i++ ;
}
/* Switch on OS type and release number */
if (strstr(config.sysname, "linux")!=NULL) {
config.local_os = os_linux ;
printf(" - linux\n");
} else if (strstr(config.sysname, "cygwin")!=NULL) {
config.local_os = os_cygwin ;
printf(" - cygwin\n");
} else if (strstr(config.sysname, "hp")!=NULL) {
if (strstr(config.release, "8.")!=NULL) {
config.local_os = os_hp08 ;
printf(" - hpux_08\n");
} else if (strstr(config.release, "9.")!=NULL) {
config.local_os = os_hp09 ;
printf(" - hpux_09\n");
} else if (strstr(config.release, "10.")!=NULL) {
config.local_os = os_hp10 ;
printf(" - hpux_10\n");
} else if (strstr(config.release, "11.")!=NULL) {
config.local_os = os_hp11 ;
printf(" - hpux_11\n");
}
} else if ((strstr(config.sysname, "sun")!=NULL) ||
(strstr(config.sysname, "solaris")!=NULL)) {
config.local_os = os_solaris ;
printf(" - solaris\n");
} else if (strstr(config.sysname, "irix")!=NULL) {
config.local_os = os_irix ;
printf(" - irix\n");
} else if (strstr(config.sysname, "aix")!=NULL) {
config.local_os = os_aix ;
printf(" - aix\n");
} else if (strstr(config.sysname, "osf")!=NULL) {
config.local_os = os_dec ;
printf(" - osf/1\n");
} else if (strstr(config.sysname, "bsd")!=NULL) {
config.local_os = os_bsd ;
printf(" - %s\n", config.sysname);
} else if (strstr(config.sysname, "darwin")!=NULL) {
config.local_os = os_darwin ;
printf(" - %s\n", config.sysname);
} else {
printf("cannot identify your OS\n");
printf("Use the option --os=NAME to force an OS type\n");
exit(-1);
}
/* Find out about x86 architectures */
if ((config.machine[0]=='i') && (strstr(config.machine, "86")!=NULL)) {
config.arch_x86 = 1 ;
config.cpu_x86 = atoi(config.machine+1) ;
printf("detected x86 architecture...... %d\n", config.cpu_x86);
} else {
config.arch_x86 = 0 ;
printf("detected x86 architecture...... no\n");
}
/* Compute number of bits in a byte on this machine */
printf("computing bits per byte........ ");
c=1 ; i=0 ;
while (c) {
c<<=1 ; i++ ;
}
config.bits_per_byte = i ;
printf("%d\n", i);
/* Detect endian-ness */
printf("detecting byte-order........... ");
x = 1 ;
x = (*(char*)&x) ;
config.big_endian = !x ;
if (config.big_endian) {
printf("big endian (motorola)\n");
} else {
printf("little endian (intel)\n");
}
return ;
}
/* Locate a program in the user's PATH */
int locate_program(pname)
char * pname ;
{
int i, j, lg;
char * path ;
char buf[MAXSTRSZ];
path = getenv("PATH");
if (path!=NULL) {
for (i=0; path[i]; ) {
for (j=i ; (path[j]) && (path[j]!=':') ; j++);
lg = j - i;
strncpy(buf, path + i, lg);
if (lg == 0) buf[lg++] = '.';
buf[lg++] = '/';
strcpy(buf + lg, pname);
if (access(buf, X_OK) == 0) {
printf("using [%s]\n", buf);
return 1 ;
}
buf[0] = 0;
i = j;
if (path[i] == ':') i++ ;
}
} else {
/* No PATH variable: abort with an error */
return -1 ;
}
/* If the buffer is still empty, the command was not found */
if (buf[0] == 0) return 0 ;
/* Otherwise Ok */
return 1 ;
}
void make_config_make()
{
FILE * sysc ;
/* Set compiler name */
printf("looking for a C compiler....... ");
if (getenv("PATH")==NULL) {
printf("error: undefined PATH variable, cannot locate a compiler\n");
exit(-1) ;
}
/* Open output sysconf */
if ((sysc=fopen(MACROS_FILE, "w"))==NULL) {
printf("cannot create %s: aborting compilation", MACROS_FILE);
exit(-1) ;
}
/* In automatic mode, find out which compiler to use */
if (config.compiler==COMPILER_AUTO) {
switch (config.local_os) {
/* Use gcc under Linux, BSD, Cygwin & IRIX */
case os_linux:
case os_cygwin:
case os_bsd:
case os_irix:
config.compiler = COMPILER_GCC ;
break ;
/* All others use 'cc' (default) */
default:
config.compiler = COMPILER_CC ;
break ;
}
}
/* Make sure the compiler can be found */
if (config.compiler==COMPILER_CC) {
if (locate_program("cc")!=1) {
printf("cannot locate cc\n");
/* Try out with gcc */
config.compiler = COMPILER_GCC ;
}
}
if (config.compiler==COMPILER_GCC) {
if (locate_program("gcc")!=1) {
printf("cannot locate gcc\n");
exit(-1);
}
}
/* Set compiler name and cflags */
switch (config.compiler) {
case COMPILER_CC:
fprintf(sysc, "CC = cc\n");
fprintf(sysc, "CFLAGS = ");
if (config.xmemory_mode == 0) {
fprintf(sysc, "-DXMEMORY_MODE=%d ", config.xmemory_mode) ;
fprintf(sysc, "-DXMEMORY_MAXPTRS=1 ") ;
} else if (config.xmemory_mode == 1) {
fprintf(sysc, "-DXMEMORY_MODE=%d ", config.xmemory_mode) ;
fprintf(sysc, "-DXMEMORY_MAXPTRS=1 ") ;
} else if (config.xmemory_mode == 2) {
fprintf(sysc, "-DXMEMORY_MODE=%d ", config.xmemory_mode) ;
if (config.max_ptrs > 0) {
fprintf(sysc, "-DXMEMORY_MAXPTRS=%d ", config.max_ptrs) ;
}
} else if (config.xmemory_mode < 0) {
if (config.max_ptrs > 0) {
fprintf(sysc, "-DXMEMORY_MAXPTRS=%d ", config.max_ptrs) ;
}
}
switch (config.local_os) {
case os_hp08:
case os_hp09:
case os_hp10:
if (config.with_threads) {
printf("threads not supported on this platform\n");
}
if (config.debug_compile) {
fprintf(sysc, "-Ae -g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-Ae -O\n");
}
fprintf(sysc, "RELOC = +z\n");
fprintf(sysc, "SHARED = -b\n");
break ;
case os_hp11:
if (config.with_threads) {
fprintf(sysc, "-lpthread ");
}
if (config.debug_compile) {
fprintf(sysc, "-g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-O\n");
}
fprintf(sysc, "RELOC = +z\n");
fprintf(sysc, "SHARED = -b\n");
break ;
case os_solaris:
if (config.with_threads) {
fprintf(sysc, "-mt -lpthread ");
}
if (config.debug_compile) {
fprintf(sysc, "-g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-xO5\n");
}
fprintf(sysc, "RELOC = -G\n");
fprintf(sysc, "SHARED = -G\n");
break ;
case os_dec:
if (config.with_threads) {
printf("threads not supported on this platform\n");
}
if (config.debug_compile) {
fprintf(sysc, "-g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-O\n");
}
fprintf(sysc, "RELOC =\n");
fprintf(sysc, "SHARED = -shared -expect_unresolved \"*\"\n");
break ;
case os_irix:
case os_aix:
case os_bsd:
if (config.with_threads) {
printf("threads not supported on this platform\n");
}
if (config.debug_compile) {
fprintf(sysc, "-g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-O\n");
}
fprintf(sysc, "RELOC =\n");
fprintf(sysc, "SHARED =\n");
break ;
case os_cygwin:
case os_linux:
/* cc with Linux? Why not! */
if (config.with_threads) {
fprintf(sysc, "-pthread ");
}
if (config.debug_compile) {
fprintf(sysc, "-g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-O3\n");
}
fprintf(sysc, "RELOC = -fpic\n");
fprintf(sysc, "SHARED = -shared\n");
break ;
case os_darwin:
/* Darwin uses gcc but calls it 'cc' */
if (config.with_threads) {
fprintf(sysc, "-pthread ");
}
if (config.debug_compile) {
fprintf(sysc, "-g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-O3\n");
}
fprintf(sysc, "RELOC = -fPIC\n");
fprintf(sysc, "SHARED = -shared\n");
break ;
default:
printf("error: unsupported OS\n");
exit(-1) ;
}
break ;
case COMPILER_GCC:
fprintf(sysc, "CC = gcc\n");
fprintf(sysc, "CFLAGS = ");
if (config.xmemory_mode == 0) {
fprintf(sysc, "-DXMEMORY_MODE=%d ", config.xmemory_mode) ;
fprintf(sysc, "-DXMEMORY_MAXPTRS=1 ") ;
} else if (config.xmemory_mode == 1) {
fprintf(sysc, "-DXMEMORY_MODE=%d ", config.xmemory_mode) ;
fprintf(sysc, "-DXMEMORY_MAXPTRS=1 ") ;
} else if (config.xmemory_mode == 2) {
fprintf(sysc, "-DXMEMORY_MODE=%d ", config.xmemory_mode) ;
if (config.max_ptrs > 0) {
fprintf(sysc, "-DXMEMORY_MAXPTRS=%d ", config.max_ptrs) ;
}
} else if (config.xmemory_mode < 0) {
if (config.max_ptrs > 0) {
fprintf(sysc, "-DXMEMORY_MAXPTRS=%d ", config.max_ptrs) ;
}
}
if (config.with_threads) {
fprintf(sysc, "-pthread ");
}
if (config.lint_compile) {
fprintf(sysc, " -Wall -pedantic ");
}
if (config.debug_compile) {
fprintf(sysc, "-g%s\n", XMEMDEBUG);
} else {
fprintf(sysc, "-O3\n");
}
if (config.local_os != os_cygwin)
fprintf(sysc, "RELOC = -fPIC -DPIC\n");
fprintf(sysc, "SHARED = -shared\n");
break ;
default:
printf("error in compiler option switch: aborting\n");
exit(-1);
break ;
}
if (config.debug_compile) {
printf(" in debug mode\n");
} else {
printf(" all optimizations on\n");
}
if (config.lint_compile) {
printf(" with all warnings\n");
}
/* LFLAGS */
fprintf(sysc, "LFLAGS = ");
switch (config.local_os) {
case os_hp10:
case os_hp11:
fprintf(sysc, "-Wl,+vnocompatwarnings ");
break ;
default:
break ;
}
fprintf(sysc, "\n");
/* DYNSUF */
switch (config.local_os) {
case os_hp08:
case os_hp09:
case os_hp10:
case os_hp11:
fprintf(sysc, "DYNSUF = sl\n");
break ;
case os_darwin:
fprintf(sysc, "DYNSUF = so\n");
break ;
default:
fprintf(sysc, "DYNSUF = so\n");
break ;
}
/* STRIP */
if (config.debug_compile) {
fprintf(sysc, "STRIP = true\n");
} else {
fprintf(sysc, "STRIP = strip\n");
}
/* TARGETS */
fprintf(sysc, "TARGETS =");
printf("static library................. %s\n",
config.lib_static ? "yes" : "no");
if (config.lib_static) {
fprintf(sysc, " static");
}
printf("shared library................. %s\n",
config.lib_dynamic ? "yes" : "no");
if (config.lib_dynamic) {
fprintf(sysc, " dynamic");
}
fprintf(sysc,"\n");
/* PREFIX */
fprintf(sysc, "prefix = %s\n",
config.prefix ? config.prefix : PREFIX_DEFAULT);
printf("setting installation prefix as: [%s]\n",
config.prefix ? config.prefix : PREFIX_DEFAULT);
fclose(sysc);
}
void make_config_h()
{
FILE * out ;
out = fopen(HEADER_FILE, "w");
if (out==NULL) {
printf("cannot create header file %s: aborting", HEADER_FILE);
return ;
}
fprintf(out,
"/* This file automatically generated */\n"
"#ifndef _CONFIG_H_\n"
"#define _CONFIG_H_\n"
"\n"
"%s",
config.big_endian ? "#define WORDS_BIGENDIAN 1\n" : "\n"
);
/* Generate SIZEOF macros for basic types */
printf("detecting basic size types\n");
fprintf(out,
"#define SIZEOF_CHAR %d\n"
"#define SIZEOF_SHORT %d\n"
"#define SIZEOF_INT %d\n"
"#define SIZEOF_LONG %d\n"
"#define SIZEOF_FLOAT %d\n"
"#define SIZEOF_DOUBLE %d\n",
sizeof(char),
sizeof(short),
sizeof(int),
sizeof(long),
sizeof(float),
sizeof(double));
printf(
"sizeof(char)................... %d\n"
"sizeof(short).................. %d\n"
"sizeof(int).................... %d\n"
"sizeof(long)................... %d\n"
"sizeof(float).................. %d\n"
"sizeof(double)................. %d\n",
sizeof(char),
sizeof(short),
sizeof(int),
sizeof(long),
sizeof(float),
sizeof(double));
/* Do not output CHAR_BIT on AIX */
if (config.local_os!=os_aix) {
fprintf(out,
"\n"
"#ifndef CHAR_BIT\n"
"#define CHAR_BIT\t%d\n"
"#endif\n"
"\n\n",
config.bits_per_byte);
}
if (config.arch_x86) {
fprintf(out, "#define CPU_X86 %d\n", config.cpu_x86);
}
if (config.with_threads) {
fprintf(out, "#define HAS_PTHREADS 1\n");
}
fprintf(out, "\n");
switch (config.local_os) {
case os_hp08:
case os_hp09:
case os_hp10:
case os_hp11:
fprintf(out, "#define OS_HPUX 1\n");
break ;
case os_linux:
fprintf(out, "#define OS_LINUX 1\n");
break ;
case os_cygwin:
fprintf(out, "#define OS_CYGWIN 1\n");
break ;
case os_irix:
fprintf(out, "#define OS_IRIX 1\n");
break ;
case os_aix:
fprintf(out, "#define OS_AIX 1\n");
break ;
case os_dec:
fprintf(out, "#define OS_DEC 1\n");
break ;
case os_solaris:
fprintf(out, "#define OS_SOLARIS 1\n");
break ;
case os_bsd:
fprintf(out, "#define OS_BSD 1\n");
break ;
case os_darwin:
fprintf(out, "#define OS_DARWIN 1\n");
break ;
default:
fprintf(out, "#define OS_UNKNOWN 1\n");
break ;
}
fprintf(out, "#endif\n");
fclose(out);
printf("done\n");
return ;
}
void help()
{
printf(
"\n\n"
"***** qfits configure help\n"
"Use: configure [options]\n"
"\n"
"options are:\n"
"\t--debug Compile modules in debug mode\n"
"\t--help Get this help\n"
"\n"
"\t--with-cc Force compilation with local cc\n"
"\t--with-gcc Force compilation with gcc\n"
"\n"
"\t--enable-static Compile static library (default)\n"
"\t--enable-shared Compile shared library\n"
"\t--disable-shared Do not compile shared library (default)\n"
"\t--disable-static Do not compile static library\n"
"\n"
"\t--xmemory-mode=M M=0 switches off the internal xmemory\n"
"\t handling, M=1 exits the program\n"
"\t whenever a memory allocation fails,\n"
"\t M=2 switches on the internal xmemory\n"
"\t handling.\n"
"\n"
"\t--max-ptrs=MAXPTRS Set MAXPTRS as the maximum number of\n"
"\t pointers allowed\n"
"\n"
"\t--prefix=PATH Install in PATH (must be absolute)\n"
"\t--mt Compile with multithreading support\n"
"\n"
"options specific to compilation with gcc (for developers):\n"
"\t--lint Compile with -Wall\n"
"\n"
"If your platform is not or incorrectly recognized, you\n"
"can force a given configuration with this option:\n"
"\n"
"\t--os=NAME Where NAME is one of the following:\n"
"\n"
"\tlinux - Linux systems (any processor type)\n"
"\tcygwin - Cygwin (UNIX environment for Windows)\n"
"\thp08 - HPUX version 8.x\n"
"\thp09 - HPUX version 9.x\n"
"\thp10 - HPUX version 10.x\n"
"\thp11 - HPUX version 11.x\n"
"\tirix - SGI IRIX64\n"
"\taix - IBM AIX (any version)\n"
"\tdec - Dec OSF/1 or Tru64 Unix\n"
"\tsolaris - Sun Solaris >=2.5\n"
"\tbsd - BSD compatible Unix\n"
"\tdarwin - Darwin (BSD compatible on Mac)\n"
"\n"
);
}
int main(argc, argv)
int argc ;
char * argv[];
{
char sysname[MAXSTRSZ];
char * sval ;
int i ;
config.debug_compile = 0;
config.lint_compile = 0 ;
config.compiler = COMPILER_AUTO ;
config.with_threads = 0 ;
config.lib_static = 1 ;
config.lib_dynamic = 0 ;
config.prefix = NULL ;
config.max_ptrs = -1 ;
config.xmemory_mode = -1 ;
memset(config.sysname, 0, MAXSTRSZ);
memset(config.release, 0, MAXSTRSZ);
memset(config.machine, 0, MAXSTRSZ);
for (i=0 ; i<argc ; i++) {
if (!strcmp(argv[i], "--help")) {
help() ;
return 1 ;
} else if (!strcmp(argv[i], "--debug")) {
config.debug_compile = 1 ;
} else if (!strcmp(argv[i], "--with-cc")) {
config.compiler = COMPILER_CC ;
} else if (!strcmp(argv[i], "--with-gcc")) {
config.compiler = COMPILER_GCC ;
} else if (!strcmp(argv[i], "--lint")) {
config.lint_compile = 1 ;
} else if (!strcmp(argv[i], "--mt")) {
config.with_threads=1 ;
} else if (!strcmp(argv[i], "--enable-shared")) {
config.lib_dynamic = 1;
} else if (!strcmp(argv[i], "--disable-shared")) {
config.lib_dynamic = 0;
} else if (!strcmp(argv[i], "--enable-static")) {
config.lib_static = 1;
} else if (!strcmp(argv[i], "--disable-static")) {
config.lib_static = 0;
} else if (!strncmp(argv[i], "--prefix=", 9)) {
config.prefix = strchr(argv[i], '=') + 1 ;
} else if (!strncmp(argv[i], "--max-ptrs=", 11)) {
sval = strchr(argv[i], '=') + 1 ;
config.max_ptrs = (int)atoi(sval) ;
} else if (!strncmp(argv[i], "--xmemory-mode=", 15)) {
sval = strchr(argv[i], '=') + 1 ;
config.xmemory_mode = (int)atoi(sval) ;
} else if (!strncmp(argv[i], "--os=", 5)) {
strcpy(sysname, argv[i]+5);
if (!strcmp(sysname, "linux")) {
strcpy(config.sysname, "Linux");
} else if (!strcmp(sysname, "cygwin")) {
strcpy(config.sysname, "CYGWIN");
} else if (!strcmp(sysname, "hp08")) {
strcpy(config.sysname, "HPUX");
strcpy(config.release, "8.x");
} else if (!strcmp(sysname, "hp09")) {
strcpy(config.sysname, "HPUX");
strcpy(config.release, "9.x");
} else if (!strcmp(sysname, "hp10")) {
strcpy(config.sysname, "HPUX");
strcpy(config.release, "10.x");
} else if (!strcmp(sysname, "hp11")) {
strcpy(config.sysname, "HPUX");
strcpy(config.release, "11.x");
} else if (!strcmp(sysname, "irix")) {
strcpy(config.sysname, "IRIX64");
} else if (!strcmp(sysname, "aix")) {
strcpy(config.sysname, "AIX");
} else if (!strcmp(sysname, "dec")) {
strcpy(config.sysname, "Dec OSF/1 or Tru64");
} else if (!strcmp(sysname, "solaris")) {
strcpy(config.sysname, "Solaris");
strcpy(config.release, ">= 2.5");
} else if (!strcmp(sysname, "bsd")) {
strcpy(config.sysname, "BSD compatible");
} else if (!strcmp(sysname, "darwin")) {
strcpy(config.sysname, "Darwin");
} else {
printf("unsupported OS: %s\n", sysname);
return -1 ;
}
}
}
detect_config();
make_config_make();
make_config_h();
return 0 ;
}