wcslib (8.2.2)

(root)/
include/
wcslib-8.2.2/
fitshdr.h
       1  /*============================================================================
       2    WCSLIB 8.2 - an implementation of the FITS WCS standard.
       3    Copyright (C) 1995-2023, Mark Calabretta
       4  
       5    This file is part of WCSLIB.
       6  
       7    WCSLIB is free software: you can redistribute it and/or modify it under the
       8    terms of the GNU Lesser General Public License as published by the Free
       9    Software Foundation, either version 3 of the License, or (at your option)
      10    any later version.
      11  
      12    WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
      13    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      14    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
      15    more details.
      16  
      17    You should have received a copy of the GNU Lesser General Public License
      18    along with WCSLIB.  If not, see http://www.gnu.org/licenses.
      19  
      20    Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
      21    http://www.atnf.csiro.au/people/Mark.Calabretta
      22    $Id: fitshdr.h,v 8.2.1.1 2023/11/16 10:05:57 mcalabre Exp mcalabre $
      23  *=============================================================================
      24  *
      25  * WCSLIB 8.2 - C routines that implement the FITS World Coordinate System
      26  * (WCS) standard.  Refer to the README file provided with WCSLIB for an
      27  * overview of the library.
      28  *
      29  *
      30  * Summary of the fitshdr routines
      31  * -------------------------------
      32  * The Flexible Image Transport System (FITS), is a data format widely used in
      33  * astronomy for data interchange and archive.  It is described in
      34  *
      35  =   "Definition of the Flexible Image Transport System (FITS), version 3.0",
      36  =   Pence, W.D., Chiappetti, L., Page, C.G., Shaw, R.A., & Stobie, E. 2010,
      37  =   A&A, 524, A42 - http://dx.doi.org/10.1051/0004-6361/201015362
      38  *
      39  * See also http://fits.gsfc.nasa.gov
      40  *
      41  * fitshdr() is a generic FITS header parser provided to handle keyrecords that
      42  * are ignored by the WCS header parsers, wcspih() and wcsbth().  Typically the
      43  * latter may be set to remove WCS keyrecords from a header leaving fitshdr()
      44  * to handle the remainder.
      45  *
      46  *
      47  * fitshdr() - FITS header parser routine
      48  * --------------------------------------
      49  * fitshdr() parses a character array containing a FITS header, extracting
      50  * all keywords and their values into an array of fitskey structs.
      51  *
      52  * Given:
      53  *   header    const char []
      54  *                       Character array containing the (entire) FITS header,
      55  *                       for example, as might be obtained conveniently via the
      56  *                       CFITSIO routine fits_hdr2str().
      57  *
      58  *                       Each header "keyrecord" (formerly "card image")
      59  *                       consists of exactly 80 7-bit ASCII printing characters
      60  *                       in the range 0x20 to 0x7e (which excludes NUL, BS,
      61  *                       TAB, LF, FF and CR) especially noting that the
      62  *                       keyrecords are NOT null-terminated.
      63  *
      64  *   nkeyrec   int       Number of keyrecords in header[].
      65  *
      66  *   nkeyids   int       Number of entries in keyids[].
      67  *
      68  * Given and returned:
      69  *   keyids    struct fitskeyid []
      70  *                       While all keywords are extracted from the header,
      71  *                       keyids[] provides a convienient way of indexing them.
      72  *                       The fitskeyid struct contains three members;
      73  *                       fitskeyid::name must be set by the user while
      74  *                       fitskeyid::count and fitskeyid::idx are returned by
      75  *                       fitshdr().  All matched keywords will have their
      76  *                       fitskey::keyno member negated.
      77  *
      78  * Returned:
      79  *   nreject   int*      Number of header keyrecords rejected for syntax
      80  *                       errors.
      81  *
      82  *   keys      struct fitskey**
      83  *                       Pointer to an array of nkeyrec fitskey structs
      84  *                       containing all keywords and keyvalues extracted from
      85  *                       the header.
      86  *
      87  *                       Memory for the array is allocated by fitshdr() and
      88  *                       this must be freed by the user.  See wcsdealloc().
      89  *
      90  * Function return value:
      91  *             int       Status return value:
      92  *                         0: Success.
      93  *                         1: Null fitskey pointer passed.
      94  *                         2: Memory allocation failed.
      95  *                         3: Fatal error returned by Flex parser.
      96  *                         4: Unrecognised data type.
      97  *
      98  * Notes:
      99  *   1: Keyword parsing is done in accordance with the syntax defined by
     100  *      NOST 100-2.0, noting the following points in particular:
     101  *
     102  *      a: Sect. 5.1.2.1 specifies that keywords be left-justified in columns
     103  *         1-8, blank-filled with no embedded spaces, composed only of the
     104  *         ASCII characters ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789-_
     105  *
     106  *         fitshdr() accepts any characters in columns 1-8 but flags keywords
     107  *         that do not conform to standard syntax.
     108  *
     109  *      b: Sect. 5.1.2.2 defines the "value indicator" as the characters "= "
     110  *         occurring in columns 9 and 10.  If these are absent then the
     111  *         keyword has no value and columns 9-80 may contain any ASCII text
     112  *         (but see note 2 for CONTINUE keyrecords).  This is copied to the
     113  *         comment member of the fitskey struct.
     114  *
     115  *      c: Sect. 5.1.2.3 states that a keyword may have a null (undefined)
     116  *         value if the value/comment field, columns 11-80, consists entirely
     117  *         of spaces, possibly followed by a comment.
     118  *
     119  *      d: Sect. 5.1.1 states that trailing blanks in a string keyvalue are
     120  *         not significant and the parser always removes them.  A string
     121  *         containing nothing but blanks will be replaced with a single
     122  *         blank.
     123  *
     124  *         Sect. 5.2.1 also states that a quote character (') in a string
     125  *         value is to be represented by two successive quote characters and
     126  *         the parser removes the repeated quote.
     127  *
     128  *      e: The parser recognizes free-format character (NOST 100-2.0,
     129  *         Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
     130  *         (Sect. 5.2.4) for all keywords.
     131  *
     132  *      f: Sect. 5.2.3 offers no comment on the size of an integer keyvalue
     133  *         except indirectly in limiting it to 70 digits.  The parser will
     134  *         translate an integer keyvalue to a 32-bit signed integer if it
     135  *         lies in the range -2147483648 to +2147483647, otherwise it
     136  *         interprets it as a 64-bit signed integer if possible, or else a
     137  *         "very long" integer (see fitskey::type).
     138  *
     139  *      g: END not followed by 77 blanks is not considered to be a legitimate
     140  *         end keyrecord.
     141  *
     142  *   2: The parser supports a generalization of the OGIP Long String Keyvalue
     143  *      Convention (v1.0) whereby strings may be continued onto successive
     144  *      header keyrecords.  A keyrecord contains a segment of a continued
     145  *      string if and only if
     146  *
     147  *      a: it contains the pseudo-keyword CONTINUE,
     148  *
     149  *      b: columns 9 and 10 are both blank,
     150  *
     151  *      c: columns 11 to 80 contain what would be considered a valid string
     152  *         keyvalue, including optional keycomment, if column 9 had contained
     153  *         '=',
     154  *
     155  *      d: the previous keyrecord contained either a valid string keyvalue or
     156  *         a valid CONTINUE keyrecord.
     157  *
     158  *      If any of these conditions is violated, the keyrecord is considered in
     159  *      isolation.
     160  *
     161  *      Syntax errors in keycomments in a continued string are treated more
     162  *      permissively than usual; the '/' delimiter may be omitted provided that
     163  *      parsing of the string keyvalue is not compromised.  However, the
     164  *      FITSHDR_COMMENT status bit will be set for the keyrecord (see
     165  *      fitskey::status).
     166  *
     167  *      As for normal strings, trailing blanks in a continued string are not
     168  *      significant.
     169  *
     170  *      In the OGIP convention "the '&' character is used as the last non-blank
     171  *      character of the string to indicate that the string is (probably)
     172  *      continued on the following keyword".  This additional syntax is not
     173  *      required by fitshdr(), but if '&' does occur as the last non-blank
     174  *      character of a continued string keyvalue then it will be removed, along
     175  *      with any trailing blanks.  However, blanks that occur before the '&'
     176  *      will be preserved.
     177  *
     178  *
     179  * fitskeyid struct - Keyword indexing
     180  * -----------------------------------
     181  * fitshdr() uses the fitskeyid struct to return indexing information for
     182  * specified keywords.  The struct contains three members, the first of which,
     183  * fitskeyid::name, must be set by the user with the remainder returned by
     184  * fitshdr().
     185  *
     186  *   char name[12]:
     187  *     (Given) Name of the required keyword.  This is to be set by the user;
     188  *     the '.' character may be used for wildcarding.  Trailing blanks will be
     189  *     replaced with nulls.
     190  *
     191  *   int count:
     192  *     (Returned) The number of matches found for the keyword.
     193  *
     194  *   int idx[2]:
     195  *     (Returned) Indices into keys[], the array of fitskey structs returned by
     196  *     fitshdr().  Note that these are 0-relative array indices, not keyrecord
     197  *     numbers.
     198  *
     199  *     If the keyword is found in the header the first index will be set to the
     200  *     array index of its first occurrence, otherwise it will be set to -1.
     201  *
     202  *     If multiples of the keyword are found, the second index will be set to
     203  *     the array index of its last occurrence, otherwise it will be set to -1.
     204  *
     205  *
     206  * fitskey struct - Keyword/value information
     207  * ------------------------------------------
     208  * fitshdr() returns an array of fitskey structs, each of which contains the
     209  * result of parsing one FITS header keyrecord.  All members of the fitskey
     210  * struct are returned by fitshdr(), none are given by the user.
     211  *
     212  *   int keyno
     213  *     (Returned) Keyrecord number (1-relative) in the array passed as input to
     214  *     fitshdr().  This will be negated if the keyword matched any specified in
     215  *     the keyids[] index.
     216  *
     217  *   int keyid
     218  *     (Returned) Index into the first entry in keyids[] with which the
     219  *     keyrecord matches, else -1.
     220  *
     221  *   int status
     222  *     (Returned) Status flag bit-vector for the header keyrecord employing the
     223  *     following bit masks defined as preprocessor macros:
     224  *
     225  *       - FITSHDR_KEYWORD:    Illegal keyword syntax.
     226  *       - FITSHDR_KEYVALUE:   Illegal keyvalue syntax.
     227  *       - FITSHDR_COMMENT:    Illegal keycomment syntax.
     228  *       - FITSHDR_KEYREC:     Illegal keyrecord, e.g. an END keyrecord with
     229  *                             trailing text.
     230  *       - FITSHDR_TRAILER:    Keyrecord following a valid END keyrecord.
     231  *
     232  *     The header keyrecord is syntactically correct if no bits are set.
     233  *
     234  *   char keyword[12]
     235  *     (Returned) Keyword name, null-filled for keywords of less than eight
     236  *     characters (trailing blanks replaced by nulls).
     237  *
     238  *     Use
     239  *
     240  =       sprintf(dst, "%.8s", keyword)
     241  *
     242  *     to copy it to a character array with null-termination, or
     243  *
     244  =       sprintf(dst, "%8.8s", keyword)
     245  *
     246  *     to blank-fill to eight characters followed by null-termination.
     247  *
     248  *   int type
     249  *     (Returned) Keyvalue data type:
     250  *       - 0: No keyvalue (both the value and type are undefined).
     251  *       - 1: Logical, represented as int.
     252  *       - 2: 32-bit signed integer.
     253  *       - 3: 64-bit signed integer (see below).
     254  *       - 4: Very long integer (see below).
     255  *       - 5: Floating point (stored as double).
     256  *       - 6: Integer complex (stored as double[2]).
     257  *       - 7: Floating point complex (stored as double[2]).
     258  *       - 8: String.
     259  *       - 8+10*n: Continued string (described below and in fitshdr() note 2).
     260  *
     261  *     A negative type indicates that a syntax error was encountered when
     262  *     attempting to parse a keyvalue of the particular type.
     263  *
     264  *     Comments on particular data types:
     265  *       - 64-bit signed integers lie in the range
     266  *
     267  =           (-9223372036854775808 <= int64 <  -2147483648) ||
     268  =                    (+2147483647 <  int64 <= +9223372036854775807)
     269  *
     270  *         A native 64-bit data type may be defined via preprocessor macro
     271  *         WCSLIB_INT64 defined in wcsconfig.h, e.g. as 'long long int'; this
     272  *         will be typedef'd to 'int64' here.  If WCSLIB_INT64 is not set, then
     273  *         int64 is typedef'd to int[3] instead and fitskey::keyvalue is to be
     274  *         computed as
     275  *
     276  =           ((keyvalue.k[2]) * 1000000000 +
     277  =             keyvalue.k[1]) * 1000000000 +
     278  =             keyvalue.k[0]
     279  *
     280  *         and may reported via
     281  *
     282  =            if (keyvalue.k[2]) {
     283  =              printf("%d%09d%09d", keyvalue.k[2], abs(keyvalue.k[1]),
     284  =                                   abs(keyvalue.k[0]));
     285  =            } else {
     286  =              printf("%d%09d", keyvalue.k[1], abs(keyvalue.k[0]));
     287  =            }
     288  *
     289  *         where keyvalue.k[0] and keyvalue.k[1] range from -999999999 to
     290  *         +999999999.
     291  *
     292  *       - Very long integers, up to 70 decimal digits in length, are encoded
     293  *         in keyvalue.l as an array of int[8], each of which stores 9 decimal
     294  *         digits.  fitskey::keyvalue is to be computed as
     295  *
     296  =           (((((((keyvalue.l[7]) * 1000000000 +
     297  =                  keyvalue.l[6]) * 1000000000 +
     298  =                  keyvalue.l[5]) * 1000000000 +
     299  =                  keyvalue.l[4]) * 1000000000 +
     300  =                  keyvalue.l[3]) * 1000000000 +
     301  =                  keyvalue.l[2]) * 1000000000 +
     302  =                  keyvalue.l[1]) * 1000000000 +
     303  =                  keyvalue.l[0]
     304  *
     305  *       - Continued strings are not reconstructed, they remain split over
     306  *         successive fitskey structs in the keys[] array returned by
     307  *         fitshdr().  fitskey::keyvalue data type, 8 + 10n, indicates the
     308  *         segment number, n, in the continuation.
     309  *
     310  *   int padding
     311  *     (An unused variable inserted for alignment purposes only.)
     312  *
     313  *   union keyvalue
     314  *     (Returned) A union comprised of
     315  *
     316  *       - fitskey::i,
     317  *       - fitskey::k,
     318  *       - fitskey::l,
     319  *       - fitskey::f,
     320  *       - fitskey::c,
     321  *       - fitskey::s,
     322  *
     323  *     used by the fitskey struct to contain the value associated with a
     324  *     keyword.
     325  *
     326  *   int i
     327  *     (Returned) Logical (fitskey::type == 1) and 32-bit signed integer
     328  *     (fitskey::type == 2) data types in the fitskey::keyvalue union.
     329  *
     330  *   int64 k
     331  *     (Returned) 64-bit signed integer (fitskey::type == 3) data type in the
     332  *     fitskey::keyvalue union.
     333  *
     334  *   int l[8]
     335  *     (Returned) Very long integer (fitskey::type == 4) data type in the
     336  *     fitskey::keyvalue union.
     337  *
     338  *   double f
     339  *     (Returned) Floating point (fitskey::type == 5) data type in the
     340  *     fitskey::keyvalue union.
     341  *
     342  *   double c[2]
     343  *     (Returned) Integer and floating point complex (fitskey::type == 6 || 7)
     344  *     data types in the fitskey::keyvalue union.
     345  *
     346  *   char s[72]
     347  *     (Returned) Null-terminated string (fitskey::type == 8) data type in the
     348  *     fitskey::keyvalue union.
     349  *
     350  *   int ulen
     351  *     (Returned) Where a keycomment contains a units string in the standard
     352  *     form, e.g. [m/s], the ulen member indicates its length, inclusive of
     353  *     square brackets.  Otherwise ulen is zero.
     354  *
     355  *   char comment[84]
     356  *     (Returned) Keycomment, i.e. comment associated with the keyword or, for
     357  *     keyrecords rejected because of syntax errors, the compete keyrecord
     358  *     itself with null-termination.
     359  *
     360  *     Comments are null-terminated with trailing spaces removed.  Leading
     361  *     spaces are also removed from keycomments (i.e. those immediately
     362  *     following the '/' character), but not from COMMENT or HISTORY keyrecords
     363  *     or keyrecords without a value indicator ("= " in columns 9-80).
     364  *
     365  *
     366  * Global variable: const char *fitshdr_errmsg[] - Status return messages
     367  * ----------------------------------------------------------------------
     368  * Error messages to match the status value returned from each function.
     369  *
     370  *===========================================================================*/
     371  
     372  #ifndef WCSLIB_FITSHDR
     373  #define WCSLIB_FITSHDR
     374  
     375  #include "wcsconfig.h"
     376  
     377  #ifdef __cplusplus
     378  extern "C" {
     379  #endif
     380  
     381  #define FITSHDR_KEYWORD  0x01
     382  #define FITSHDR_KEYVALUE 0x02
     383  #define FITSHDR_COMMENT  0x04
     384  #define FITSHDR_KEYREC   0x08
     385  #define FITSHDR_CARD     0x08	// Alias for backwards compatibility.
     386  #define FITSHDR_TRAILER  0x10
     387  
     388  
     389  extern const char *fitshdr_errmsg[];
     390  
     391  enum fitshdr_errmsg_enum {
     392    FITSHDRERR_SUCCESS      = 0,	// Success.
     393    FITSHDRERR_NULL_POINTER = 1,	// Null fitskey pointer passed.
     394    FITSHDRERR_MEMORY       = 2,	// Memory allocation failed.
     395    FITSHDRERR_FLEX_PARSER  = 3,	// Fatal error returned by Flex parser.
     396    FITSHDRERR_DATA_TYPE    = 4 	// Unrecognised data type.
     397  };
     398  
     399  #ifdef WCSLIB_INT64
     400    typedef WCSLIB_INT64 int64;
     401  #else
     402    typedef int int64[3];
     403  #endif
     404  
     405  
     406  // Struct used for indexing the keywords.
     407  struct fitskeyid {
     408    char name[12];		// Keyword name, null-terminated.
     409    int  count;			// Number of occurrences of keyword.
     410    int  idx[2];			// Indices into fitskey array.
     411  };
     412  
     413  // Size of the fitskeyid struct in int units, used by the Fortran wrappers.
     414  #define KEYIDLEN (sizeof(struct fitskeyid)/sizeof(int))
     415  
     416  
     417  // Struct used for storing FITS keywords.
     418  struct fitskey {
     419    int  keyno;			// Header keyrecord sequence number (1-rel).
     420    int  keyid;			// Index into fitskeyid[].
     421    int  status;			// Header keyrecord status bit flags.
     422    char keyword[12];		// Keyword name, null-filled.
     423    int  type;			// Keyvalue type (see above).
     424    int  padding;			// (Dummy inserted for alignment purposes.)
     425    union {
     426      int    i;			// 32-bit integer and logical values.
     427      int64  k;			// 64-bit integer values.
     428      int    l[8];		// Very long signed integer values.
     429      double f;			// Floating point values.
     430      double c[2];		// Complex values.
     431      char   s[72];		// String values, null-terminated.
     432    } keyvalue;			// Keyvalue.
     433    int  ulen;			// Length of units string.
     434    char comment[84];		// Comment (or keyrecord), null-terminated.
     435  };
     436  
     437  // Size of the fitskey struct in int units, used by the Fortran wrappers.
     438  #define KEYLEN (sizeof(struct fitskey)/sizeof(int))
     439  
     440  
     441  int fitshdr(const char header[], int nkeyrec, int nkeyids,
     442              struct fitskeyid keyids[], int *nreject, struct fitskey **keys);
     443  
     444  
     445  #ifdef __cplusplus
     446  }
     447  #endif
     448  
     449  #endif // WCSLIB_FITSHDR