WCSLIB  7.7
fitshdr.h
Go to the documentation of this file.
1 /*============================================================================
2  WCSLIB 7.7 - 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.7 2021/07/12 06:36:49 mcalabre Exp $
23 *=============================================================================
24 *
25 * WCSLIB 7.7 - 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 
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
fitshdr_errmsg_enum
Definition: fitshdr.h:391
@ FITSHDRERR_FLEX_PARSER
Definition: fitshdr.h:395
@ FITSHDRERR_NULL_POINTER
Definition: fitshdr.h:393
@ FITSHDRERR_SUCCESS
Definition: fitshdr.h:392
@ FITSHDRERR_DATA_TYPE
Definition: fitshdr.h:396
@ FITSHDRERR_MEMORY
Definition: fitshdr.h:394
int int64[3]
64-bit signed integer data type.
Definition: fitshdr.h:402
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:418
double c[2]
Definition: fitshdr.h:430
int padding
Definition: fitshdr.h:424
int keyno
Definition: fitshdr.h:419
char keyword[12]
Definition: fitshdr.h:422
char comment[84]
Definition: fitshdr.h:434
int l[8]
Definition: fitshdr.h:428
int i
Definition: fitshdr.h:426
int status
Definition: fitshdr.h:421
union fitskey::@1 keyvalue
char s[72]
Definition: fitshdr.h:431
int ulen
Definition: fitshdr.h:433
int type
Definition: fitshdr.h:423
double f
Definition: fitshdr.h:429
int64 k
Definition: fitshdr.h:427
int keyid
Definition: fitshdr.h:420
Keyword indexing.
Definition: fitshdr.h:407
int idx[2]
Definition: fitshdr.h:410
char name[12]
Definition: fitshdr.h:408
int count
Definition: fitshdr.h:409