00001 /*============================================================================ 00002 00003 WCSLIB 4.4 - an implementation of the FITS WCS standard. 00004 Copyright (C) 1995-2009, Mark Calabretta 00005 00006 This file is part of WCSLIB. 00007 00008 WCSLIB is free software: you can redistribute it and/or modify it under the 00009 terms of the GNU Lesser General Public License as published by the Free 00010 Software Foundation, either version 3 of the License, or (at your option) 00011 any later version. 00012 00013 WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY 00014 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00016 more details. 00017 00018 You should have received a copy of the GNU Lesser General Public License 00019 along with WCSLIB. If not, see <http://www.gnu.org/licenses/>. 00020 00021 Correspondence concerning WCSLIB may be directed to: 00022 Internet email: mcalabre@atnf.csiro.au 00023 Postal address: Dr. Mark Calabretta 00024 Australia Telescope National Facility, CSIRO 00025 PO Box 76 00026 Epping NSW 1710 00027 AUSTRALIA 00028 00029 Author: Mark Calabretta, Australia Telescope National Facility 00030 http://www.atnf.csiro.au/~mcalabre/index.html 00031 $Id: fitshdr_8h-source.html,v 1.1 2009/09/14 20:25:21 irby Exp $ 00032 *============================================================================= 00033 * 00034 * The Flexible Image Transport System (FITS), a data format widely used in 00035 * astronomy for data interchange and archive, is described in 00036 * 00037 * "Definition of The Flexible Image Transport System (FITS)", 00038 * Hanisch, R.J., Farris, A., Greisen, E.W., et al. 2001, A&A, 376, 359 00039 * 00040 * which formalizes NOST 100-2.0, a document produced by the NASA/Science 00041 * Office of Standards and Technology, see http://fits.gsfc.nasa.gov. 00042 * 00043 * Refer to the README file provided with WCSLIB for an overview of the 00044 * library. 00045 * 00046 * 00047 * Summary of the fitshdr routines 00048 * ------------------------------- 00049 * fitshdr() is a generic FITS header parser provided to handle keyrecords that 00050 * are ignored by the WCS header parsers, wcspih() and wcsbth(). Typically the 00051 * latter may be set to remove WCS keyrecords from a header leaving fitshdr() 00052 * to handle the remainder. 00053 * 00054 * 00055 * fitshdr() - FITS header parser routine 00056 * -------------------------------------- 00057 * fitshdr() parses a character array containing a FITS header, extracting 00058 * all keywords and their values into an array of fitskey structs. 00059 * 00060 * Given: 00061 * header const char [] 00062 * Character array containing the (entire) FITS header, 00063 * for example, as might be obtained conveniently via the 00064 * CFITSIO routine fits_hdr2str(). 00065 * 00066 * Each header "keyrecord" (formerly "card image") 00067 * consists of exactly 80 7-bit ASCII printing characters 00068 * in the range 0x20 to 0x7e (which excludes NUL, BS, 00069 * TAB, LF, FF and CR) especially noting that the 00070 * keyrecords are NOT null-terminated. 00071 * 00072 * nkeyrec int Number of keyrecords in header[]. 00073 * nkeyids int Number of entries in keyids[]. 00074 * 00075 * Given and returned: 00076 * keyids struct fitskeyid [] 00077 * While all keywords are extracted from the header, 00078 * keyids[] provides a convienient way of indexing them. 00079 * The fitskeyid struct contains three members; 00080 * fitskeyid::name must be set by the user while 00081 * fitskeyid::count and fitskeyid::name are returned by 00082 * fitshdr(). All matched keywords will have their 00083 * fitskey::keyno member negated. 00084 * 00085 * Returned: 00086 * nreject int* Number of header keyrecords rejected for syntax 00087 * errors. 00088 * keys struct fitskey** 00089 * Pointer to an array of nkeyrec fitskey structs 00090 * containing all keywords and keyvalues extracted from 00091 * the header. 00092 * 00093 * Memory for the array is allocated by fitshdr() and 00094 * this must be freed by the user by invoking free() on 00095 * the array. 00096 * 00097 * Function return value: 00098 * int Status return value: 00099 * 0: Success. 00100 * 1: Null fitskey pointer passed. 00101 * 2: Memory allocation failed. 00102 * 3: Fatal error returned by Flex parser. 00103 * 00104 * Notes: 00105 * 1: Keyword parsing is done in accordance with the syntax defined by 00106 * NOST 100-2.0, noting the following points in particular: 00107 * 00108 * a: Sect. 5.1.2.1 specifies that keywords be left-justified in columns 00109 * 1-8, blank-filled with no embedded spaces, composed only of the 00110 * ASCII characters ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789-_ 00111 * 00112 * fitshdr() accepts any characters in columns 1-8 but flags keywords 00113 * that do not conform to standard syntax. 00114 * 00115 * b: Sect. 5.1.2.2 defines the "value indicator" as the characters "= " 00116 * occurring in columns 9 and 10. If these are absent then the 00117 * keyword has no value and columns 9-80 may contain any ASCII text 00118 * (but see note 2 for CONTINUE keyrecords). This is copied to the 00119 * comment member of the fitskey struct. 00120 * 00121 * c: Sect. 5.1.2.3 states that a keyword may have a null (undefined) 00122 * value if the value/comment field, columns 11-80, consists entirely 00123 * of spaces, possibly followed by a comment. 00124 * 00125 * d: Sect. 5.1.1 states that trailing blanks in a string keyvalue are 00126 * not significant and the parser always removes them. A string 00127 * containing nothing but blanks will be replaced with a single 00128 * blank. 00129 * 00130 * Sect. 5.2.1 also states that a quote character (') in a string 00131 * value is to be represented by two successive quote characters and 00132 * the parser removes the repeated quote. 00133 * 00134 * e: The parser recognizes free-format character (NOST 100-2.0, 00135 * Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values 00136 * (Sect. 5.2.4) for all keywords. 00137 * 00138 * f: Sect. 5.2.3 offers no comment on the size of an integer keyvalue 00139 * except indirectly in limiting it to 70 digits. The parser will 00140 * translates an integer keyvalue to a 32-bit signed integer if it 00141 * lies in the range -2147483648 to +2147483647, otherwise it 00142 * interprets it as a 64-bit signed integer if possible, or else a 00143 * "very long" integer (see fitskey::type). 00144 * 00145 * g: END not followed by 77 blanks is not considered to be a legitimate 00146 * end keyrecord. 00147 * 00148 * 2: The parser supports a generalization of the OGIP Long String Keyvalue 00149 * Convention (v1.0) whereby strings may be continued onto successive 00150 * header keyrecords. A keyrecord contains a segment of a continued 00151 * string if and only if 00152 * 00153 * a: it contains the pseudo-keyword CONTINUE, 00154 * 00155 * b: columns 9 and 10 are both blank, 00156 * 00157 * c: columns 11 to 80 contain what would be considered a valid string 00158 * keyvalue, including optional keycomment, if column 9 had contained 00159 * '=', 00160 * 00161 * d: the previous keyrecord contained either a valid string keyvalue or 00162 * a valid CONTINUE keyrecord. 00163 * 00164 * If any of these conditions is violated, the keyrecord is considered in 00165 * isolation. 00166 * 00167 * Syntax errors in keycomments in a continued string are treated more 00168 * permissively than usual; the '/' delimiter may be omitted provided that 00169 * parsing of the string keyvalue is not compromised. However, the 00170 * FITSHDR_COMMENT status bit will be set for the keyrecord (see 00171 * fitskey::status). 00172 * 00173 * As for normal strings, trailing blanks in a continued string are not 00174 * significant. 00175 * 00176 * In the OGIP convention "the '&' character is used as the last non-blank 00177 * character of the string to indicate that the string is (probably) 00178 * continued on the following keyword". This additional syntax is not 00179 * required by fitshdr(), but if '&' does occur as the last non-blank 00180 * character of a continued string keyvalue then it will be removed, along 00181 * with any trailing blanks. However, blanks that occur before the '&' 00182 * will be preserved. 00183 * 00184 * 00185 * fitskeyid struct - Keyword indexing 00186 * ----------------------------------- 00187 * fitshdr() uses the fitskeyid struct to return indexing information for 00188 * specified keywords. The struct contains three members, the first of which, 00189 * fitskeyid::name, must be set by the user with the remainder returned by 00190 * fitshdr(). 00191 * 00192 * char name[12]: 00193 * (Given) Name of the required keyword. This is to be set by the user; 00194 * the '.' character may be used for wildcarding. Trailing blanks will be 00195 * replaced with nulls. 00196 * 00197 * int count: 00198 * (Returned) The number of matches found for the keyword. 00199 * 00200 * int idx[2]: 00201 * (Returned) Indices into keys[], the array of fitskey structs returned by 00202 * fitshdr(). Note that these are 0-relative array indices, not keyrecord 00203 * numbers. 00204 * 00205 * If the keyword is found in the header the first index will be set to the 00206 * array index of its first occurrence, otherwise it will be set to -1. 00207 * 00208 * If multiples of the keyword are found, the second index will be set to 00209 * the array index of its last occurrence, otherwise it will be set to -1. 00210 * 00211 * 00212 * fitskey struct - Keyword/value information 00213 * ------------------------------------------ 00214 * fitshdr() returns an array of fitskey structs, each of which contains the 00215 * result of parsing one FITS header keyrecord. All members of the fitskey 00216 * struct are returned by fitshdr(), none are given by the user. 00217 * 00218 * int keyno 00219 * (Returned) Keyrecord number (1-relative) in the array passed as input to 00220 * fitshdr(). This will be negated if the keyword matched any specified in 00221 * the keyids[] index. 00222 * 00223 * int keyid 00224 * (Returned) Index into the first entry in keyids[] with which the 00225 * keyrecord matches, else -1. 00226 * 00227 * int status 00228 * (Returned) Status flag bit-vector for the header keyrecord employing the 00229 * following bit masks defined as preprocessor macros: 00230 * 00231 * - FITSHDR_KEYWORD: Illegal keyword syntax. 00232 * - FITSHDR_KEYVALUE: Illegal keyvalue syntax. 00233 * - FITSHDR_COMMENT: Illegal keycomment syntax. 00234 * - FITSHDR_KEYREC: Illegal keyrecord, e.g. an END keyrecord with 00235 * trailing text. 00236 * - FITSHDR_TRAILER: Keyrecord following a valid END keyrecord. 00237 * 00238 * The header keyrecord is syntactically correct if no bits are set. 00239 * 00240 * char keyword[12] 00241 * (Returned) Keyword name, null-filled for keywords of less than eight 00242 * characters (trailing blanks replaced by nulls). 00243 * 00244 * Use 00245 * 00246 = sprintf(dst, "%.8s", keyword) 00247 * 00248 * to copy it to a character array with null-termination, or 00249 * 00250 = sprintf(dst, "%8.8s", keyword) 00251 * 00252 * to blank-fill to eight characters followed by null-termination. 00253 * 00254 * int type 00255 * (Returned) Keyvalue data type: 00256 * - 0: No keyvalue. 00257 * - 1: Logical, represented as int. 00258 * - 2: 32-bit signed integer. 00259 * - 3: 64-bit signed integer (see below). 00260 * - 4: Very long integer (see below). 00261 * - 5: Floating point (stored as double). 00262 * - 6: Integer complex (stored as double[2]). 00263 * - 7: Floating point complex (stored as double[2]). 00264 * - 8: String. 00265 * - 8+10*n: Continued string (described below and in fitshdr() note 2). 00266 * 00267 * A negative type indicates that a syntax error was encountered when 00268 * attempting to parse a keyvalue of the particular type. 00269 * 00270 * Comments on particular data types: 00271 * - 64-bit signed integers lie in the range 00272 * 00273 = (-9223372036854775808 <= int64 < -2147483648) || 00274 = (+2147483647 < int64 <= +9223372036854775807) 00275 * 00276 * A native 64-bit data type may be defined via preprocessor macro 00277 * WCSLIB_INT64 defined in wcsconfig.h, e.g. as 'long long int'; this 00278 * will be typedef'd to 'int64' here. If WCSLIB_INT64 is not set, then 00279 * int64 is typedef'd to int[3] instead and fitskey::keyvalue is to be 00280 * computed as 00281 * 00282 = ((keyvalue.k[2]) * 1000000000 + 00283 = keyvalue.k[1]) * 1000000000 + 00284 = keyvalue.k[0] 00285 * 00286 * and may reported via 00287 * 00288 = if (keyvalue.k[2]) { 00289 = printf("%d%09d%09d", keyvalue.k[2], abs(keyvalue.k[1]), 00290 = abs(keyvalue.k[0])); 00291 = } else { 00292 = printf("%d%09d", keyvalue.k[1], abs(keyvalue.k[0])); 00293 = } 00294 * 00295 * where keyvalue.k[0] and keyvalue.k[1] range from -999999999 to 00296 * +999999999. 00297 * 00298 * - Very long integers, up to 70 decimal digits in length, are encoded 00299 * in keyvalue.l as an array of int[8], each of which stores 9 decimal 00300 * digits. fitskey::keyvalue is to be computed as 00301 * 00302 = (((((((keyvalue.l[7]) * 1000000000 + 00303 = keyvalue.l[6]) * 1000000000 + 00304 = keyvalue.l[5]) * 1000000000 + 00305 = keyvalue.l[4]) * 1000000000 + 00306 = keyvalue.l[3]) * 1000000000 + 00307 = keyvalue.l[2]) * 1000000000 + 00308 = keyvalue.l[1]) * 1000000000 + 00309 = keyvalue.l[0] 00310 * 00311 * - Continued strings are not reconstructed, they remain split over 00312 * successive fitskey structs in the keys[] array returned by 00313 * fitshdr(). fitskey::keyvalue data type, 8 + 10n, indicates the 00314 * segment number, n, in the continuation. 00315 * 00316 * int padding 00317 * (An unused variable inserted for alignment purposes only.) 00318 * 00319 * union keyvalue 00320 * (Returned) A union comprised of 00321 * 00322 * - fitskey::i, 00323 * - fitskey::k, 00324 * - fitskey::l, 00325 * - fitskey::f, 00326 * - fitskey::c, 00327 * - fitskey::s, 00328 * 00329 * used by the fitskey struct to contain the value associated with a 00330 * keyword. 00331 * 00332 * int i 00333 * (Returned) Logical (fitskey::type == 1) and 32-bit signed integer 00334 * (fitskey::type == 2) data types in the fitskey::keyvalue union. 00335 * 00336 * int64 k 00337 * (Returned) 64-bit signed integer (fitskey::type == 3) data type in the 00338 * fitskey::keyvalue union. 00339 * 00340 * int l[8] 00341 * (Returned) Very long integer (fitskey::type == 4) data type in the 00342 * fitskey::keyvalue union. 00343 * 00344 * double f 00345 * (Returned) Floating point (fitskey::type == 5) data type in the 00346 * fitskey::keyvalue union. 00347 * 00348 * double c[2] 00349 * (Returned) Integer and floating point complex (fitskey::type == 6 || 7) 00350 * data types in the fitskey::keyvalue union. 00351 * 00352 * char s[72] 00353 * (Returned) Null-terminated string (fitskey::type == 8) data type in the 00354 * fitskey::keyvalue union. 00355 * 00356 * int ulen 00357 * (Returned) Where a keycomment contains a units string in the standard 00358 * form, e.g. [m/s], the ulen member indicates its length, inclusive of 00359 * square brackets. Otherwise ulen is zero. 00360 * 00361 * char comment[84] 00362 * (Returned) Keycomment, i.e. comment associated with the keyword or, for 00363 * keyrecords rejected because of syntax errors, the compete keyrecord 00364 * itself with null-termination. 00365 * 00366 * Comments are null-terminated with trailing spaces removed. Leading 00367 * spaces are also removed from keycomments (i.e. those immediately 00368 * following the '/' character), but not from COMMENT or HISTORY keyrecords 00369 * or keyrecords without a value indicator ("= " in columns 9-80). 00370 * 00371 * 00372 * Global variable: const char *fitshdr_errmsg[] - Status return messages 00373 * ---------------------------------------------------------------------- 00374 * Error messages to match the status value returned from each function. 00375 * 00376 *===========================================================================*/ 00377 00378 #ifndef WCSLIB_FITSHDR 00379 #define WCSLIB_FITSHDR 00380 00381 #include "wcsconfig.h" 00382 00383 #ifdef __cplusplus 00384 extern "C" { 00385 #endif 00386 00387 #define FITSHDR_KEYWORD 0x01 00388 #define FITSHDR_KEYVALUE 0x02 00389 #define FITSHDR_COMMENT 0x04 00390 #define FITSHDR_KEYREC 0x08 00391 #define FITSHDR_CARD 0x08 /* Alias for backwards compatibility. */ 00392 #define FITSHDR_TRAILER 0x10 00393 00394 00395 extern const char *fitshdr_errmsg[]; 00396 00397 #ifdef WCSLIB_INT64 00398 typedef WCSLIB_INT64 int64; 00399 #else 00400 typedef int int64[3]; 00401 #endif 00402 00403 00404 /* Struct used for indexing the keywords. */ 00405 struct fitskeyid { 00406 char name[12]; /* Keyword name, null-terminated. */ 00407 int count; /* Number of occurrences of keyword. */ 00408 int idx[2]; /* Indices into fitskey array. */ 00409 }; 00410 00411 /* Size of the fitskeyid struct in int units, used by the Fortran wrappers. */ 00412 #define KEYIDLEN (sizeof(struct fitskeyid)/sizeof(int)) 00413 00414 00415 /* Struct used for storing FITS keywords. */ 00416 struct fitskey { 00417 int keyno; /* Header keyrecord sequence number (1-rel).*/ 00418 int keyid; /* Index into fitskeyid[]. */ 00419 int status; /* Header keyrecord status bit flags. */ 00420 char keyword[12]; /* Keyword name, null-filled. */ 00421 int type; /* Keyvalue type (see above). */ 00422 int padding; /* (Dummy inserted for alignment purposes.) */ 00423 union { 00424 int i; /* 32-bit integer and logical values. */ 00425 int64 k; /* 64-bit integer values. */ 00426 int l[8]; /* Very long signed integer values. */ 00427 double f; /* Floating point values. */ 00428 double c[2]; /* Complex values. */ 00429 char s[72]; /* String values, null-terminated. */ 00430 } keyvalue; /* Keyvalue. */ 00431 int ulen; /* Length of units string. */ 00432 char comment[84]; /* Comment (or keyrecord), null-terminated. */ 00433 }; 00434 00435 /* Size of the fitskey struct in int units, used by the Fortran wrappers. */ 00436 #define KEYLEN (sizeof(struct fitskey)/sizeof(int)) 00437 00438 00439 int fitshdr(const char header[], int nkeyrec, int nkeyids, 00440 struct fitskeyid keyids[], int *nreject, struct fitskey **keys); 00441 00442 00443 #ifdef __cplusplus 00444 } 00445 #endif 00446 00447 #endif /* WCSLIB_FITSHDR */