Add bits from qfits
parent
fb339194c1
commit
28dd111b0f
|
@ -0,0 +1,3 @@
|
|||
Nicolas Devillard ndevilla@eso.org
|
||||
Yves Jung yjung@eso.org
|
||||
|
|
@ -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.
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 ;
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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, ®ex_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, ®ex_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, ®ex_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 */
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
|||
|
||||
/* Library version */
|
||||
static const char *
|
||||
_qfits_version = "5.4.0" ;
|
||||
|
||||
const char * qfits_version(void)
|
||||
{
|
||||
return _qfits_version ;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 ;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue