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