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