WCSLIB  7.4
fitshdr.h
Go to the documentation of this file.
1 /*============================================================================
2  WCSLIB 7.4 - an implementation of the FITS WCS standard.
3  Copyright (C) 1995-2021, 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 7.4 2021/01/31 02:24:51 mcalabre Exp $
23 *=============================================================================
24 *
25 * WCSLIB 7.4 - 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 *
97 * Notes:
98 * 1: Keyword parsing is done in accordance with the syntax defined by
99 * NOST 100-2.0, noting the following points in particular:
100 *
101 * a: Sect. 5.1.2.1 specifies that keywords be left-justified in columns
102 * 1-8, blank-filled with no embedded spaces, composed only of the
103 * ASCII characters ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789-_
104 *
105 * fitshdr() accepts any characters in columns 1-8 but flags keywords
106 * that do not conform to standard syntax.
107 *
108 * b: Sect. 5.1.2.2 defines the "value indicator" as the characters "= "
109 * occurring in columns 9 and 10. If these are absent then the
110 * keyword has no value and columns 9-80 may contain any ASCII text
111 * (but see note 2 for CONTINUE keyrecords). This is copied to the
112 * comment member of the fitskey struct.
113 *
114 * c: Sect. 5.1.2.3 states that a keyword may have a null (undefined)
115 * value if the value/comment field, columns 11-80, consists entirely
116 * of spaces, possibly followed by a comment.
117 *
118 * d: Sect. 5.1.1 states that trailing blanks in a string keyvalue are
119 * not significant and the parser always removes them. A string
120 * containing nothing but blanks will be replaced with a single
121 * blank.
122 *
123 * Sect. 5.2.1 also states that a quote character (') in a string
124 * value is to be represented by two successive quote characters and
125 * the parser removes the repeated quote.
126 *
127 * e: The parser recognizes free-format character (NOST 100-2.0,
128 * Sect. 5.2.1), integer (Sect. 5.2.3), and floating-point values
129 * (Sect. 5.2.4) for all keywords.
130 *
131 * f: Sect. 5.2.3 offers no comment on the size of an integer keyvalue
132 * except indirectly in limiting it to 70 digits. The parser will
133 * translate an integer keyvalue to a 32-bit signed integer if it
134 * lies in the range -2147483648 to +2147483647, otherwise it
135 * interprets it as a 64-bit signed integer if possible, or else a
136 * "very long" integer (see fitskey::type).
137 *
138 * g: END not followed by 77 blanks is not considered to be a legitimate
139 * end keyrecord.
140 *
141 * 2: The parser supports a generalization of the OGIP Long String Keyvalue
142 * Convention (v1.0) whereby strings may be continued onto successive
143 * header keyrecords. A keyrecord contains a segment of a continued
144 * string if and only if
145 *
146 * a: it contains the pseudo-keyword CONTINUE,
147 *
148 * b: columns 9 and 10 are both blank,
149 *
150 * c: columns 11 to 80 contain what would be considered a valid string
151 * keyvalue, including optional keycomment, if column 9 had contained
152 * '=',
153 *
154 * d: the previous keyrecord contained either a valid string keyvalue or
155 * a valid CONTINUE keyrecord.
156 *
157 * If any of these conditions is violated, the keyrecord is considered in
158 * isolation.
159 *
160 * Syntax errors in keycomments in a continued string are treated more
161 * permissively than usual; the '/' delimiter may be omitted provided that
162 * parsing of the string keyvalue is not compromised. However, the
163 * FITSHDR_COMMENT status bit will be set for the keyrecord (see
164 * fitskey::status).
165 *
166 * As for normal strings, trailing blanks in a continued string are not
167 * significant.
168 *
169 * In the OGIP convention "the '&' character is used as the last non-blank
170 * character of the string to indicate that the string is (probably)
171 * continued on the following keyword". This additional syntax is not
172 * required by fitshdr(), but if '&' does occur as the last non-blank
173 * character of a continued string keyvalue then it will be removed, along
174 * with any trailing blanks. However, blanks that occur before the '&'
175 * will be preserved.
176 *
177 *
178 * fitskeyid struct - Keyword indexing
179 * -----------------------------------
180 * fitshdr() uses the fitskeyid struct to return indexing information for
181 * specified keywords. The struct contains three members, the first of which,
182 * fitskeyid::name, must be set by the user with the remainder returned by
183 * fitshdr().
184 *
185 * char name[12]:
186 * (Given) Name of the required keyword. This is to be set by the user;
187 * the '.' character may be used for wildcarding. Trailing blanks will be
188 * replaced with nulls.
189 *
190 * int count:
191 * (Returned) The number of matches found for the keyword.
192 *
193 * int idx[2]:
194 * (Returned) Indices into keys[], the array of fitskey structs returned by
195 * fitshdr(). Note that these are 0-relative array indices, not keyrecord
196 * numbers.
197 *
198 * If the keyword is found in the header the first index will be set to the
199 * array index of its first occurrence, otherwise it will be set to -1.
200 *
201 * If multiples of the keyword are found, the second index will be set to
202 * the array index of its last occurrence, otherwise it will be set to -1.
203 *
204 *
205 * fitskey struct - Keyword/value information
206 * ------------------------------------------
207 * fitshdr() returns an array of fitskey structs, each of which contains the
208 * result of parsing one FITS header keyrecord. All members of the fitskey
209 * struct are returned by fitshdr(), none are given by the user.
210 *
211 * int keyno
212 * (Returned) Keyrecord number (1-relative) in the array passed as input to
213 * fitshdr(). This will be negated if the keyword matched any specified in
214 * the keyids[] index.
215 *
216 * int keyid
217 * (Returned) Index into the first entry in keyids[] with which the
218 * keyrecord matches, else -1.
219 *
220 * int status
221 * (Returned) Status flag bit-vector for the header keyrecord employing the
222 * following bit masks defined as preprocessor macros:
223 *
224 * - FITSHDR_KEYWORD: Illegal keyword syntax.
225 * - FITSHDR_KEYVALUE: Illegal keyvalue syntax.
226 * - FITSHDR_COMMENT: Illegal keycomment syntax.
227 * - FITSHDR_KEYREC: Illegal keyrecord, e.g. an END keyrecord with
228 * trailing text.
229 * - FITSHDR_TRAILER: Keyrecord following a valid END keyrecord.
230 *
231 * The header keyrecord is syntactically correct if no bits are set.
232 *
233 * char keyword[12]
234 * (Returned) Keyword name, null-filled for keywords of less than eight
235 * characters (trailing blanks replaced by nulls).
236 *
237 * Use
238 *
239 = sprintf(dst, "%.8s", keyword)
240 *
241 * to copy it to a character array with null-termination, or
242 *
243 = sprintf(dst, "%8.8s", keyword)
244 *
245 * to blank-fill to eight characters followed by null-termination.
246 *
247 * int type
248 * (Returned) Keyvalue data type:
249 * - 0: No keyvalue (both the value and type are undefined).
250 * - 1: Logical, represented as int.
251 * - 2: 32-bit signed integer.
252 * - 3: 64-bit signed integer (see below).
253 * - 4: Very long integer (see below).
254 * - 5: Floating point (stored as double).
255 * - 6: Integer complex (stored as double[2]).
256 * - 7: Floating point complex (stored as double[2]).
257 * - 8: String.
258 * - 8+10*n: Continued string (described below and in fitshdr() note 2).
259 *
260 * A negative type indicates that a syntax error was encountered when
261 * attempting to parse a keyvalue of the particular type.
262 *
263 * Comments on particular data types:
264 * - 64-bit signed integers lie in the range
265 *
266 = (-9223372036854775808 <= int64 < -2147483648) ||
267 = (+2147483647 < int64 <= +9223372036854775807)
268 *
269 * A native 64-bit data type may be defined via preprocessor macro
270 * WCSLIB_INT64 defined in wcsconfig.h, e.g. as 'long long int'; this
271 * will be typedef'd to 'int64' here. If WCSLIB_INT64 is not set, then
272 * int64 is typedef'd to int[3] instead and fitskey::keyvalue is to be
273 * computed as
274 *
275 = ((keyvalue.k[2]) * 1000000000 +
276 = keyvalue.k[1]) * 1000000000 +
277 = keyvalue.k[0]
278 *
279 * and may reported via
280 *
281 = if (keyvalue.k[2]) {
282 = printf("%d%09d%09d", keyvalue.k[2], abs(keyvalue.k[1]),
283 = abs(keyvalue.k[0]));
284 = } else {
285 = printf("%d%09d", keyvalue.k[1], abs(keyvalue.k[0]));
286 = }
287 *
288 * where keyvalue.k[0] and keyvalue.k[1] range from -999999999 to
289 * +999999999.
290 *
291 * - Very long integers, up to 70 decimal digits in length, are encoded
292 * in keyvalue.l as an array of int[8], each of which stores 9 decimal
293 * digits. fitskey::keyvalue is to be computed as
294 *
295 = (((((((keyvalue.l[7]) * 1000000000 +
296 = keyvalue.l[6]) * 1000000000 +
297 = keyvalue.l[5]) * 1000000000 +
298 = keyvalue.l[4]) * 1000000000 +
299 = keyvalue.l[3]) * 1000000000 +
300 = keyvalue.l[2]) * 1000000000 +
301 = keyvalue.l[1]) * 1000000000 +
302 = keyvalue.l[0]
303 *
304 * - Continued strings are not reconstructed, they remain split over
305 * successive fitskey structs in the keys[] array returned by
306 * fitshdr(). fitskey::keyvalue data type, 8 + 10n, indicates the
307 * segment number, n, in the continuation.
308 *
309 * int padding
310 * (An unused variable inserted for alignment purposes only.)
311 *
312 * union keyvalue
313 * (Returned) A union comprised of
314 *
315 * - fitskey::i,
316 * - fitskey::k,
317 * - fitskey::l,
318 * - fitskey::f,
319 * - fitskey::c,
320 * - fitskey::s,
321 *
322 * used by the fitskey struct to contain the value associated with a
323 * keyword.
324 *
325 * int i
326 * (Returned) Logical (fitskey::type == 1) and 32-bit signed integer
327 * (fitskey::type == 2) data types in the fitskey::keyvalue union.
328 *
329 * int64 k
330 * (Returned) 64-bit signed integer (fitskey::type == 3) data type in the
331 * fitskey::keyvalue union.
332 *
333 * int l[8]
334 * (Returned) Very long integer (fitskey::type == 4) data type in the
335 * fitskey::keyvalue union.
336 *
337 * double f
338 * (Returned) Floating point (fitskey::type == 5) data type in the
339 * fitskey::keyvalue union.
340 *
341 * double c[2]
342 * (Returned) Integer and floating point complex (fitskey::type == 6 || 7)
343 * data types in the fitskey::keyvalue union.
344 *
345 * char s[72]
346 * (Returned) Null-terminated string (fitskey::type == 8) data type in the
347 * fitskey::keyvalue union.
348 *
349 * int ulen
350 * (Returned) Where a keycomment contains a units string in the standard
351 * form, e.g. [m/s], the ulen member indicates its length, inclusive of
352 * square brackets. Otherwise ulen is zero.
353 *
354 * char comment[84]
355 * (Returned) Keycomment, i.e. comment associated with the keyword or, for
356 * keyrecords rejected because of syntax errors, the compete keyrecord
357 * itself with null-termination.
358 *
359 * Comments are null-terminated with trailing spaces removed. Leading
360 * spaces are also removed from keycomments (i.e. those immediately
361 * following the '/' character), but not from COMMENT or HISTORY keyrecords
362 * or keyrecords without a value indicator ("= " in columns 9-80).
363 *
364 *
365 * Global variable: const char *fitshdr_errmsg[] - Status return messages
366 * ----------------------------------------------------------------------
367 * Error messages to match the status value returned from each function.
368 *
369 *===========================================================================*/
370 
371 #ifndef WCSLIB_FITSHDR
372 #define WCSLIB_FITSHDR
373 
374 #include "wcsconfig.h"
375 
376 #ifdef __cplusplus
377 extern "C" {
378 #endif
379 
380 #define FITSHDR_KEYWORD 0x01
381 #define FITSHDR_KEYVALUE 0x02
382 #define FITSHDR_COMMENT 0x04
383 #define FITSHDR_KEYREC 0x08
384 #define FITSHDR_CARD 0x08 // Alias for backwards compatibility.
385 #define FITSHDR_TRAILER 0x10
386 
387 
388 extern const char *fitshdr_errmsg[];
389 
391  FITSHDRERR_SUCCESS = 0, // Success.
392  FITSHDRERR_NULL_POINTER = 1, // Null fitskey pointer passed.
393  FITSHDRERR_MEMORY = 2, // Memory allocation failed.
394  FITSHDRERR_FLEX_PARSER = 3 // Fatal error returned by Flex parser.
395 };
396 
397 #ifdef WCSLIB_INT64
398  typedef WCSLIB_INT64 int64;
399 #else
400  typedef int int64[3];
401 #endif
402 
403 
404 // Struct used for indexing the keywords.
405 struct fitskeyid {
406  char name[12]; // Keyword name, null-terminated.
407  int count; // Number of occurrences of keyword.
408  int idx[2]; // Indices into fitskey array.
409 };
410 
411 // Size of the fitskeyid struct in int units, used by the Fortran wrappers.
412 #define KEYIDLEN (sizeof(struct fitskeyid)/sizeof(int))
413 
414 
415 // Struct used for storing FITS keywords.
416 struct fitskey {
417  int keyno; // Header keyrecord sequence number (1-rel).
418  int keyid; // Index into fitskeyid[].
419  int status; // Header keyrecord status bit flags.
420  char keyword[12]; // Keyword name, null-filled.
421  int type; // Keyvalue type (see above).
422  int padding; // (Dummy inserted for alignment purposes.)
423  union {
424  int i; // 32-bit integer and logical values.
425  int64 k; // 64-bit integer values.
426  int l[8]; // Very long signed integer values.
427  double f; // Floating point values.
428  double c[2]; // Complex values.
429  char s[72]; // String values, null-terminated.
430  } keyvalue; // Keyvalue.
431  int ulen; // Length of units string.
432  char comment[84]; // Comment (or keyrecord), null-terminated.
433 };
434 
435 // Size of the fitskey struct in int units, used by the Fortran wrappers.
436 #define KEYLEN (sizeof(struct fitskey)/sizeof(int))
437 
438 
439 int fitshdr(const char header[], int nkeyrec, int nkeyids,
440  struct fitskeyid keyids[], int *nreject, struct fitskey **keys);
441 
442 
443 #ifdef __cplusplus
444 }
445 #endif
446 
447 #endif // WCSLIB_FITSHDR
fitshdr_errmsg_enum
Definition: fitshdr.h:390
@ FITSHDRERR_FLEX_PARSER
Definition: fitshdr.h:394
@ FITSHDRERR_NULL_POINTER
Definition: fitshdr.h:392
@ FITSHDRERR_SUCCESS
Definition: fitshdr.h:391
@ FITSHDRERR_MEMORY
Definition: fitshdr.h:393
int int64[3]
64-bit signed integer data type.
Definition: fitshdr.h:400
const char * fitshdr_errmsg[]
Status return messages.
int fitshdr(const char header[], int nkeyrec, int nkeyids, struct fitskeyid keyids[], int *nreject, struct fitskey **keys)
FITS header parser routine.
Keyword/value information.
Definition: fitshdr.h:416
double c[2]
Definition: fitshdr.h:428
int padding
Definition: fitshdr.h:422
int keyno
Definition: fitshdr.h:417
char keyword[12]
Definition: fitshdr.h:420
char comment[84]
Definition: fitshdr.h:432
int l[8]
Definition: fitshdr.h:426
int i
Definition: fitshdr.h:424
int status
Definition: fitshdr.h:419
union fitskey::@1 keyvalue
char s[72]
Definition: fitshdr.h:429
int ulen
Definition: fitshdr.h:431
int type
Definition: fitshdr.h:421
double f
Definition: fitshdr.h:427
int64 k
Definition: fitshdr.h:425
int keyid
Definition: fitshdr.h:418
Keyword indexing.
Definition: fitshdr.h:405
int idx[2]
Definition: fitshdr.h:408
char name[12]
Definition: fitshdr.h:406
int count
Definition: fitshdr.h:407