1 /*
2 This file is part of "fitsverify" and was imported from:
3 http://heasarc.gsfc.nasa.gov/docs/software/ftools/fitsverify/
4 */
5 #include "fverify.h"
6
7 /*
8 the following are only needed if one calls wcslib
9 #include <wcslib/wcshdr.h>
10 #include <wcslib/wcsfix.h>
11 #include <wcslib/wcs.h>
12 #include <wcslib/getwcstab.h>
13 */
14
15 static char **cards; /* array to store the keywords */
16 static int ncards; /* total number of the keywords */
17 static char **tmpkwds; /* An string array holding the keyword name.
18 It is sorted in alphabetical ascending order
19 and not includes the keywords before
20 the first non-reserved keyword and END
21 keyword. */
22
23 static char **ttype;
24 static char **tform;
25 static char **tunit;
26
27 static char temp[80];
28 static char *ptemp; /* it always pointed to the address of
29 temp */
30 static char snull[] = "";
31 static int curhdu; /* current HDU index */
32 static int curtype; /* current HDU type */
33
34 /******************************************************************************
35 * Function
36 * verify_fits
37 *
38 * DESCRIPTION:
39 * Verify individual fits file.
40 *
41 *******************************************************************************/
42 /* routine to verify individual fitsfile */
verify_fits(char * infile,FILE * out)43 void verify_fits(char *infile, FILE *out)
44 {
45 char rootnam[FLEN_FILENAME] = ""; /* Input Fits file root name */
46 fitsfile *infits; /* input fits file pointer */
47 FitsHdu fitshdu; /* hdu information */
48 int hdutype;
49 int status = 0;
50 int i;
51 int len;
52 char *p;
53 char *pfile;
54 char xtension[80];
55
56 /* take out the leading and trailing space and skip the empty line*/
57 p = infile;
58 while(isspace((int)*p) )p++;
59 len = strlen(p);
60 pfile = p;
61 p += (len -1);
62 for (i = len - 1; i >= 0 && isspace((int)*p); i--) {*p = '\0'; p--;}
63 if(!strlen(pfile)) return;
64
65 #ifndef WEBTOOL
66 wrtout(out," ");
67 sprintf(comm,"File: %s",pfile);
68 wrtout(out,comm);
69 #endif
70
71 totalhdu = 0;
72
73 /* discard the extension, rowfilter... */
74 if(ffrtnm(pfile, rootnam, &status)) {
75 wrtserr(out,"",&status,2);
76 leave_early(out);
77 return;
78 }
79
80 if(fits_open_file(&infits, rootnam, READONLY, &status)) {
81 wrtserr(out,"",&status,2);
82 leave_early(out);
83 return;
84 }
85
86 /* get the total hdus */
87 if(fits_get_num_hdus(infits, &totalhdu, &status)) {
88 wrtserr(out,"",&status,2);
89 leave_early(out);
90 return;
91 }
92
93 /* initialize the report */
94 init_report(out,rootnam);
95 /*------------------ Hdu Loop --------------------------------*/
96 for (i = 1; i <= totalhdu; i++) {
97 /* move to the right hdu and do the CFITSIO test */
98 hdutype = -1;
99 if(fits_movabs_hdu(infits,i, &hdutype, &status) ) {
100 print_title(out,i, hdutype);
101 wrtferr(out,"",&status,2);
102 set_hdubasic(i,hdutype);
103 break;
104 }
105
106 if (i != 1 && hdutype == IMAGE_HDU) {
107 /* test if this is a tile compressed image in a binary table */
108 fits_read_key(infits, TSTRING, "XTENSION", xtension, NULL, &status);
109 if (!strcmp(xtension, "BINTABLE") )
110 print_title(out,i, BINARY_TBL);
111 else
112 print_title(out,i, hdutype);
113 }
114 else
115 print_title(out,i, hdutype);
116
117 init_hdu(infits,out,i,hdutype,
118 &fitshdu); /* initialize fitshdu */
119
120 test_hdu(infits,out,&fitshdu); /* test hdu header */
121
122 if(testdata)
123 test_data(infits,out,&fitshdu);
124
125 close_err(out); /* end of error report */
126
127 if(prhead)
128 print_header(out);
129 if(prstat)
130 print_summary(infits,out,&fitshdu);
131 close_hdu(&fitshdu); /* clear the fitshdu */
132 }
133 /* test the end of file */
134 test_end(infits,out);
135
136 /*------------------ Closing --------------------------------*/
137 /* closing the report*/
138 close_report(out);
139
140 /* close the input fitsfile */
141 fits_close_file(infits, &status);
142 }
143
leave_early(FILE * out)144 void leave_early (FILE* out)
145 {
146 sprintf(comm,"**** Abort Verification: Fatal Error. ****");
147 wrtout(out,comm);
148
149 /* write the total number of errors and warnings to parfile*/
150 update_parfile(1,0);
151 }
152
close_err(FILE * out)153 void close_err(FILE* out)
154 {
155 int merr, mwrn;
156 num_err_wrn(&merr, &mwrn);
157 if(merr || mwrn ) wrtout(out," ");
158 return;
159 }
160
161
162 /*************************************************************
163 *
164 * init_hdu
165 *
166 * Initialize the FitsHdu, HduName and ttype, tform, tunit if
167 * the hdu is a table.
168 *
169 *
170 *************************************************************/
init_hdu(fitsfile * infits,FILE * out,int hdunum,int hdutype,FitsHdu * hduptr)171 void init_hdu(fitsfile *infits, /* input fits file */
172 FILE* out, /* output ascii file */
173 int hdunum, /* hdu index */
174 int hdutype, /* hdutype */
175 FitsHdu *hduptr
176 )
177 {
178
179 int morekeys;
180 int i,j,k,m,n;
181 int status = 0;
182 FitsKey ** kwds;
183 char *p = 0;
184 int numusrkey;
185 LONGLONG lv,lu=0L;
186
187
188 FitsKey tmpkey;
189
190 hduptr->hdunum = hdunum;
191 hduptr->hdutype = hdutype;
192
193 /* curhdu and curtype are shared with print_title */
194 curhdu = hdunum; /* set the current hdu number */
195 curtype = hdutype; /* set the current hdu number */
196
197 /* check the null character in the header.(only the first one will
198 be recorded */
199 lv = 0;
200 lv = fits_null_check(infits, &status);
201 if (lv > 0) {
202 m = (lv - 1)/80 + 1;
203 n = lv - (m - 1) * 80;
204 sprintf(errmes,
205 "Byte #%d in Card#%d is a null(\\0).",n,m);
206 wrterr(out,errmes,1);
207 status = 0;
208 } else {
209 if (status) {
210 wrtserr(out,"",&status,1);
211 status = 0;
212 }
213 }
214
215 /* get the total number of keywords */
216 hduptr->nkeys = 0;
217 morekeys = 0;
218 if(fits_get_hdrspace(infits, &(hduptr->nkeys), &morekeys, &status))
219 wrtferr(out,"",&status,1);
220 (hduptr->nkeys)++; /* include END keyword */
221
222
223 /* read all the keywords */
224 ncards = hduptr->nkeys;
225 cards = (char **)malloc(sizeof(char *) * ncards );
226 for (i=0; i < ncards; i++) {
227 cards[i] = (char *)malloc(sizeof(char )* FLEN_CARD );
228 }
229 for (i=1; i <= ncards; i++) {
230 if(fits_read_record(infits, i, cards[i-1], &status))
231 wrtferr(out,"",&status,1);
232 }
233
234 /* Parse the XTENSION/SIMPLEX keyword */
235 fits_parse_card(out, 1, cards[0], tmpkey.kname,
236 &(tmpkey.ktype), tmpkey.kvalue,comm);
237 if( *(tmpkey.kvalue) == ' ') {
238 sprintf(errmes,
239 "Keyword #1, %s \"%s\" should not have leading space.",
240 tmpkey.kname,tmpkey.kvalue);
241 wrterr(out,errmes,1);
242 }
243 if(hdunum == 1) { /* SIMPLE should be logical T */
244 if(strcmp(tmpkey.kname,"SIMPLE"))
245 wrterr(out, "The 1st keyword of a primary array is not SIMPLE.",1);
246 if( !check_log(&tmpkey,out)|| strcmp(tmpkey.kvalue,"T"))
247 wrtwrn(out,
248 "SIMPLE != T indicates file may not conform to the FITS Standard.",0);
249
250 check_fixed_log(cards[0], out);
251 }
252 else {
253 if(strcmp(tmpkey.kname,"XTENSION"))
254 wrterr(out, "The 1st keyword of a extension is not XTENSION.",1);
255 check_str(&tmpkey,out);
256
257 check_fixed_str(cards[0], out);
258
259 /* Get the original string */
260 p = cards[0];
261 p +=10;
262 while (*p == ' ') p++;
263 p++; /* skip the quote */
264 if( strncmp(p,"TABLE ",8) &&
265 strncmp(p,"BINTABLE",8) &&
266 strncmp(p,"A3DTABLE",8) &&
267 strncmp(p,"IUEIMAGE",8) &&
268 strncmp(p,"FOREIGN ",8) &&
269 strncmp(p,"DUMP ",8) &&
270 strncmp(p,"IMAGE ",8) ) {
271 sprintf(errmes, "Unregistered XTENSION value \"%8.8s\".",p);
272 wrterr(out,errmes,1);
273 }
274 else {
275 if (p[8] != '\'') {
276 sprintf(errmes,
277 "Extra \'%c\' follows the XTENSION value \"%8.8s\".",p[8],p);
278 wrterr(out,errmes,1);
279 }
280 }
281
282 /* test if this is a tile compressed image, stored in a binary table */
283 /* If so then test the extension as binary table rather than an image */
284
285 if (!strncmp(p,"BINTABLE",8) && hduptr->hdutype == IMAGE_HDU) {
286 hduptr->hdutype = BINARY_TBL;
287 hduptr->istilecompressed = 1;
288 } else {
289 hduptr->istilecompressed = 0;
290 }
291 }
292
293
294 /* read the BITPIX keywords */
295 if(fits_read_key(infits, TINT, "BITPIX", &(hduptr->bitpix), NULL, &status))
296 wrtferr(out,"",&status,2);
297 check_fixed_int(cards[1], out);
298
299 /* Read and Parse the NAXIS */
300 hduptr->naxis = 0;
301 if(fits_read_key(infits, TINT, "NAXIS", &(hduptr->naxis), NULL, &status))
302 wrtferr(out,"",&status,2);
303 check_fixed_int(cards[2], out);
304
305 if(hduptr->naxis!=0)
306 hduptr->naxes = (LONGLONG *)malloc(hduptr->naxis*sizeof(LONGLONG));
307 for (i = 0; i < hduptr->naxis; i++) hduptr->naxes[i] = -1;
308
309 /* Parse the keywords NAXISn */
310 for (j = 3; j < 3 + hduptr->naxis; j++){
311 fits_parse_card(out, 1+j,cards[j], tmpkey.kname,
312 &(tmpkey.ktype), tmpkey.kvalue,comm);
313 p = tmpkey.kname+5;
314 if(!isdigit((int) *p))continue;
315 #if (USE_LL_SUFFIX == 1)
316 if(check_int(&tmpkey,out)) lu = strtoll(tmpkey.kvalue,NULL,10);
317 #else
318 if(check_int(&tmpkey,out)) lu = strtol(tmpkey.kvalue,NULL,10);
319 #endif
320 lv = strtol(p,NULL,10);
321 if(lv > hduptr->naxis && lv <= 0) {
322 sprintf(errmes,
323 "Keyword #%d, %s is not allowed (with n > NAXIS = %d).",
324 tmpkey.kindex,tmpkey.kname,hduptr->naxis);
325 wrterr(out,errmes,1);
326 }
327 else {
328 if(hduptr->naxes[lv-1] == -1) {
329 hduptr->naxes[lv-1] = lu;
330 }
331 else {
332 sprintf(errmes, "Keyword #%d, %s is duplicated.",
333 tmpkey.kindex,tmpkey.kname);
334 wrterr(out,errmes,1);
335 }
336 }
337
338 check_fixed_int(cards[j], out);
339 }
340
341 /* check all the NAXISn are there */
342 for (j = 0; j < hduptr->naxis; j++) {
343 if(hduptr->naxes[j] == -1) {
344 sprintf(errmes,
345 "Keyword NAXIS%d is not present or is out of order.", j+1);
346 wrterr(out,errmes,2);
347 }
348 }
349
350 /* get the column number */
351 hduptr->ncols = 1;
352 if(hduptr->hdutype == ASCII_TBL || hduptr->hdutype == BINARY_TBL) {
353 /* get the total number of columns */
354 if(fits_get_num_cols(infits, &(hduptr->ncols),&status))
355 wrtferr(out,"",&status,2);
356 }
357
358 /* parse the keywords after NAXISn and prepare the array for
359 sorting. We only check the keywords after the NAXISn */
360 n = hduptr->nkeys - 4 - hduptr->naxis ; /* excluding the SIMPLE/XTENSION,
361 BITPIX, NAXIS, NAXISn
362 and END */
363 hduptr->kwds = (FitsKey **)malloc(sizeof(FitsKey *)*n);
364 for (i= 0; i < n; i++)
365 hduptr->kwds[i] = (FitsKey *)malloc(sizeof(FitsKey));
366 kwds = hduptr->kwds;
367 k = 3 + hduptr->naxis; /* index of first keyword following NAXISn. */
368 m = hduptr->nkeys - 1; /* last key */
369 i = 0;
370 hduptr->use_longstr = 0;
371 for (j = k ; j < m; j++) {
372 kwds[i]->kindex = j+1; /* record number */
373 kwds[i]->goodkey=1;
374 if(fits_parse_card(out,1+j,cards[j], kwds[i]->kname,
375 &(kwds[i]->ktype), kwds[i]->kvalue,comm))
376 kwds[i]->goodkey=0;
377
378 if (kwds[i]->ktype == UNKNOWN && *(kwds[i]->kvalue) == 0)
379 {
380 sprintf(errmes,
381 "Keyword #%d, %s has a null value.",
382 j+1,kwds[i]->kname);
383 wrtwrn(out,errmes,0);
384 }
385
386 /* only count the non-commentary keywords */
387 if (!strcmp(kwds[i]->kname,"CONTINUE")) {
388 hduptr->use_longstr = 1;
389 }
390 if( strcmp(kwds[i]->kname,"COMMENT") &&
391 strcmp(kwds[i]->kname,"HISTORY") &&
392 strcmp(kwds[i]->kname,"HIERARCH") &&
393 strcmp(kwds[i]->kname,"CONTINUE") &&
394 strcmp(kwds[i]->kname,"") ) i++;
395 }
396 numusrkey = i;
397 hduptr->tkeys = i;
398
399 /* parse the END key */
400 fits_parse_card(out,m+1,cards[hduptr->nkeys-1],
401 tmpkey.kname,&(tmpkey.ktype),tmpkey.kvalue,comm) ;
402
403 /* sort the keyword in the ascending order of kname field*/
404 qsort(kwds, numusrkey, sizeof(FitsKey *), compkey);
405
406 /* store addresses of sorted keyword names in a working
407 array */
408 tmpkwds = (char **)malloc(sizeof(char*) * numusrkey);
409 for (i=0; i < numusrkey; i++) tmpkwds[i] = kwds[i]->kname;
410
411 /* Initialize the PCOUNT, GCOUNT and heap values */
412 hduptr->pcount = -99;
413 hduptr->gcount = -99;
414 hduptr->heap = -99;
415
416 /* set the random group flag (will be determined later) */
417 hduptr->isgroup = 0;
418
419 /* allocate memory for datamax and datamin (will determined later)*/
420 if(hduptr->ncols > 0) {
421 hduptr->datamax = (char **)calloc(hduptr->ncols, sizeof(char *));
422 hduptr->datamin = (char **)calloc(hduptr->ncols, sizeof(char *));
423 hduptr->tnull = (char **)calloc(hduptr->ncols, sizeof(char *));
424 for (i = 0; i < hduptr->ncols; i++) {
425 hduptr->datamax[i] = (char *)calloc(13,sizeof(char));
426 hduptr->datamin[i] = (char *)calloc(13,sizeof(char));
427 hduptr->tnull[i] = (char *)calloc(12,sizeof(char));
428 }
429 }
430
431
432 /* initialize the extension name and version */
433 strcpy(hduptr->extname,"");
434 hduptr->extver = -999;
435
436
437 return;
438 }
439
440 /*************************************************************
441 *
442 * test_hdu
443 *
444 * Test the HDU header
445 * This includes many tests of WCS keywords
446 *
447 *************************************************************/
test_hdu(fitsfile * infits,FILE * out,FitsHdu * hduptr)448 void test_hdu(fitsfile *infits, /* input fits file */
449 FILE *out, /* output ascii file */
450 FitsHdu *hduptr
451 )
452
453 {
454 int status = 0;
455 FitsKey **kwds;
456 int numusrkey;
457 int hdunum;
458 char *p, *p2, *pname = 0;
459 int i,j,k,m,n, wcsaxes = 0, taxes;
460 int wcsaxesExists = 0, wcsaxesvalue = 0, wcsaxespos = 0, wcskeypos = 1000000000;
461 FitsKey *pkey;
462 int crota2_exists = 0, matrix_exists[2] = {0,0};
463 double dvalue;
464
465 /* floating WCS keywords */
466 char *cfltkeys[] = {"CRPIX", "CRVAL","CDELT","CROTA",
467 "CRDER","CSYER", "PV"};
468 int ncfltkeys = 7;
469 int keynum[] = {0,0,0,0,0,0,0}, nmax = 0;
470
471 /* floating non-indexed WCS keywords */
472 char *cfltnkeys[] = {"RESTFRQ", "RESTFREQ", "RESTWAV",
473 "OBSGEO-X", "OBSGEO-Y", "OBSGEO-Z",
474 "VELOSYS", "ZSOURCE", "VELANGL",
475 "LONPOLE", "LATPOLE"};
476 int ncfltnkeys = 11;
477
478 /* floating WCS keywords w/ underscore */
479 char *cflt_keys[] = {"PC","CD"};
480 int ncflt_keys = 2;
481
482 /* string WCS keywords */
483 char *cstrkeys[] = {"CTYPE", "CUNIT", "PS", "CNAME" };
484 int ncstrkeys = 4;
485
486 /* string RADESYS keywords with list of allowed values */
487 char *rastrkeys[] = {"RADESYS", "RADECSYS" };
488 int nrastrkeys = 2;
489
490 /* string spectral ref frame keywords with list of allowed values */
491 char *specstrkeys[] = {"SPECSYS", "SSYSOBS", "SSYSSRC" };
492 int nspecstrkeys = 3;
493
494
495 numusrkey = hduptr->tkeys;
496 kwds = hduptr->kwds;
497
498 /* find the extension name and version */
499 strcpy(temp,"EXTNAME");
500 ptemp = temp;
501 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
502 if(k> -1 ) {
503 if(kwds[k]->ktype == STR_KEY)
504 strcpy(hduptr->extname,kwds[k]->kvalue);
505 }
506
507 strcpy(temp,"EXTVER");
508 ptemp = temp;
509 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
510 if(k> -1 ) {
511 if(kwds[k]->ktype == INT_KEY)
512 hduptr->extver = (int) strtol(kwds[k]->kvalue,NULL,10);
513 }
514
515 /* set the HduName structure */
516 hdunum = hduptr->hdunum;
517 set_hduname(hdunum,hduptr->hdutype,hduptr->extname, hduptr->extver);
518
519 if(hduptr->hdunum == 1) {
520 test_prm(infits,out,hduptr);
521 }
522 else {
523 /* test the keywords specific to the hdutype*/
524 switch (hduptr->hdutype) {
525 case IMAGE_HDU:
526 test_img_ext(infits,out,hduptr);
527 break;
528 case ASCII_TBL:
529 test_asc_ext(infits,out,hduptr);
530 break;
531 case BINARY_TBL:
532 test_bin_ext(infits,out,hduptr);
533 break;
534 default:
535 break;
536 }
537 }
538 /* test the general keywords */
539 test_header(infits,out,hduptr);
540
541 /* test if CROTA2 exists; if so, then PCi_j must not exist */
542 strcpy(temp,"CROTA2");
543 ptemp = temp;
544 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
545 if (n == 1) {
546 pkey = hduptr->kwds[k];
547 crota2_exists = pkey->kindex;
548 }
549
550 strcpy(temp,"WCSAXES");
551 ptemp = temp;
552
553 /* first find the primary WCSAXES value, if it exists */
554 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
555 if (k >= 0) {
556 j = k;
557 if (check_int(kwds[j],out)) {
558 pkey = hduptr->kwds[j];
559 wcsaxesvalue = (int) strtol(pkey->kvalue,NULL,10);
560 nmax = wcsaxesvalue;
561 }
562 }
563
564 /* Check and find max value of the WCSAXESa keywords */
565 /* Use the max value when checking the range of the indexed WCS keywords. */
566 /* This is a less rigorous test than if one were to test the range of the */
567 /* keywords for each of the alternate WCS systems (A - Z) against the */
568 /* corresponding WCSAXESa keyword. */
569 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
570
571 for (j = k; j< n + k ; j++){
572 if (check_int(kwds[j],out)) {
573 pkey = hduptr->kwds[j];
574 taxes = (int) strtol(pkey->kvalue,NULL,10);
575 if (taxes > wcsaxes) wcsaxes = taxes;
576 wcsaxesExists = 1;
577
578 /* store highest index of any wcsaxes keyword */
579 /* (they must appear before other WCS keywords) */
580 if (pkey->kindex > wcsaxespos) wcsaxespos = pkey->kindex;
581 }
582 }
583
584 /* test datatype of reserved indexed floating point WCS keywords */
585 for (i = 0; i < ncfltkeys; i++) {
586 strcpy(temp,cfltkeys[i]);
587 ptemp = temp;
588 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
589 if(k < 0) continue;
590
591 for (j = k; j < k+n; j++) {
592 pkey = hduptr->kwds[j];
593
594 p = kwds[j]->kname;
595 p += strlen(temp);
596 if(!isdigit((int)*p)) continue;
597
598 if (!check_flt(pkey,out) )continue;
599
600 if (i == 2 ) { /* test that CDELTi != 0 */
601 dvalue = strtod(pkey->kvalue, NULL);
602 if (dvalue == 0.) {
603 sprintf( errmes,
604 "Keyword #%d, %s: must have non-zero value.",
605 pkey->kindex,pkey->kname);
606 wrterr(out,errmes,1);
607 }
608 }
609
610 if (i == 4 || i == 5 ) { /* test that CRDERi and CSYSERi are non-negative */
611 dvalue = strtod(pkey->kvalue, NULL);
612 if (dvalue < 0.) {
613 sprintf( errmes,
614 "Keyword #%d, %s: must have non-negative value: %s",
615 pkey->kindex,pkey->kname,pkey->kvalue);
616 wrterr(out,errmes,1);
617 }
618 }
619
620 m = (int)strtol(p,&p2,10);
621 if (wcsaxesExists) { /* WCSAXES keyword exists */
622
623 if (m < 1 || m > wcsaxes) {
624 sprintf( errmes,
625 "Keyword #%d, %s: index %d is not in range 1-%d (WCSAXES).",
626 pkey->kindex,pkey->kname,m,wcsaxes);
627 wrterr(out,errmes,1);
628 }
629
630 } else {
631
632 if (m < 1 || m > hduptr->naxis) {
633 sprintf( errmes,
634 "Keyword #%d, %s: index %d is not in range 1-%d (NAXIS).",
635 pkey->kindex,pkey->kname,m,hduptr->naxis);
636 wrtwrn(out,errmes,0);
637 }
638 }
639
640 /* count the number of each keyword */
641 if (*p2 == 0) { /* only test the primary set of WCS keywords */
642 keynum[i] = keynum[i] + 1;
643 if (m > nmax) nmax = m;
644 }
645
646 /* store lowest index of any wcs keyword */
647 if (pkey->kindex < wcskeypos) {
648 wcskeypos = pkey->kindex;
649 pname = pkey->kname;
650 }
651 }
652 }
653
654 if (wcsaxesvalue == 0) { /* limit value of nmax to the legal maximum */
655 if (nmax > hduptr->naxis)
656 nmax = hduptr->naxis;
657 } else {
658 if (nmax > wcsaxesvalue)
659 nmax = wcsaxesvalue;
660 }
661
662 if (keynum[0] < nmax) { /* test number of CRPIXi keywords */
663 sprintf( errmes,
664 "Some CRPIXi keywords appear to be missing; expected %d.",nmax);
665 wrtwrn(out,errmes,0);
666 }
667 if (keynum[1] < nmax) { /* test number of CRVALi keywords */
668 sprintf( errmes,
669 "Some CRVALi keywords appear to be missing; expected %d.",nmax);
670 wrtwrn(out,errmes,0);
671 }
672
673 /* test datatype of reserved non-indexed floating point WCS keywords */
674 for (i = 0; i < ncfltnkeys; i++) {
675 strcpy(temp,cfltnkeys[i]);
676 ptemp = temp;
677 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
678
679 if(k < 0) continue;
680
681 for (j = k; j < k+n; j++) {
682 pkey = hduptr->kwds[j];
683
684 if (!check_flt(pkey,out) )continue;
685 }
686 }
687
688 /* test datatype of reserved indexed floating point WCS keywords with "_" */
689 for (i = 0; i < ncflt_keys; i++) {
690 strcpy(temp,cflt_keys[i]);
691 ptemp = temp;
692 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
693 if(k < 0) continue;
694
695 for (j = k; j < k+n; j++) {
696 pkey = hduptr->kwds[j];
697
698 p = kwds[j]->kname;
699 p += strlen(temp);
700 if(!isdigit((int)*p)) continue;
701
702 p2 = strchr(p, '_'); /* 2 digits must be separated by a '_' */
703 if (!p2) continue;
704
705 if (!check_flt(pkey,out) )continue;
706
707 *p2 = '\0'; /* terminate string at the '_' */
708
709 /* test the first digit */
710 m = (int)strtol(p,NULL,10);
711 *p2 = '_'; /* replace the '_' */
712
713 if (wcsaxesExists) { /* WCSAXES keyword exists */
714
715 if (m < 1 || m > wcsaxes) {
716 sprintf( errmes,
717 "Keyword #%d, %s: 1st index %d is not in range 1-%d (WCSAXES).",
718 pkey->kindex,pkey->kname,m,wcsaxes);
719 wrterr(out,errmes,1);
720 }
721
722 } else {
723
724 if (m < 1 || m > hduptr->naxis) {
725 sprintf( errmes,
726 "Keyword #%d, %s: 1st index %d is not in range 1-%d (NAXIS).",
727 pkey->kindex,pkey->kname,m,hduptr->naxis);
728 wrtwrn(out,errmes,0);
729 }
730
731 }
732
733 /* test the second digit */
734 p = p2 + 1;
735 m = (int)strtol(p,&p2,10);
736
737 if (wcsaxesExists) { /* WCSAXES keyword exists */
738
739 if (m < 1 || m > wcsaxes) {
740 sprintf( errmes,
741 "Keyword #%d, %s: 2nd index %d is not in range 1-%d (WCSAXES).",
742 pkey->kindex,pkey->kname,m,wcsaxes);
743 wrterr(out,errmes,1);
744 }
745
746 } else {
747
748 if (m < 1 || m > hduptr->naxis) {
749 sprintf( errmes,
750 "Keyword #%d, %s: 2nd index %d is not in range 1-%d (NAXIS).",
751 pkey->kindex,pkey->kname,m,hduptr->naxis);
752 wrtwrn(out,errmes,0);
753 }
754 }
755
756 if (*p2 == 0) { /* no alternate suffix on the PC or CD name */
757 matrix_exists[i] = pkey->kindex;
758 }
759
760 /* store lowest index of any wcs keyword */
761 if (pkey->kindex < wcskeypos) {
762 wcskeypos = pkey->kindex;
763 pname = pkey->kname;
764 }
765 }
766 }
767
768 if (matrix_exists[0] > 0 && matrix_exists[1] > 0 ) {
769 sprintf( errmes,
770 "Keywords PCi_j (#%d) and CDi_j (#%d) are mutually exclusive.",
771 matrix_exists[0],matrix_exists[1]);
772 wrterr(out,errmes,1);
773 }
774
775 if (matrix_exists[0] > 0 && crota2_exists > 0 ) {
776 sprintf( errmes,
777 "Keywords PCi_j (#%d) and CROTA2 (#%d) are mutually exclusive.",
778 matrix_exists[0],crota2_exists);
779 wrterr(out,errmes,1);
780 }
781
782 /* test datatype of reserved indexed string WCS keywords */
783 for (i = 0; i < ncstrkeys; i++) {
784 strcpy(temp,cstrkeys[i]);
785 ptemp = temp;
786 keynum[i] = 0;
787 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
788
789 if(k < 0) continue;
790
791 for (j = k; j < k+n; j++) {
792 pkey = hduptr->kwds[j];
793
794 p = kwds[j]->kname;
795 p += strlen(temp);
796 if(!isdigit((int)*p)) continue;
797
798 if (!check_str(pkey,out) )continue;
799
800 m = (int)strtol(p,&p2,10);
801
802 if (wcsaxesExists) { /* WCSAXES keyword exists */
803
804 if (m < 1 || m > wcsaxes) {
805 sprintf( errmes,
806 "Keyword #%d, %s: index %d is not in range 1-%d (WCSAXES).",
807 pkey->kindex,pkey->kname,m,wcsaxes);
808 wrterr(out,errmes,1);
809 }
810
811 } else {
812
813 if (m < 1 || m > hduptr->naxis) {
814 sprintf( errmes,
815 "Keyword #%d, %s: index %d is not in range 1-%d (NAXIS).",
816 pkey->kindex,pkey->kname,m,hduptr->naxis);
817 wrtwrn(out,errmes,0);
818 }
819
820 }
821
822 if (*p2 == 0) { /* only test the primary set of WCS keywords */
823 keynum[i] = keynum[i] + 1;
824 }
825
826 /* store lowest index of any wcs keyword */
827 if (pkey->kindex < wcskeypos) {
828 wcskeypos = pkey->kindex;
829 pname = pkey->kname;
830 }
831 }
832 }
833
834 if (keynum[0] < nmax) {
835 sprintf( errmes,
836 "Some CTYPEi keywords appear to be missing; expected %d.",nmax);
837 wrtwrn(out,errmes,0);
838 }
839
840 if (wcskeypos < wcsaxespos) {
841 sprintf( errmes,
842 "WCSAXES keyword #%d appears after other WCS keyword %s #%d",
843 wcsaxespos, pname, wcskeypos);
844 wrterr(out,errmes,1);
845 }
846
847 /* test datatype and value of reserved RADECSYS WCS keywords */
848 for (i = 0; i < nrastrkeys; i++) {
849 strcpy(temp,rastrkeys[i]);
850 ptemp = temp;
851 keynum[i] = 0;
852 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
853
854 if(k < 0) continue;
855
856 for (j = k; j < k+n; j++) {
857 pkey = hduptr->kwds[j];
858
859 p = kwds[j]->kname;
860 p += strlen(temp);
861
862 if (!check_str(pkey,out) )continue;
863
864 if (strcmp(pkey->kvalue, "ICRS") && strcmp(pkey->kvalue, "FK5") &&
865 strcmp(pkey->kvalue, "FK4") && strcmp(pkey->kvalue, "FK4-NO-E") &&
866 strcmp(pkey->kvalue, "GAPPT")) {
867 sprintf( errmes,
868 "Keyword #%d, %s has non-allowed value: %s",
869 pkey->kindex,pkey->kname,pkey->kvalue);
870 wrtwrn(out,errmes,0);
871 }
872
873 }
874 }
875
876 /* test datatype and value of reserved spectral ref frame WCS keywords */
877 for (i = 0; i < nspecstrkeys; i++) {
878 strcpy(temp,specstrkeys[i]);
879 ptemp = temp;
880 keynum[i] = 0;
881 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
882
883 if(k < 0) continue;
884
885 for (j = k; j < k+n; j++) {
886 pkey = hduptr->kwds[j];
887
888 p = kwds[j]->kname;
889 p += strlen(temp);
890
891 if (!check_str(pkey,out) )continue;
892
893 if (strcmp(pkey->kvalue, "TOPOCENT") && strcmp(pkey->kvalue, "GEOCENTR") &&
894 strcmp(pkey->kvalue, "BARYCENT") && strcmp(pkey->kvalue, "HELIOCEN") &&
895 strcmp(pkey->kvalue, "LSRK") && strcmp(pkey->kvalue, "LSRD") &&
896 strcmp(pkey->kvalue, "GALACTOC") && strcmp(pkey->kvalue, "LOCALGRP") &&
897 strcmp(pkey->kvalue, "CMBDIPOL") && strcmp(pkey->kvalue, "SOURCE")) {
898 sprintf( errmes,
899 "Keyword #%d, %s has non-allowed value: %s",
900 pkey->kindex,pkey->kname,pkey->kvalue);
901 wrtwrn(out,errmes,0);
902 }
903
904 }
905 }
906
907 /* test the fill area */
908 if(testfill) {
909 if(ffchfl(infits,&status)) {
910 wrterr(out,
911 "The header fill area is not totally filled with blanks.",1);
912 }
913 }
914 return ;
915 }
916
917
918 /*************************************************************
919 *
920 * test_prm
921 *
922 * Test the primary array header
923 *
924 *
925 *************************************************************/
test_prm(fitsfile * infits,FILE * out,FitsHdu * hduptr)926 void test_prm(fitsfile *infits, /* input fits file */
927 FILE* out, /* output ascii file */
928 FitsHdu *hduptr /* hdu information structure */
929 )
930
931 {
932 int i,j,k,n;
933 FitsKey *pkey;
934 FitsKey **kwds;
935 int numusrkey;
936 char *p;
937
938 char *exlkey[] = {"XTENSION"};
939 int nexlkey = 1;
940
941 kwds = hduptr->kwds;
942 numusrkey = hduptr->tkeys;
943
944 /* The SIMPLE, BITPIX, NAXIS, and NAXISn keywords have been
945 checked in CFITSIO */
946
947 /* excluded keywords cannot be used. */
948 for (i = 0; i < nexlkey; i++) {
949 strcpy(temp,exlkey[i]);
950 ptemp = temp;
951 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
952 if( n > 0) {
953 pkey = hduptr->kwds[k];
954 sprintf(errmes,
955 "Keyword #%d, %s is not allowed in a primary array.",
956 pkey->kindex,exlkey[i]);
957 wrterr(out,errmes,1);
958 }
959 }
960
961 /* Check if Random Groups file */
962 strcpy(temp,"GROUPS");
963 ptemp = temp;
964 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
965 if(k > -1){
966 pkey = hduptr->kwds[k];
967 if(*(pkey->kvalue) == 'T' && hduptr->naxis > 0 && hduptr->naxes[0]==0) {
968 hduptr->isgroup = 1;
969
970 check_fixed_log(cards[pkey->kindex - 1], out);
971 }
972 }
973
974 /* check the position of the EXTEND */
975
976 /* the EXTEND keyword is no longer required if the file contains extensions */
977
978 if (hduptr->isgroup == 0) {
979 strcpy(temp,"EXTEND");
980 ptemp = temp;
981 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
982 if( k > 0) {
983 pkey = hduptr->kwds[k];
984
985 if(check_log(pkey,out) && *(pkey->kvalue)!='T' && totalhdu > 1) {
986 sprintf(errmes,"There are extensions but EXTEND = F.");
987 wrterr(out,errmes,1);
988 }
989 }
990 }
991
992 /* Check PCOUNT and GCOUNT keyword */
993 strcpy(temp,"PCOUNT");
994 ptemp = temp;
995 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
996 if(k > -1) {
997 pkey = hduptr->kwds[k];
998 /* Primary array cannot have PCOUNT */
999 if (!hduptr->isgroup ){
1000 sprintf(errmes,
1001 " Keyword #%d, %s is not allowed in a primary array.",
1002 pkey->kindex,pkey->kname);
1003 wrterr(out,errmes,1);
1004 }
1005 else {
1006 if(check_int(pkey,out))
1007 hduptr->pcount = (int) strtol(pkey->kvalue,NULL,10);
1008
1009 check_fixed_int(cards[pkey->kindex - 1], out);
1010 }
1011 }
1012
1013 strcpy(temp,"GCOUNT");
1014 ptemp = temp;
1015 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1016 if(k > -1) {
1017 pkey = hduptr->kwds[k];
1018 /* Primary array cannot have GCOUNT */
1019 if (!hduptr->isgroup ){
1020 sprintf(errmes,
1021 " Keyword #%d, %s is not allowed in a primary array.",
1022 pkey->kindex,pkey->kname);
1023 wrterr(out,errmes,1);
1024 }
1025 else {
1026 if(check_int(pkey,out))
1027 hduptr->gcount = (int) strtol(pkey->kvalue,NULL,10);
1028
1029 check_fixed_int(cards[pkey->kindex - 1], out);
1030 }
1031 }
1032
1033 strcpy(temp,"BLOCKED");
1034 ptemp = temp;
1035 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1036 if(k > -1) {
1037 pkey = hduptr->kwds[k];
1038 sprintf(errmes,
1039 "Keyword #%d, %s is deprecated.",
1040 pkey->kindex, pkey->kname);
1041 wrtwrn(out,errmes,0);
1042 check_log(pkey,out);
1043
1044 /* no longer required
1045 if(pkey->kindex > 36) {
1046 sprintf(errmes,
1047 "Keyword #%d, BLOCKED, appears beyond keyword 36.",
1048 pkey->kindex);
1049 wrterr(out,errmes,1);
1050 }
1051 */
1052
1053 }
1054
1055 /* Check PSCALn keywords (only in Random Groups) */
1056 strcpy(temp,"PSCAL");
1057 ptemp = temp;
1058 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1059 for (j = k; j< k + n ; j++){
1060 p = kwds[j]->kname;
1061 p += 5;
1062 if(!isdigit((int)*p)) continue;
1063
1064 if (!(hduptr->isgroup)) {
1065 sprintf(errmes,"Keyword #%d, %s ",
1066 kwds[j]->kindex,kwds[j]->kname);
1067 strcat(errmes,
1068 "is only allowed in Random Groups structures.");
1069 wrterr(out,errmes,1);
1070 continue;
1071 }
1072
1073 if (check_flt(kwds[j],out) && strtod(kwds[j]->kvalue,NULL) == 0.0) {
1074 sprintf(errmes,"Keyword #%d, %s: ",
1075 kwds[j]->kindex,kwds[j]->kname);
1076 strcat(errmes,
1077 "The scaling factor is zero.");
1078 wrtwrn(out,errmes,0);
1079 }
1080
1081 i = (int) strtol(p,NULL,10) -1 ;
1082 if(i< 0 || i >= hduptr->gcount) {
1083 sprintf(errmes,
1084 "Keyword #%d, %s: invalid index %d (> GCOUNT = %d).",
1085 kwds[j]->kindex,kwds[j]->kname,i+1,hduptr->gcount);
1086 wrterr(out,errmes,1);
1087 continue;
1088 }
1089
1090 }
1091
1092 /* Check PZEROn keywords (only in Random Groups) */
1093 strcpy(temp,"PZERO");
1094 ptemp = temp;
1095 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1096 for (j = k; j< k + n ; j++){
1097 p = kwds[j]->kname;
1098 p += 5;
1099 if(!isdigit((int)*p)) continue;
1100
1101 if (!(hduptr->isgroup)) {
1102 sprintf(errmes,"Keyword #%d, %s ",
1103 kwds[j]->kindex,kwds[j]->kname);
1104 strcat(errmes,
1105 "is only allowed in Random Groups structures.");
1106 wrterr(out,errmes,1);
1107 continue;
1108 }
1109
1110 check_flt(kwds[j],out);
1111 i = (int) strtol(p,NULL,10) -1 ;
1112 if(i< 0 || i >= hduptr->gcount) {
1113 sprintf(errmes,
1114 "Keyword #%d, %s: invalid index %d (> GCOUNT = %d).",
1115 kwds[j]->kindex,kwds[j]->kname,i+1,hduptr->gcount);
1116 wrterr(out,errmes,1);
1117 continue;
1118 }
1119 }
1120
1121 /* Check PTYPEn keywords (only in Random Groups) */
1122 strcpy(temp,"PTYPE");
1123 ptemp = temp;
1124 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1125 for (j = k; j< k + n ; j++){
1126 p = kwds[j]->kname;
1127 p += 5;
1128 if(!isdigit((int)*p)) continue;
1129
1130 if (!(hduptr->isgroup)) {
1131 sprintf(errmes,"Keyword #%d, %s ",
1132 kwds[j]->kindex,kwds[j]->kname);
1133 strcat(errmes,
1134 "is only allowed in Random Groups structures.");
1135 wrterr(out,errmes,1);
1136 continue;
1137 }
1138
1139 check_str(kwds[j],out);
1140 i = (int) strtol(p,NULL,10) -1 ;
1141 if(i< 0 || i >= hduptr->gcount) {
1142 sprintf(errmes,
1143 "Keyword #%d, %s: invalid index %d (> GCOUNT = %d).",
1144 kwds[j]->kindex,kwds[j]->kname,i+1,hduptr->gcount);
1145 wrterr(out,errmes,1);
1146 continue;
1147 }
1148 }
1149 test_array(infits, out, hduptr);
1150
1151 return;
1152 }
1153
1154 /*************************************************************
1155 *
1156 * test_ext
1157 *
1158 * Test the extension header
1159 *
1160 *
1161 *************************************************************/
test_ext(fitsfile * infits,FILE * out,FitsHdu * hduptr)1162 void test_ext(fitsfile *infits, /* input fits file */
1163 FILE* out, /* output ascii file */
1164 FitsHdu *hduptr /* information about header */
1165 )
1166 {
1167 FitsKey *pkey;
1168 FitsKey **kwds;
1169 int i,j,k,n;
1170 int numusrkey;
1171 char *exlkey[] = {"SIMPLE","EXTEND", "BLOCKED", };
1172 int nexlkey = 3;
1173 char *exlnkey[] = {"PTYPE","PSCAL", "PZERO", "GROUPS", };
1174 int nexlnkey = 4;
1175 int hdunum;
1176 char *p;
1177
1178 numusrkey = hduptr->tkeys;
1179 kwds = hduptr->kwds;
1180 hdunum = hduptr->hdunum;
1181
1182 /* check the duplicate extensions */
1183 for (i = hdunum - 1; i > 0; i--) {
1184 if(test_hduname(hdunum,i)) {
1185 sprintf(comm,
1186 "The HDU %d and %d have identical type/name/version",
1187 hdunum,i);
1188 wrtwrn(out,comm,0);
1189 }
1190 }
1191
1192 /* check the position of the PCOUNT */
1193 strcpy(temp,"PCOUNT");
1194 ptemp = temp;
1195 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1196 if( k < 0) {
1197 sprintf(errmes,"cannot find the PCOUNT keyword.");
1198 wrterr(out,errmes,1);
1199 }
1200 else {
1201 pkey = hduptr->kwds[k];
1202 if(check_int(pkey,out))
1203 hduptr->pcount = (int) strtol(pkey->kvalue,NULL,10);
1204 if( pkey->kindex != 4 + hduptr->naxis ) {
1205 sprintf(errmes,"PCOUNT is not in record %d of the header.",
1206 hduptr->naxis + 4);
1207 wrterr(out,errmes,1);
1208 }
1209
1210 check_fixed_int(cards[pkey->kindex - 1], out);
1211 }
1212
1213 /* check the position of the GCOUNT */
1214 strcpy(temp,"GCOUNT");
1215 ptemp = temp;
1216 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1217 if( k < 0) {
1218 sprintf(errmes,"cannot find the GCOUNT keyword.");
1219 wrterr(out,errmes,1);
1220 }
1221 else {
1222 pkey = hduptr->kwds[k];
1223 if(check_int(pkey,out))
1224 hduptr->gcount = (int) strtol(pkey->kvalue,NULL,10);
1225 if( pkey->kindex != 5 + hduptr->naxis ) {
1226 sprintf(errmes,"GCOUNT is not in record %d of the header.",
1227 hduptr->naxis + 5);
1228 wrterr(out,errmes,1);
1229 }
1230
1231 check_fixed_int(cards[pkey->kindex - 1], out);
1232 }
1233
1234 for (i = 0; i < nexlkey; i++) {
1235 strcpy(temp,exlkey[i]);
1236 ptemp = temp;
1237 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1238 if(k > -1) {
1239 pkey = hduptr->kwds[k];
1240 sprintf( errmes,
1241 "Keyword #%d, %s is not allowed in extensions.",
1242 pkey->kindex,pkey->kname);
1243 wrterr(out,errmes,1);
1244 }
1245 }
1246
1247 for (i = 0; i < nexlnkey; i++) {
1248 strcpy(temp,exlnkey[i]);
1249 ptemp = temp;
1250 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1251 if(k > -1) {
1252
1253 for (j = k; j< k + n ; j++){
1254 p = kwds[j]->kname;
1255 p += 5;
1256 if(!isdigit((int)*p)) continue;
1257
1258 pkey = hduptr->kwds[j];
1259 sprintf( errmes,
1260 "Keyword #%d, %s is only allowed in Random Groups structures.",
1261 pkey->kindex,pkey->kname);
1262 wrterr(out,errmes,1);
1263 }
1264 }
1265 }
1266
1267 return;
1268
1269 }
1270 /*************************************************************
1271 *
1272 * test_img_ext
1273 *
1274 * Test the image extension header
1275 *
1276 *
1277 *************************************************************/
test_img_ext(fitsfile * infits,FILE * out,FitsHdu * hduptr)1278 void test_img_ext(fitsfile *infits, /* input fits file */
1279 FILE* out, /* output ascii file */
1280 FitsHdu *hduptr /* information about header */
1281 )
1282 {
1283 int numusrkey;
1284
1285 numusrkey = hduptr->tkeys;
1286
1287 test_ext(infits,out,hduptr);
1288
1289 /* The XTENSION, BITPIX, NAXIS, and NAXISn keywords have been
1290 checked in CFITSIO */
1291
1292 if(hduptr->pcount != 0 && hduptr->pcount != -99){
1293 sprintf(errmes,
1294 "Illegal pcount value %d for image ext.",hduptr->pcount);
1295 wrterr(out,errmes,1);
1296 }
1297
1298 if(hduptr->gcount !=1 && hduptr->gcount != -99){
1299 sprintf(errmes,
1300 "Illegal gcount value %d for image ext.",hduptr->gcount);
1301 wrterr(out,errmes,1);
1302 }
1303
1304 test_array(infits, out, hduptr);
1305
1306 return ;
1307 }
1308
1309 /*************************************************************
1310 *
1311 * test_array
1312 *
1313 * Test the keywords which are used by both the primary array
1314 * and image Extension.
1315 *
1316 *
1317 *************************************************************/
test_array(fitsfile * infits,FILE * out,FitsHdu * hduptr)1318 void test_array(fitsfile *infits, /* input fits file */
1319 FILE* out, /* output ascii file */
1320 FitsHdu *hduptr /* information about header */
1321 )
1322 {
1323 int numusrkey;
1324 FitsKey **kwds;
1325 char *p;
1326 int i,j,k,n;
1327 FitsKey *pkey;
1328
1329 /* excluded non-indexed keywords */
1330 char *exlkeys[] = {"TFIELDS","THEAP"};
1331 int nexlkeys = 2;
1332
1333 /* excluded indexed keywords */
1334 char *exlnkeys[] = {"TBCOL", "TFORM",
1335 "TSCAL", "TZERO","TNULL",
1336 "TTYPE", "TUNIT","TDISP","TDIM",
1337 "TCTYP","TCUNI","TCRVL","TCDLT","TCRPX","TCROT"};
1338 int nexlnkeys = 15;
1339
1340 /* non-indexed floating keywords (excluding BSCALE) */
1341 char *fltkeys[] = {"BZERO","DATAMAX","DATAMIN"};
1342 int nfltkeys = 3;
1343
1344 /* non-indexed string keywords */
1345 char *strkeys[] = {"BUNIT"};
1346 int nstrkeys = 1;
1347
1348 numusrkey = hduptr->tkeys;
1349 kwds = hduptr->kwds;
1350
1351 /* Check BLANK, BSCALE keywords */
1352 strcpy(temp,"BLANK");
1353 ptemp = temp;
1354 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1355 if( k >= 0) {
1356 check_int(kwds[k],out);
1357 if(hduptr->bitpix < 0) {
1358 sprintf(errmes,
1359 "Keyword #%d, %s must not be used with floating point data (BITPIX = %d).",
1360 kwds[k]->kindex,kwds[k]->kname, hduptr->bitpix);
1361 wrterr(out,errmes,2);
1362 }
1363 }
1364
1365 strcpy(temp,"BSCALE");
1366 ptemp = temp;
1367 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1368 if( k >= 0) {
1369 if(check_flt(kwds[k],out) && strtod(kwds[k]->kvalue,NULL) == 0.0) {
1370 sprintf(errmes,"Keyword #%d, %s: The scaling factor is 0.",
1371 kwds[k]->kindex,kwds[k]->kname);
1372 wrtwrn(out,errmes,0);
1373 }
1374 }
1375
1376 /* search for excluded, non-indexed keywords */
1377 for (i = 0; i < nexlkeys; i++) {
1378 strcpy(temp,exlkeys[i]);
1379 ptemp = temp;
1380 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1381 if(k < 0) continue;
1382 for (j = k; j < k+n; j++) {
1383 pkey = hduptr->kwds[j];
1384 sprintf( errmes,
1385 "Keyword #%d, %s is not allowed in the array HDU.",
1386 pkey->kindex,pkey->kname);
1387 wrterr(out,errmes,1);
1388 }
1389 }
1390
1391 /* search for excluded, indexed keywords */
1392 for (i = 0; i < nexlnkeys; i++) {
1393 strcpy(temp,exlnkeys[i]);
1394 ptemp = temp;
1395 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1396 if(k < 0) continue;
1397 for (j = k; j < k+n; j++) {
1398 pkey = hduptr->kwds[j];
1399
1400 p = kwds[j]->kname;
1401 p += strlen(temp);
1402 if(!isdigit((int)*p)) continue;
1403
1404 sprintf( errmes,
1405 "Keyword #%d, %s is not allowed in the array HDU.",
1406 pkey->kindex,pkey->kname);
1407 wrterr(out,errmes,1);
1408 }
1409 }
1410
1411 /* test datatype of reserved non-indexed floating point keywords */
1412 for (i = 0; i < nfltkeys; i++) {
1413 strcpy(temp,fltkeys[i]);
1414 ptemp = temp;
1415 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1416 if(k < 0) continue;
1417 for (j = k; j < k+n; j++) {
1418 pkey = hduptr->kwds[j];
1419 if (!check_flt(pkey,out)) continue;
1420 }
1421 }
1422
1423 /* test datatype of reserved non-indexed string keywords */
1424 for (i = 0; i < nstrkeys; i++) {
1425 strcpy(temp,strkeys[i]);
1426 ptemp = temp;
1427 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1428 if(k < 0) continue;
1429 for (j = k; j < k+n; j++) {
1430 pkey = hduptr->kwds[j];
1431 check_str(pkey,out);
1432 }
1433 }
1434
1435 return;
1436 }
1437
1438 /*************************************************************
1439 *
1440 * test_img_wcs
1441 *
1442 * Test the image WCS keywords
1443 *
1444 *
1445 *************************************************************/
1446
1447 /*
1448 void test_img_wcs(fitsfile *infits,
1449 FILE* out,
1450 FitsHdu *hduptr
1451 )
1452 {
1453
1454 int nkeyrec, nreject, nwcs, status = 0;
1455 int *stat = 0, ii;
1456 char *header;
1457 struct wcsprm *wcs;
1458 */
1459
1460 /* NOTE: WCSLIB currently doesn't provide very much diagnostic information
1461 about possible problems with the WCS keywords so for now, comment out this
1462 routine.
1463 */
1464
1465 /* use WCSLIB to look for inconsistencies in the WCS keywords */
1466
1467 /* Read in the FITS header, excluding COMMENT and HISTORY keyrecords. */
1468 /*
1469 if (fits_hdr2str(infits, 1, NULL, 0, &header, &nkeyrec, &status)) {
1470 sprintf(errmes,
1471 "test_img_ext failed to read header keywords into array %d", status);
1472 wrterr(out,errmes,1);
1473 return;
1474 }
1475 */
1476 /* Interpret the WCS keywords. */
1477
1478 /*
1479 if ((status = wcsbth(header, nkeyrec, WCSHDR_all, -2, 0, 0, &nreject, &nwcs,
1480 &wcs))) {
1481 sprintf(errmes,
1482 "test_img_ext: wcsbth ERROR %d: %s.", status, wcshdr_errmsg[status]);
1483 wrterr(out,errmes,1);
1484
1485 free(header);
1486 return;
1487 }
1488
1489 free(header);
1490
1491 if (wcs) {
1492 if (nwcs == 1) {
1493 sprintf(errmes,
1494 " Found 1 World Coordinate System (WCS).");
1495 } else {
1496 sprintf(errmes,
1497 " Found %d World Coordinate Systems (WCS).", nwcs);
1498 }
1499 wrtout(out,errmes);
1500 }
1501 */
1502 /* Translate non-standard WCS keyvalues and look for inconsistencies */
1503
1504 /* this doesn't provide any useful checks
1505 stat = malloc(NWCSFIX * sizeof(int));
1506
1507 if ((status = wcsfix(7, 0, wcs, stat))) {
1508 for (ii = 0; ii < NWCSFIX; ii++) {
1509 if (stat[ii] > 0) {
1510 sprintf(errmes, "wcsfix ERROR %d: %s.", stat[ii],
1511 wcsfix_errmsg[stat[ii]]);
1512 wrtwrn(out,errmes,0);
1513
1514 }
1515 }
1516 }
1517
1518 if ((status = wcsset(wcs))) {
1519 sprintf(errmes,
1520 "wcsset ERROR %d %s.", status, wcs_errmsg[status]);
1521 wrtwrn(out,errmes,0);
1522 }
1523 */
1524
1525 /*
1526 status = wcsvfree(&nwcs, &wcs);
1527
1528 return;
1529 }
1530 */
1531
1532 /*************************************************************
1533 *
1534 * test_tbl
1535 *
1536 * Test the table extension header and fill the tform, ttype,
1537 * tunit.
1538 *
1539 *
1540 *************************************************************/
test_tbl(fitsfile * infits,FILE * out,FitsHdu * hduptr)1541 void test_tbl(fitsfile *infits, /* input fits file */
1542 FILE* out, /* output ascii file */
1543 FitsHdu *hduptr /* information about header */
1544 )
1545
1546 {
1547 FitsKey *pkey;
1548 FitsKey **kwds;
1549 char *p;
1550 char *q;
1551 int m,n,i,j,k;
1552 long w,d,e;
1553 long lm;
1554 int mcol;
1555
1556 /* excluded, non-index keywords (allowed in tile-compressed images) */
1557 char* exlkey[] = {"BSCALE","BZERO", "BUNIT", "BLANK", "DATAMAX",
1558 "DATAMIN" };
1559 int nexlkey = 6;
1560
1561 /* floating WCS keywords */
1562 char *cfltkeys[] = {"TCRVL","TCDLT","TCRPX","TCROT" };
1563 int ncfltkeys = 4;
1564
1565 /* string WCS keywords */
1566 char *cstrkeys[] = {"TCTYP","TCUNI" };
1567 int ncstrkeys = 2
1568 ;
1569 int numusrkey;
1570
1571 numusrkey = hduptr->tkeys;
1572 mcol = hduptr->ncols;
1573 kwds = hduptr->kwds;
1574
1575 if(mcol <= 0) goto OTHERKEY;
1576 /* set the ttype, ttform, tunit for tables */
1577 ttype = (char **)calloc(mcol, sizeof(char *));
1578 tform = (char **)calloc(mcol, sizeof(char *));
1579 tunit = (char **)calloc(mcol, sizeof(char *));
1580 for (i=0; i< mcol; i++) {
1581 ttype[i] = snull;
1582 tform[i] = snull;
1583 tunit[i] = snull;
1584 }
1585
1586 strcpy(temp,"TFIELDS");
1587 ptemp = temp;
1588 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1589 if( k >= 0) {
1590 pkey = hduptr->kwds[k];
1591 check_fixed_int(cards[pkey->kindex - 1], out);
1592 }
1593
1594 strcpy(temp,"TTYPE");
1595 ptemp = temp;
1596 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1597 for (j = k; j< k+n ; j++){
1598 pkey = hduptr->kwds[j];
1599 p = pkey->kname;
1600 p += 5;
1601 if(!isdigit((int)*p)) continue;
1602
1603 check_str(pkey,out);
1604 i = (int) strtol(p,NULL,10) -1 ;
1605 if(i>= 0 && i < mcol) {
1606 ttype[i] = pkey->kvalue;
1607 }
1608 else {
1609 sprintf(errmes,
1610 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
1611 pkey->kindex,pkey->kname,i+1,mcol);
1612 wrterr(out,errmes,2);
1613 }
1614 }
1615
1616 strcpy(temp,"TFORM");
1617 ptemp = temp;
1618 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1619 for (j = k; j< k + n ; j++){
1620 pkey = hduptr->kwds[j];
1621 p = pkey->kname;
1622 p += 5;
1623 if(!isdigit((int)*p)) continue;
1624
1625 check_str(pkey,out);
1626
1627 /* TFORMn keyword no longer required to be padded to at least 8 characters
1628 check_fixed_str(cards[pkey->kindex - 1], out);
1629 */
1630
1631 if(*(pkey->kvalue) == ' ') {
1632 sprintf(errmes,"Keyword #%d, %s: TFORM=\"%s\" ",
1633 pkey->kindex,pkey->kname, pkey->kvalue);
1634 strcat(errmes,
1635 "should not have leading space.");
1636 wrterr(out,errmes,1);
1637 }
1638
1639 i = (int) strtol(p,NULL,10) -1 ;
1640 if(i>= 0 && i < mcol) {
1641 tform[i] = pkey->kvalue;
1642 }
1643 else {
1644 sprintf(errmes,
1645 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
1646 pkey->kindex,pkey->kname,i+1,mcol);
1647 wrterr(out,errmes,2);
1648 }
1649
1650 p = pkey->kvalue;
1651 while(*p != ' ' && *p != '\0') {
1652 if( !isdigit((int)*p) && !isupper((int)*p) && *p != '.' && *p != ')'
1653 && *p != '(' ) {
1654 sprintf(errmes,
1655 "Keyword #%d, %s: The value %s has character %c which is not uppercase letter.",
1656 pkey->kindex,pkey->kname,pkey->kvalue,*p);
1657 wrterr(out,errmes,1);
1658 }
1659
1660 p++;
1661 }
1662 }
1663
1664 strcpy(temp,"TUNIT");
1665 ptemp = temp;
1666 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1667 for (j = k; j< k + n ; j++){
1668 pkey = hduptr->kwds[j];
1669 p = pkey->kname;
1670 p += 5;
1671 if(!isdigit((int)*p)) continue;
1672
1673 check_str(pkey,out);
1674 i = (int) strtol(p,NULL,10) -1 ;
1675 if(i>= 0 && i < mcol) {
1676 tunit[i] = pkey->kvalue;
1677 }
1678 else {
1679 sprintf(errmes,
1680 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
1681 pkey->kindex,pkey->kname,i+1,mcol);
1682 wrterr(out,errmes,1);
1683 }
1684 }
1685
1686 /* Check TDISPn keywords */
1687 strcpy(temp,"TDISP");
1688 ptemp = temp;
1689 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1690 for (j = k; j< k + n ; j++){
1691 p = kwds[j]->kname;
1692 p += 5;
1693 if(!isdigit((int)*p)) continue;
1694
1695 if (*(kwds[j]->kvalue) == '\0') continue; /* ignore blank string */
1696 check_str(kwds[j],out);
1697 if(*(kwds[j]->kvalue) == ' ') {
1698 sprintf(errmes,"Keyword #%d, %s: TDISP=\"%s\" ",
1699 kwds[j]->kindex,kwds[j]->kname,kwds[j]->kvalue);
1700 strcat(errmes,
1701 "should not have leading space.");
1702 wrterr(out,errmes,1);
1703 }
1704
1705
1706 i = (int) strtol(p,NULL,10) -1 ;
1707 if(i< 0 || i >= mcol ) {
1708 sprintf(errmes,
1709 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
1710 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
1711 wrterr(out,errmes,1);
1712 continue;
1713 }
1714 p = kwds[j]->kvalue;
1715 switch (*p) {
1716 case 'A':
1717 p++;
1718 w = 0;
1719 w = strtol(p,NULL,10);
1720 if( !w || w == LONG_MAX || w == LONG_MIN) {
1721 sprintf(errmes,
1722 "Keyword #%d, %s: invalid format \"%s\".",
1723 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue);
1724 wrterr(out,errmes,1);
1725 }
1726 if(strchr(tform[i],'A') == NULL ){
1727 sprintf(errmes,
1728 "Keyword #%d, %s: Format \"%s\" cannot be used for TFORM \"%s\".",
1729 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue, tform[i]);
1730 wrterr(out,errmes,1);
1731 }
1732 break;
1733 case 'L':
1734 p++;
1735 w = 0;
1736 w = strtol(p,NULL,10);
1737 if(!w || w == LONG_MAX || w == LONG_MIN) {
1738 sprintf(errmes,
1739 "Keyword #%d, %s: invalid format \"%s\".",
1740 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue);
1741 wrterr(out,errmes,1);
1742 }
1743 if(strchr(tform[i],'L') == NULL ){
1744 sprintf(errmes,
1745 "Keyword #%d, %s: Format %s cannot be used for TFORM \"%s\".",
1746 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue, tform[i]);
1747 wrterr(out,errmes,1);
1748 }
1749 break;
1750 case 'I': case 'B': case 'O': case 'Z':
1751 p++;
1752 w = 0;
1753 w = strtol(p,NULL,10);
1754 if((q = strchr(p,'.')) != NULL) {
1755 p = q;
1756 p++;
1757 lm = strtol(p,NULL,10);
1758 }
1759 else {
1760 lm = -1; /* no minimum digit field */
1761 }
1762 if(!w || w == LONG_MAX || w == LONG_MIN ||
1763 lm == LONG_MAX || lm == LONG_MIN || w < lm ) {
1764 sprintf(errmes,
1765 "Keyword #%d, %s: invalid format \"%s\".",
1766 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue);
1767 wrterr(out,errmes,1);
1768 }
1769 if(strchr(tform[i],'I') == NULL &&
1770 strchr(tform[i],'J') == NULL &&
1771 strchr(tform[i],'K') == NULL &&
1772 strchr(tform[i],'B') == NULL &&
1773 strchr(tform[i],'X') == NULL ){
1774 sprintf(errmes,
1775 "Keyword #%d, %s: Format \"%s\" cannot be used for TFORM \"%s\".",
1776 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue, tform[i]);
1777 wrterr(out,errmes,1);
1778 }
1779 break;
1780 case 'F':
1781 p++;
1782 d = -1;
1783 w = 0;
1784 w = strtol(p,NULL,10);
1785 if((q = strchr(p,'.')) != NULL) {
1786 p = q;
1787 p++;
1788 d = strtol(p,NULL,10);
1789 }
1790 if(!w || w == LONG_MAX || w == LONG_MIN ||
1791 d == -1 || d == LONG_MAX || d == LONG_MIN || w < d+1 ) {
1792 sprintf(errmes,
1793 "Keyword #%d, %s: invalid format \"%s\".",
1794 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue);
1795 wrterr(out,errmes,1);
1796 }
1797 if(strchr(tform[i],'E') == NULL &&
1798 strchr(tform[i],'F') == NULL &&
1799 strchr(tform[i],'C') == NULL &&
1800 strchr(tform[i],'D') == NULL &&
1801 strchr(tform[i],'M') == NULL &&
1802 strchr(tform[i],'I') == NULL &&
1803 strchr(tform[i],'J') == NULL &&
1804 strchr(tform[i],'B') == NULL &&
1805 strchr(tform[i],'X') == NULL ){
1806 sprintf(errmes,
1807 "Keyword #%d, %s: Format \"%s\" cannot be used for TFORM \"%s\".",
1808 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue, tform[i]);
1809 wrterr(out,errmes,1);
1810 }
1811 break;
1812 case 'E': case 'D':
1813 p++;
1814 w = 0;
1815 e = 0;
1816 d = 0;
1817 if(*p == 'N' || *p == 'S') { p++; e = 2;}
1818 w = strtol(p,NULL,10);
1819 if((q = strchr(p,'.')) != NULL) {
1820 p = q;
1821 p++;
1822 d = strtol(p,NULL,10);
1823 }
1824 if((q = strchr(p,'E')) != NULL) {
1825 p = q;
1826 p++;
1827 e = strtol(p,NULL,10);
1828 }
1829 else {
1830 e = 2;
1831 }
1832 if(!w || w == LONG_MAX || w == LONG_MIN ||
1833 !d || d == LONG_MAX || d == LONG_MIN ||
1834 !e || e == LONG_MAX || e == LONG_MIN ||
1835 w < d+e+3) {
1836 sprintf(errmes,
1837 "Keyword #%d, %s: invalid format \"%s\".",
1838 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue);
1839 wrterr(out,errmes,1);
1840 }
1841 if(strchr(tform[i],'E') == NULL &&
1842 strchr(tform[i],'F') == NULL &&
1843 strchr(tform[i],'C') == NULL &&
1844 strchr(tform[i],'D') == NULL &&
1845 strchr(tform[i],'M') == NULL &&
1846 strchr(tform[i],'I') == NULL &&
1847 strchr(tform[i],'J') == NULL &&
1848 strchr(tform[i],'B') == NULL &&
1849 strchr(tform[i],'X') == NULL ){
1850 sprintf(errmes,
1851 "Keyword #%d, %s: Format \"%s\" cannot be used for TFORM \"%s\".",
1852 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue, tform[i]);
1853 wrterr(out,errmes,1);
1854 }
1855 break;
1856 case 'G':
1857 p++;
1858 e = 0;
1859 d = 0;
1860 w = 0;
1861 w = strtol(p,NULL,10);
1862 if((q = strchr(p,'.')) != NULL) {
1863 p = q;
1864 p++;
1865 d = strtol(p,NULL,10);
1866 }
1867 if((q = strchr(p,'E')) != NULL) {
1868 p = q;
1869 p++;
1870 e = strtol(p,NULL,10);
1871 }
1872 else {
1873 e = 2;
1874 }
1875 if(!w || w == LONG_MAX || w == LONG_MIN ||
1876 !d || d == LONG_MAX || d == LONG_MIN ||
1877 !e || e == LONG_MAX || e == LONG_MIN ){
1878 sprintf(errmes,
1879 "Keyword #%d, %s: invalid format \"%s\".",
1880 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue);
1881 wrterr(out,errmes,1);
1882 }
1883 break;
1884 default:
1885 sprintf(errmes,
1886 "Keyword #%d, %s: invalid format \"%s\".",
1887 kwds[j]->kindex,kwds[j]->kname, kwds[j]->kvalue);
1888 wrterr(out,errmes,1);
1889 break;
1890 }
1891 }
1892
1893 OTHERKEY:
1894 if (!(hduptr->istilecompressed) ) {
1895 /* tile compressed images can have these keywords */
1896 for (i = 0; i < nexlkey; i++) {
1897 strcpy(temp,exlkey[i]);
1898 ptemp = temp;
1899 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
1900 if(k > -1) {
1901 pkey = hduptr->kwds[k];
1902 sprintf( errmes,
1903 "Keyword #%d, %s is not allowed in the Bin/ASCII table.",
1904 pkey->kindex,pkey->kname);
1905 wrterr(out,errmes,1);
1906 }
1907 }
1908
1909 /* search for excluded indexed keywords */
1910
1911 /* these WCS keywords are all allowed (changed July 2010)
1912 for (i = 0; i < nexlkeys; i++) {
1913 strcpy(temp,exlkeys[i]);
1914 ptemp = temp;
1915 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1916 if(k < 0) continue;
1917 for (j = k; j < k+n; j++) {
1918 pkey = hduptr->kwds[j];
1919
1920 p = kwds[j]->kname;
1921 p += strlen(temp);
1922 if(!isdigit((int)*p)) continue;
1923
1924 sprintf( errmes,
1925 "Keyword #%d, %s is not allowed in the Bin/ASCII table.",
1926 pkey->kindex,pkey->kname);
1927 wrterr(out,errmes,1);
1928 }
1929 }
1930 */
1931 }
1932
1933 /* test datatype of reserved indexed floating point WCS keywords */
1934 for (i = 0; i < ncfltkeys; i++) {
1935 strcpy(temp,cfltkeys[i]);
1936 ptemp = temp;
1937 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1938 if(k < 0) continue;
1939
1940 for (j = k; j < k+n; j++) {
1941 pkey = hduptr->kwds[j];
1942
1943 p = kwds[j]->kname;
1944 p += strlen(temp);
1945 if(!isdigit((int)*p)) continue;
1946
1947 if (!check_flt(pkey,out) )continue;
1948
1949 m = (int)strtol(p,NULL,10);
1950 if (m < 1 || m > mcol) {
1951 sprintf( errmes,
1952 "Keyword #%d, %s: index %d is not in range 1-%d (TFIELD).",
1953 pkey->kindex,pkey->kname,m,mcol);
1954 wrterr(out,errmes,1);
1955 }
1956 }
1957 }
1958
1959 /* test datatype of reserved indexed string WCS keywords */
1960 for (i = 0; i < ncstrkeys; i++) {
1961 strcpy(temp,cstrkeys[i]);
1962 ptemp = temp;
1963 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
1964 if(k < 0) continue;
1965
1966 for (j = k; j < k+n; j++) {
1967 pkey = hduptr->kwds[j];
1968
1969 p = kwds[j]->kname;
1970 p += strlen(temp);
1971 if(!isdigit((int)*p)) continue;
1972
1973 if (!check_str(pkey,out) )continue;
1974
1975 m = (int)strtol(p,NULL,10);
1976 if (m < 1 || m > mcol) {
1977 sprintf( errmes,
1978 "Keyword #%d, %s: index %d is not in range 1-%d (TFIELD).",
1979 pkey->kindex,pkey->kname,m,mcol);
1980 wrterr(out,errmes,1);
1981 }
1982
1983 }
1984 }
1985 return;
1986 }
1987
1988 /*************************************************************
1989 *
1990 * test_asc_ext
1991 *
1992 * Test the ascii table extension header
1993 *
1994 *
1995 *************************************************************/
test_asc_ext(fitsfile * infits,FILE * out,FitsHdu * hduptr)1996 void test_asc_ext(fitsfile *infits, /* input fits file */
1997 FILE* out, /* output ascii file */
1998 FitsHdu *hduptr /* information about header */
1999 )
2000 {
2001 int numusrkey;
2002 FitsKey **kwds;
2003 FitsKey *pkey;
2004 char *p;
2005 int i,j,k;
2006 int n;
2007 int mcol;
2008
2009 numusrkey = hduptr->tkeys;
2010 kwds = hduptr->kwds;
2011 mcol = hduptr->ncols;
2012
2013 /* The XTENSION, BITPIX, NAXIS, NAXISn, TFIELDS, PCOUNT, GCOUNT, TFORMn,
2014 TBCOLn, TTYPEn keywords have been checked in CFITSIO */
2015
2016 /* General extension */
2017 test_ext(infits,out,hduptr);
2018
2019 /* general table */
2020 test_tbl(infits,out,hduptr);
2021
2022 /* Check TBCOLn */
2023 strcpy(temp,"TBCOL");
2024 ptemp = temp;
2025 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2026 for (j = k; j< k + n ; j++){
2027 pkey = hduptr->kwds[j];
2028 p = pkey->kname;
2029 p += 5;
2030 if(!isdigit((int)*p)) continue;
2031
2032 check_int(pkey,out);
2033
2034 i = (int) strtol(p,NULL,10) ;
2035 if(i< 0 || i > mcol) {
2036 sprintf(errmes,
2037 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2038 pkey->kindex,pkey->kname,i,mcol);
2039 wrterr(out,errmes,1);
2040 }
2041 else {
2042 check_fixed_int(cards[pkey->kindex - 1], out);
2043 }
2044 }
2045
2046 /* Check TNULLn, TSCALn, and TZEORn keywords */
2047 strcpy(temp,"TNULL");
2048 ptemp = temp;
2049 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2050 for (j = k; j< k + n ; j++){
2051 p = kwds[j]->kname;
2052 p += 5;
2053 if(!isdigit((int)*p)) continue;
2054 i = (int) strtol(p,NULL,10) -1;
2055 if(i< 0 || i >= mcol) {
2056 sprintf(errmes,
2057 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2058 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
2059 wrterr(out,errmes,1);
2060 }
2061 check_str(kwds[j],out);
2062 }
2063
2064 strcpy(temp,"TSCAL");
2065 ptemp = temp;
2066 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2067 for (j = k; j< k + n ; j++){
2068 p = kwds[j]->kname;
2069 p += 5;
2070 if(!isdigit((int)*p)) continue;
2071 i = (int) strtol(p,NULL,10) -1 ;
2072 if(check_flt(kwds[j],out)){
2073 if(strtod(kwds[j]->kvalue,NULL) == 0.0) {
2074 sprintf(errmes,"Keyword #%d, %s: Scaling factor is zero.",
2075 kwds[j]->kindex,kwds[j]->kname);
2076 wrtwrn(out,errmes,0);
2077 }
2078 }
2079 if(i< 0 || i >= mcol) {
2080 sprintf(errmes,
2081 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2082 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
2083 wrterr(out,errmes,1);
2084 continue;
2085 }
2086 if(strchr(tform[i],'A') != NULL) {
2087 sprintf(errmes,
2088 "Keyword #%d, %s may not be used for the A-format fields.",
2089 kwds[j]->kindex,kwds[j]->kname);
2090 wrterr(out,errmes,1);
2091 }
2092 }
2093
2094 strcpy(temp,"TZERO");
2095 ptemp = temp;
2096 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2097 for (j = k; j< k + n ; j++){
2098 p = kwds[j]->kname;
2099 p += 5;
2100 if(!isdigit((int)*p)) continue;
2101 check_flt(kwds[j],out);
2102 i = (int) strtol(p,NULL,10) -1 ;
2103 if(i< 0 || i >= mcol) {
2104 sprintf(errmes,
2105 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2106 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
2107 wrterr(out,errmes,1);
2108 continue;
2109 }
2110 if(strchr(tform[i],'A') != NULL) {
2111 sprintf(errmes,
2112 "Keyword #%d, %s may not be used for the A-format fields.",
2113 kwds[j]->kindex,kwds[j]->kname);
2114 wrterr(out,errmes,1);
2115 }
2116 }
2117
2118 strcpy(temp,"TDIM");
2119 ptemp = temp;
2120 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2121 for (j = k; j< k + n ; j++){
2122 p = kwds[j]->kname;
2123 p += 4;
2124 if(!isdigit((int)*p)) continue;
2125
2126 pkey = hduptr->kwds[j];
2127 sprintf( errmes,
2128 "Keyword #%d, %s is not allowed in the ASCII table.",
2129 pkey->kindex,pkey->kname);
2130 wrterr(out,errmes,1);
2131 }
2132
2133 strcpy(temp,"THEAP");
2134 ptemp = temp;
2135 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
2136 if (k > -1) {
2137 pkey = hduptr->kwds[k];
2138 sprintf( errmes,
2139 "Keyword #%d, %s is not allowed in the ASCII table.",
2140 pkey->kindex,pkey->kname);
2141 wrterr(out,errmes,1);
2142 }
2143
2144
2145 /* check whether the column name is unique */
2146 test_colnam(out, hduptr);
2147 return ;
2148 }
2149
2150
2151 /*************************************************************
2152 *
2153 * test_bin_ext
2154 *
2155 * Test the binary table extension header
2156 *
2157 *
2158 *************************************************************/
test_bin_ext(fitsfile * infits,FILE * out,FitsHdu * hduptr)2159 void test_bin_ext(fitsfile *infits, /* input fits file */
2160 FILE* out, /* output ascii file */
2161 FitsHdu *hduptr /* information about header */
2162 )
2163 {
2164 FitsKey *pkey;
2165 int i,j,k,n;
2166 long l;
2167 int status = 0;
2168 char *p;
2169
2170 int ntdim;
2171 long tdim[10];
2172 int repeat, width;
2173 FitsKey **kwds;
2174 int numusrkey;
2175 int mcol, vla, datatype;
2176
2177 /* The indexed keywords excluded from ascii table */
2178 char *exlkeys[] = { "TBCOL"};
2179 int nexlkeys = 1;
2180
2181 kwds = hduptr->kwds;
2182 numusrkey = hduptr->tkeys;
2183 mcol = hduptr->ncols;
2184
2185 /* General extension */
2186 test_ext(infits,out,hduptr);
2187
2188 /* General table */
2189 test_tbl(infits,out,hduptr);
2190
2191 /* The XTENSION, BITPIX, NAXIS, NAXISn, TFIELDS, PCOUNT, GCOUNT, TFORMn,
2192 TTYPEn keywords have been checked in CFITSIO */
2193
2194 /* Check TNULLn keywords */
2195 strcpy(temp,"TNULL");
2196 ptemp = temp;
2197 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2198 for (j = k; j< k + n ; j++){
2199 p = kwds[j]->kname;
2200 p += 5;
2201 if(!isdigit((int)*p)) continue;
2202 check_int(kwds[j],out);
2203 i = (int) strtol(p,NULL,10) -1 ;
2204 if(i< 0 || i >= mcol) {
2205 sprintf(errmes,
2206 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2207 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
2208 wrterr(out,errmes,1);
2209 continue;
2210 }
2211 if(strchr(tform[i],'B') == NULL &&
2212 strchr(tform[i],'I') == NULL &&
2213 strchr(tform[i],'J') == NULL &&
2214 strchr(tform[i],'K') == NULL ) {
2215 sprintf(errmes,
2216 "Keyword #%d, %s is used for the column with format \"%s \".",
2217 kwds[j]->kindex,kwds[j]->kname,tform[i]);
2218 wrterr(out,errmes,2);
2219 }
2220 l = strtol(kwds[j]->kvalue,NULL,10);
2221 if(strchr(tform[i],'B') != NULL && (
2222 l < 0 || l > 255) ) {
2223 sprintf(errmes,"Keyword #%d, %s: The value %ld",
2224 kwds[j]->kindex,kwds[j]->kname, l);
2225 strcat(errmes, " is not in the range of datatype B.");
2226 wrtwrn(out,errmes,0);
2227 }
2228 l = strtol(kwds[j]->kvalue,NULL,10);
2229 if(strchr(tform[i],'I') != NULL && (
2230 l < -32768 || l > 32767) ) {
2231 sprintf(errmes,"Keyword #%d, %s: The value %ld",
2232 kwds[j]->kindex,kwds[j]->kname, l);
2233 strcat(errmes, " is not in the range of datatype I ");
2234 wrtwrn(out,errmes,0);
2235 }
2236 }
2237
2238 /* Check TSCALn keywords */
2239 strcpy(temp,"TSCAL");
2240 ptemp = temp;
2241 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2242 for (j = k; j< k + n ; j++){
2243 p = kwds[j]->kname;
2244 p += 5;
2245 if(!isdigit((int)*p)) continue;
2246 if (check_flt(kwds[j],out) && strtod(kwds[j]->kvalue,NULL) == 0.0) {
2247 sprintf(errmes,"Keyword #%d, %s:",
2248 kwds[j]->kindex,kwds[j]->kname);
2249 strcat(errmes,
2250 "The scaling factor is zero.");
2251 wrtwrn(out,errmes,0);
2252 }
2253 i = (int) strtol(p,NULL,10) -1 ;
2254 if(i< 0 || i >= mcol) {
2255 sprintf(errmes,
2256 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2257 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
2258 wrterr(out,errmes,1);
2259 continue;
2260 }
2261 if(strchr(tform[i],'A') != NULL ||
2262 strchr(tform[i],'L') != NULL ||
2263 strchr(tform[i],'X') != NULL ) {
2264 sprintf(errmes,
2265 "Keyword #%d, %s is used in A, L, or X column. ",
2266 kwds[j]->kindex,kwds[j]->kname);
2267 wrterr(out,errmes,1);
2268 }
2269 }
2270
2271 /* Check TZEROn keywords */
2272 strcpy(temp,"TZERO");
2273 ptemp = temp;
2274 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2275 for (j = k; j< k + n ; j++){
2276 p = kwds[j]->kname;
2277 p += 5;
2278 if(!isdigit((int)*p)) continue;
2279 check_flt(kwds[j],out);
2280 i = (int) strtol(p,NULL,10) -1 ;
2281 if(i< 0 || i >= mcol) {
2282 sprintf(errmes,
2283 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2284 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
2285 wrterr(out,errmes,1);
2286 continue;
2287 }
2288 if(strchr(tform[i],'A') != NULL &&
2289 strchr(tform[i],'L') != NULL &&
2290 strchr(tform[i],'X') != NULL ) {
2291 sprintf(errmes,
2292 "Keyword #%d, %s is used in A, L, or X column. ",
2293 kwds[j]->kindex,kwds[j]->kname);
2294 wrterr(out,errmes,1);
2295 }
2296 }
2297
2298 /* Check THEAP keyword */
2299 hduptr->heap = (hduptr->naxes[0]) * (hduptr->naxes[1]);
2300 strcpy(temp,"THEAP");
2301 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
2302 if(k > -1) {
2303 if(check_int(kwds[k],out))
2304 hduptr->heap = (int) strtol(hduptr->kwds[k]->kvalue,NULL,10);
2305 if(!hduptr->pcount) {
2306 sprintf( errmes,
2307 "Pcount is zero, but keyword THEAP is present at record #%d). ",
2308 kwds[k]->kindex);
2309 wrterr(out,errmes,1);
2310 }
2311 }
2312
2313 /* if PCOUNT != 0, test that there is at least 1 variable length array column */
2314 vla = 0;
2315 if(hduptr->pcount) {
2316 for (i=0; i< mcol; i++){
2317 if(fits_get_coltype(infits, i+1, &datatype, NULL, NULL, &status)){
2318 sprintf(errmes,"Column #%d: ",i);
2319 wrtferr(out,errmes, &status,2);
2320 }
2321 if (datatype < 0) {
2322 vla = 1;
2323 break;
2324 }
2325 }
2326
2327 if (vla == 0) {
2328 sprintf(errmes,
2329 "PCOUNT = %ld, but there are no variable-length array columns.",
2330 (long) hduptr->pcount);
2331 wrtwrn(out,errmes,0);
2332 }
2333 }
2334
2335
2336 /* Check TDIMn keywords */
2337 strcpy(temp,"TDIM");
2338 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2339 for (j = k; j< k + n ; j++){
2340 pkey = kwds[j];
2341 p = pkey->kname;
2342 p += 4;
2343 if(!isdigit((int)*p)) continue;
2344 check_str(kwds[j],out);
2345 if(*(pkey->kvalue) == ' ') {
2346 sprintf(errmes,"Keyword #%d, %s: TDIM=\"%s\" ",
2347 pkey->kindex,pkey->kname,pkey->kvalue);
2348 strcat(errmes,
2349 "should not have leading space.");
2350 wrterr(out,errmes,1);
2351 continue;
2352 }
2353 i = (int) strtol(p,NULL,10) -1 ;
2354 if(i< 0 || i >= mcol) {
2355 sprintf(errmes,
2356 "Keyword #%d, %s: invalid index %d (> TFIELD = %d).",
2357 kwds[j]->kindex,kwds[j]->kname,i+1,mcol);
2358 wrterr(out,errmes,1);
2359 continue;
2360 }
2361 if(fits_decode_tdim(infits,pkey->kvalue,i+1,10,&ntdim,tdim, &status)){
2362 sprintf(errmes,"Keyword #%d, %s: ",
2363 kwds[j]->kindex,kwds[j]->kname);
2364 wrtferr(out,errmes,&status,1);
2365 }
2366 }
2367
2368 /* check the local convension "rAw"*/
2369 for (i = 0; i < hduptr->ncols; i++) {
2370 if((p = strchr(tform[i],'A'))==NULL) continue;
2371 repeat = (int) strtol(tform[i],NULL,10);
2372 p++;
2373 if(!isdigit((int)*p))continue;
2374 width = (int)strtol(p,NULL,10);
2375 if(repeat%width != 0) {
2376 sprintf(errmes,
2377 "TFORM %s of column %d: repeat %d is not the multiple of the width %d",
2378 tform[i], i+1, repeat, width);
2379 wrtwrn(out,errmes,0);
2380 }
2381 }
2382
2383 for (i = 0; i < nexlkeys; i++) {
2384 strcpy(temp,exlkeys[i]);
2385 ptemp = temp;
2386 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2387 if(k < 0) continue;
2388 for (j = k; j < k+n; j++) {
2389 pkey = hduptr->kwds[j];
2390
2391 p = kwds[j]->kname;
2392 p += strlen(temp);
2393 if(!isdigit((int)*p)) continue;
2394
2395 sprintf( errmes,
2396 "Keyword #%d, %s is not allowed in the Binary table.",
2397 pkey->kindex,pkey->kname);
2398 wrterr(out,errmes,1);
2399 }
2400 }
2401
2402 /* check whether the column name is unique */
2403 test_colnam(out, hduptr);
2404 return ;
2405 }
2406
2407 /*************************************************************
2408 *
2409 * test_header
2410 *
2411 * Test the general keywords that can be in any header
2412 *
2413 *
2414 *************************************************************/
test_header(fitsfile * infits,FILE * out,FitsHdu * hduptr)2415 void test_header(
2416 fitsfile *infits, /* input fits file */
2417 FILE* out, /* output ascii file */
2418 FitsHdu *hduptr /* information about header */
2419 )
2420 {
2421 /* common mandatory keywords */
2422 char *mandkey[] = {"SIMPLE", "BITPIX", "NAXIS",
2423 "XTENSION", "END"}; /* not including NAXIS */
2424 int nmandkey = 5;
2425
2426
2427 /* string keywords */
2428 char *strkey[] = {"EXTNAME", "ORIGIN", "AUTHOR","CREATOR","REFERENC","TELESCOP",
2429 "INSTRUME", "OBSERVER", "OBJECT"};
2430 int nstrkey = 9;
2431
2432 /* int keywords */
2433 char *intkey[] = {"EXTVER", "EXTLEVEL"};
2434 int nintkey = 2;
2435
2436 /* floating keywords */
2437 char *fltkey[] = {"EQUINOX", "MJD-OBS", "MJD-AVG"};
2438 int nfltkey = 3;
2439
2440 FitsKey** kwds; /* FitsKey structure array */
2441 int numusrkey;
2442
2443 int i,j,k,n;
2444 long lv;
2445 char* pt;
2446 char **pp;
2447 int status = 0;
2448 int yr, mn, dy, hr, min; /* time */
2449 double sec;
2450 int yy;
2451
2452 kwds = hduptr->kwds;
2453 numusrkey = hduptr->tkeys;
2454
2455 /* Check the mandatory keywords */
2456 for (i = 0; i < nmandkey; i++) {
2457 pp = &(mandkey[i]);
2458 key_match(tmpkwds,numusrkey,pp,1,&k,&n);
2459 if(k > -1) {
2460 for ( j = k; j < k + n; j++) {
2461 sprintf(errmes,
2462 "Keyword #%d, %s is duplicated or out of order.",
2463 kwds[j]->kindex,kwds[j]->kname);
2464 wrterr(out,errmes,1);
2465 }
2466 }
2467 }
2468
2469 /* check the NAXIS index keyword */
2470 strcpy(temp,"NAXIS");
2471 ptemp = temp;
2472 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2473 for ( j = k; j < k + n; j++) {
2474 pt = kwds[j]->kname+5;
2475 lv = strtol(pt,NULL,10);
2476 if(lv > 0 ){
2477 if(kwds[j]->kindex != 3 + lv) {
2478 sprintf(errmes,
2479 "Keyword #%d, %s is duplicated or out of order.",
2480 kwds[j]->kindex,kwds[j]->kname);
2481 wrterr(out,errmes,1);
2482 }
2483 if(lv > hduptr->naxis) {
2484 sprintf(errmes,
2485 "Keyword #%d, %s is not allowed (with n > NAXIS =%d).",
2486 kwds[j]->kindex,kwds[j]->kname,hduptr->naxis);
2487 wrterr(out,errmes,1);
2488 }
2489 }
2490 }
2491
2492 /* Check the deprecated keywords */
2493 strcpy(temp,"EPOCH");
2494 ptemp = temp;
2495 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
2496 if(k > -1) {
2497 sprintf(errmes,
2498 "Keyword #%d, %s is deprecated. Use EQUINOX instead.",
2499 kwds[k]->kindex, kwds[k]->kname);
2500 wrtwrn(out,errmes,0);
2501 check_flt(kwds[k],out);
2502 }
2503
2504
2505 /* Check the DATExxxx keyword */
2506 strcpy(temp,"DATE");
2507 ptemp = temp;
2508 key_match(tmpkwds,numusrkey,&ptemp,0,&k,&n);
2509 for (j = k; j< n + k ; j++){
2510 check_str(kwds[j],out);
2511 if(fits_str2time(kwds[j]->kvalue, &yr, &mn, &dy, &hr, &min,
2512 &sec, &status)){
2513 sprintf(errmes,"Keyword #%d, %s: ", kwds[j]->kindex,kwds[j]->kname);
2514 wrtserr(out,errmes,&status,1);
2515 }
2516 if( (pt = strchr(kwds[j]->kvalue,'/'))!=NULL) {
2517 pt +=4;
2518 yy = (int) strtol(pt,NULL,10);
2519 if(0 <= yy && yy <=10) {
2520 sprintf(errmes,
2521 "Keyword #%d, %s %s intends to mean year 20%-2.2d?",
2522 kwds[j]->kindex, kwds[j]->kname, kwds[j]->kvalue, yy);
2523 wrtwrn(out,errmes,0);
2524 }
2525 }
2526 }
2527
2528 /* Check the reserved string keywords */
2529 for (i = 0; i < nstrkey; i++) {
2530 strcpy(temp,strkey[i]);
2531 ptemp = temp;
2532 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
2533 if(k > -1) check_str(kwds[k],out);
2534 }
2535
2536 /* Check the reserved int keywords */
2537 for (i = 0; i < nintkey; i++) {
2538 strcpy(temp,intkey[i]);
2539 ptemp = temp;
2540 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
2541 if(k > -1) check_int(kwds[k],out);
2542 }
2543
2544 /* Check reserved floating keywords */
2545 for (i = 0; i < nfltkey; i++) {
2546 strcpy(temp,fltkey[i]);
2547 ptemp = temp;
2548 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
2549 if(k > -1) check_flt(kwds[k],out);
2550 }
2551
2552 /* Check the duplication of the keywords */
2553 for (i = 0; i < numusrkey-1; i++) {
2554 if(!strcmp(tmpkwds[i],tmpkwds[i+1])) {
2555 sprintf(errmes,
2556 "Keyword %s is duplicated in card #%d and card #%d.",
2557 kwds[i]->kname, kwds[i]->kindex, kwds[i+1]->kindex);
2558 wrtwrn(out,errmes,0);
2559 }
2560 }
2561
2562 /* check the long string convention */
2563 if (hduptr->use_longstr == 1) {
2564 strcpy(temp,"LONGSTRN");
2565 ptemp = temp;
2566 key_match(tmpkwds,numusrkey,&ptemp,1,&k,&n);
2567 if(k <= -1) {
2568 sprintf(errmes,
2569 "The OGIP long string keyword convention is used without the recommended LONGSTRN keyword. ");
2570 wrtwrn(out,errmes,1);
2571 }
2572 }
2573
2574 /* disabled this routine because it doesn't perform an useful tests
2575 test_img_wcs(infits, out, hduptr);
2576
2577 */
2578 return;
2579 }
2580
2581
2582 /*************************************************************
2583 *
2584 * key_match
2585 *
2586 * find the keywords whose name match the pattern. The keywords
2587 * name is stored in a sorted array.
2588 *
2589 *
2590 *************************************************************/
key_match(char ** strs,int nstr,char ** pattern,int exact,int * ikey,int * mkey)2591 void key_match(char **strs, /* fits keyname array */
2592 int nstr, /* total number of keys */
2593 char **pattern, /* wanted pattern */
2594 int exact, /* exact matching or pattern matching
2595 exact = 1: exact matching.
2596 exact = 0: pattern matching.
2597 Any keywords with "patten"* is included
2598 */
2599
2600 int *ikey, /* The element number of first key
2601 Return -99 if not found */
2602 int *mkey /* total number of key matched
2603 return -999 if not found */
2604 )
2605 {
2606 char **p;
2607 char **pi;
2608 int i;
2609 int (*fnpt)(const void *, const void *);
2610 *mkey = -999;
2611 *ikey = -99;
2612 if(exact)
2613 fnpt = compstre;
2614 else
2615 fnpt = compstrp;
2616 p = (char **)bsearch(pattern, strs, nstr,sizeof(char *), fnpt);
2617 if(p) {
2618 *mkey = 1;
2619 *ikey = p - strs;
2620 pi = p;
2621 i = *ikey - 1;
2622 p--;
2623 while(i > 0 && !fnpt(pattern, p)) {*mkey += 1; *ikey =i; i--; p--;}
2624 p = pi;
2625 i = *ikey + *mkey;
2626 p++;
2627 while(i < nstr && !fnpt(pattern, p) ) {*mkey += 1; i++; p++;}
2628 }
2629 return;
2630 }
2631
2632
2633 /*************************************************************
2634 *
2635 * test_colnam
2636 *
2637 * Test the whether the column name is unique.
2638 *
2639 *
2640 *************************************************************/
test_colnam(FILE * out,FitsHdu * hduptr)2641 void test_colnam(FILE *out,
2642 FitsHdu *hduptr)
2643 {
2644 int i,n;
2645 char *p, *q;
2646 ColName **cols;
2647 char **ttypecopy;
2648
2649 n = hduptr->ncols;
2650
2651 if(n <= 0) return;
2652 /* make a local working copy of ttype */
2653 ttypecopy = (char **)malloc(n*sizeof(char *));
2654 for (i = 0; i < n; i++) {
2655 ttypecopy[i] = (char *)malloc(FLEN_VALUE*sizeof(char));
2656 strcpy(ttypecopy[i],ttype[i]);
2657 }
2658
2659 /* check whether there are any other non ASCII-text characters
2660 (FITS standard R14). Also "uppercase" the working copies. */
2661 for (i = 0; i < n; i++) {
2662 p = ttype[i];
2663 q = ttypecopy[i];
2664 if(!strlen(p)) {
2665 sprintf(errmes,
2666 "Column #%d has no name (No TTYPE%d keyword).",i+1, i+1);
2667 wrtwrn(out,errmes,0);
2668 continue;
2669 }
2670
2671
2672 /* disable this check (it was only a warning)
2673 if( (*p > 'z' || *p < 'a') && (*p > 'Z' || *p <'A')
2674 && (*p > '9' || *p < '0') ) {
2675 sprintf(errmes,"Column #%d: Name \"%s\" does not begin with a letter or a digit.",i+1,ttype[i]);
2676 wrtwrn(out,errmes,1);
2677 }
2678 */
2679 while(*p != '\0') {
2680 if( (*p > 'z' || *p < 'a') && (*p > 'Z' || *p < 'A')
2681 && (*p > '9' || *p < '0') && (*p != '_')) {
2682 sprintf(errmes,
2683 "Column #%d: Name \"%s\" contains character \'%c\' other than letters, digits, and \"_\".",
2684 i+1,ttype[i],*p);
2685 wrtwrn(out,errmes,0);
2686 }
2687 if(*p <= 'z' || *p >= 'a') *q = toupper(*p);
2688 p++; q++;
2689 }
2690 }
2691
2692 cols = (ColName **)calloc(n, sizeof(ColName *));
2693 for (i=0; i < n; i++) {
2694 cols[i] = (ColName *)malloc(sizeof(ColName));
2695 cols[i]->name = ttypecopy[i];
2696 cols[i]->index = i+1;
2697 }
2698
2699 /* sort the column name in the ascending order of name field*/
2700 qsort(cols, n, sizeof(ColName *), compcol);
2701
2702 /* Check the duplication of the column name */
2703 for (i = 0; i < n-1; i++) {
2704 if(!strlen(cols[i]->name)) continue;
2705
2706 /* disable this warning
2707 if(!strncmp(cols[i]->name,cols[i+1]->name,16)) {
2708 sprintf(errmes,
2709 "Columns #%d, %s and #%d, %s are not unique within first 16 characters(case insensitive).",
2710 cols[i]->index, ttype[(cols[i]->index-1)],
2711 cols[i+1]->index, ttype[(cols[i+1]->index-1)]);
2712 wrtwrn(out,errmes,1);
2713 }
2714 */
2715
2716 if(!strcmp(cols[i]->name,cols[i+1]->name)) {
2717 sprintf(errmes,
2718 "Columns #%d, %s and #%d, %s are not unique (case insensitive).",
2719 cols[i]->index, ttype[(cols[i]->index-1)],
2720 cols[i+1]->index, ttype[(cols[i+1]->index-1)]);
2721 wrtwrn(out,errmes,0);
2722 }
2723 }
2724 for (i = 0; i < n; i++) { free(cols[i]); free(ttypecopy[i]);}
2725 free(cols); free(ttypecopy);
2726 return;
2727 }
2728
2729 /*************************************************************
2730 *
2731 * parse_vtform
2732 *
2733 * Parse the tform of the variable length vector.
2734 *
2735 *
2736 *************************************************************/
parse_vtform(fitsfile * infits,FILE * out,FitsHdu * hduptr,int colnum,int * datacode,long * maxlen)2737 void parse_vtform(fitsfile *infits,
2738 FILE *out,
2739 FitsHdu *hduptr,
2740 int colnum, /* column number */
2741 int* datacode, /* data code */
2742 long* maxlen /* maximum length of the vector */
2743 )
2744 {
2745 int i = 0;
2746 int status = 0;
2747 char *p;
2748
2749
2750 *maxlen = -1;
2751 strcpy(temp,tform[colnum-1]);
2752 p = temp;
2753
2754 if(isdigit((int)*p)) sscanf(ptemp,"%d",&i);
2755 if(i > 1) {
2756 sprintf(errmes,"Illegal repeat value for value %s of TFORM%d.",
2757 tform[colnum-1], colnum);
2758 wrterr(out,errmes,1);
2759 }
2760 while(isdigit((int)*p))p++;
2761
2762 if( (*p != 'P') && (*p != 'Q') ) {
2763 sprintf(errmes,
2764 "TFORM%d is not for the variable length array: %s.",
2765 colnum, tform[colnum-1]);
2766 wrterr(out,errmes,1);
2767 }
2768
2769 fits_get_coltype(infits,colnum, datacode, NULL, NULL, &status);
2770 status = 0;
2771 p += 2;
2772 if(*p != '(') return;
2773 p++;
2774 if(!isdigit((int)*p)) {
2775 sprintf(errmes, "Bad value of TFORM%d: %s.",colnum,tform[colnum-1]);
2776 wrterr(out,errmes,1);
2777 }
2778 sscanf(p,"%ld",maxlen);
2779 while(isdigit((int)*p))p++;
2780 if(*p != ')') {
2781 sprintf(errmes, "Bad value of TFORM%d: %s.",colnum,tform[colnum-1]);
2782 wrterr(out,errmes,1);
2783 }
2784 return;
2785 }
2786
2787 /*************************************************************
2788 *
2789 * print_title
2790 *
2791 * Print the title of the HDU.
2792 * when verbose < 2, called by wrterr and wrtwrn.
2793 *
2794 *************************************************************/
print_title(FILE * out,int hdunum,int hdutype)2795 void print_title(FILE* out, int hdunum, int hdutype)
2796 {
2797 static char hdutitle[64];
2798 static int oldhdu = 0;
2799
2800 /* print out the title */
2801 curhdu = hdunum;
2802 curtype = hdutype;
2803
2804 if(oldhdu == curhdu) return; /* Do not print it twice */
2805 if(curhdu == 1){
2806 sprintf(hdutitle," HDU %d: Primary Array ", curhdu);
2807 }
2808 else {
2809 switch (curtype) {
2810 case IMAGE_HDU:
2811 sprintf(hdutitle," HDU %d: Image Exten. ", curhdu);
2812 break;
2813 case ASCII_TBL:
2814 sprintf(hdutitle," HDU %d: ASCII Table ", curhdu);
2815 break;
2816 case BINARY_TBL:
2817 sprintf(hdutitle," HDU %d: BINARY Table ", curhdu);
2818 break;
2819 default:
2820 sprintf(hdutitle," HDU %d: Unknown Ext. ", curhdu);
2821 break;
2822 }
2823 }
2824 wrtsep(out,'=',hdutitle,60);
2825 wrtout(out," ");
2826 oldhdu = curhdu;
2827 if(curhdu == totalhdu) oldhdu = 0; /* reset the old hdu at the last hdu */
2828 return;
2829 }
2830
2831 /*************************************************************
2832 *
2833 * print_header
2834 *
2835 * Print the header of the HDU.
2836 *
2837 *************************************************************/
print_header(FILE * out)2838 void print_header(FILE* out)
2839 {
2840 char htemp[100];
2841 int i;
2842 for (i=1; i <= ncards; i++) {
2843 sprintf(htemp,"%4d | %s",i,cards[i-1]);
2844 wrtout(out, htemp);
2845 }
2846 wrtout(out," ");
2847 return;
2848 }
2849
2850 /*************************************************************
2851 *
2852 * print_summary
2853 *
2854 * Print out the summary of this hdu.
2855 *
2856 **************************************************************/
print_summary(fitsfile * infits,FILE * out,FitsHdu * hduptr)2857 void print_summary(fitsfile *infits, /* input fits file */
2858 FILE* out, /* output ascii file */
2859 FitsHdu *hduptr
2860 )
2861 {
2862
2863 int i = 0;
2864 char extver[10];
2865 char extnv[FLEN_VALUE];
2866 long npix;
2867 int hdutype;
2868
2869 /* get the error number and wrn number */
2870 set_hduerr(hduptr->hdunum);
2871
2872 hdutype = hduptr->hdutype;
2873 sprintf(comm," %d header keywords", hduptr->nkeys);
2874 wrtout(out,comm);
2875 wrtout(out," ");
2876 if(hdutype == ASCII_TBL || hdutype== BINARY_TBL) {
2877 sprintf(extnv, "%s",hduptr->extname);
2878 if (hduptr->extver!=-999) {
2879 sprintf(extver,"(%d)",hduptr->extver);
2880 strcat(extnv,extver);
2881 }
2882
2883 #if (USE_LL_SUFFIX == 1)
2884 sprintf(comm," %s (%d columns x %lld rows)", extnv, hduptr->ncols,
2885 hduptr->naxes[1]);
2886 #else
2887 sprintf(comm," %s (%d columns x %ld rows)", extnv, hduptr->ncols,
2888 hduptr->naxes[1]);
2889 #endif
2890 wrtout(out,comm);
2891 if(hduptr->ncols) {
2892 wrtout(out," ");
2893 sprintf(comm, " Col# Name (Units) Format");
2894 wrtout(out,comm);
2895 }
2896 for ( i = 0; i < hduptr->ncols; i++) {
2897 if(strlen(tunit[i]))
2898 sprintf(extnv,"%s (%s)",ttype[i],tunit[i]);
2899 else
2900 sprintf(extnv,"%s",ttype[i]);
2901 sprintf(comm," %3d %-20.20s %-10.10s",
2902 i+1, extnv, tform[i]);
2903 wrtout(out,comm);
2904 }
2905 }
2906 else if(hdutype == IMAGE_HDU && hduptr->isgroup) {
2907
2908 sprintf(comm, " %d Random Groups, ",hduptr->gcount);
2909
2910 switch(hduptr->bitpix) {
2911 case BYTE_IMG:
2912 strcpy(temp," 8-bit integer pixels, ");
2913 break;
2914 case SHORT_IMG:
2915 strcpy(temp," 16-bit integer pixels, ");
2916 break;
2917 case USHORT_IMG:
2918 strcpy(temp," 16-bit unsigned integer pixels, ");
2919 break;
2920 case LONG_IMG:
2921 strcpy(temp," 32-bit integer pixels, ");
2922 break;
2923 case LONGLONG_IMG:
2924 strcpy(temp," 64-bit long integer pixels, ");
2925 break;
2926 case ULONG_IMG:
2927 strcpy(temp," 32-bit unsigned integer pixels, ");
2928 break;
2929 case FLOAT_IMG:
2930 strcpy(temp," 32-bit floating point pixels, ");
2931 break;
2932 case DOUBLE_IMG:
2933 strcpy(temp," 64-bit double precision pixels, ");
2934 break;
2935 default:
2936 strcpy(temp," unknown datatype, ");
2937 break;
2938 }
2939 strcat(comm,temp);
2940
2941 sprintf(temp," %d axes ",hduptr->naxis);
2942 strcat(comm,temp);
2943
2944 #if (USE_LL_SUFFIX == 1)
2945 sprintf(temp, "(%lld",hduptr->naxes[0]);
2946 #else
2947 sprintf(temp, "(%ld",hduptr->naxes[0]);
2948 #endif
2949 strcat(comm,temp);
2950
2951 npix = hduptr->naxes[0];
2952 for ( i = 1; i < hduptr->naxis; i++){
2953 npix *= hduptr->naxes[i];
2954 #if (USE_LL_SUFFIX == 1)
2955 sprintf(temp, " x %lld",hduptr->naxes[i]);
2956 #else
2957 sprintf(temp, " x %ld",hduptr->naxes[i]);
2958 #endif
2959 strcat(comm,temp);
2960 }
2961 strcat(comm,"), ");
2962 wrtout(out,comm);
2963 }
2964 else if(hdutype == IMAGE_HDU) {
2965 if(hduptr->naxis > 0) {
2966
2967 if(hduptr->hdunum == 1) {
2968 strcpy(extnv,"");
2969 } else {
2970 sprintf(extnv, "%s",hduptr->extname);
2971 if (hduptr->extver!=-999) {
2972 sprintf(extver," (%d)",hduptr->extver);
2973 strcat(extnv,extver);
2974 }
2975 }
2976 strcpy(comm,extnv);
2977
2978 switch(hduptr->bitpix) {
2979 case BYTE_IMG:
2980 strcpy(temp," 8-bit integer pixels, ");
2981 break;
2982 case SHORT_IMG:
2983 strcpy(temp," 16-bit integer pixels, ");
2984 break;
2985 case USHORT_IMG:
2986 strcpy(temp," 16-bit unsigned integer pixels, ");
2987 break;
2988 case LONG_IMG:
2989 strcpy(temp," 32-bit integer pixels, ");
2990 break;
2991 case LONGLONG_IMG:
2992 strcpy(temp," 64-bit long integer pixels, ");
2993 break;
2994 case ULONG_IMG:
2995 strcpy(temp," 32-bit unsigned integer pixels, ");
2996 break;
2997 case FLOAT_IMG:
2998 strcpy(temp," 32-bit floating point pixels, ");
2999 break;
3000 case DOUBLE_IMG:
3001 strcpy(temp," 64-bit double precision pixels, ");
3002 break;
3003 default:
3004 strcpy(temp," unknown datatype, ");
3005 break;
3006 }
3007 strcat(comm,temp);
3008
3009 sprintf(temp," %d axes ",hduptr->naxis);
3010 strcat(comm,temp);
3011
3012 #if (USE_LL_SUFFIX == 1)
3013 sprintf(temp, "(%lld",hduptr->naxes[0]);
3014 #else
3015 sprintf(temp, "(%ld",hduptr->naxes[0]);
3016 #endif
3017 strcat(comm,temp);
3018
3019 npix = hduptr->naxes[0];
3020 for ( i = 1; i < hduptr->naxis; i++){
3021 npix *= hduptr->naxes[i];
3022 #if (USE_LL_SUFFIX == 1)
3023 sprintf(temp, " x %lld",hduptr->naxes[i]);
3024 #else
3025 sprintf(temp, " x %ld",hduptr->naxes[i]);
3026 #endif
3027 strcat(comm,temp);
3028 }
3029 strcat(comm,"), ");
3030 wrtout(out,comm);
3031 }
3032 else{
3033 sprintf(comm," Null data array; NAXIS = 0 ");
3034 wrtout(out,comm);
3035 }
3036 }
3037 wrtout(out," ");
3038 return;
3039 }
3040
3041 /*************************************************************
3042 *
3043 * close_hdu
3044 *
3045 * Free the memory allocated to the FitsHdu structure and
3046 * other temporary spaces.
3047 *
3048 **************************************************************/
close_hdu(FitsHdu * hduptr)3049 void close_hdu( FitsHdu *hduptr )
3050 {
3051 int i;
3052 int n;
3053 /* free memories */
3054 for (i=0; i < ncards; i++) free(cards[i]);
3055
3056 n = hduptr->nkeys - 4 - hduptr->naxis ; /* excluding the SIMPLE,
3057 BITPIX, NAXIS, NAXISn
3058 and END */
3059 for (i=0; i < n; i++) free(hduptr->kwds[i]);
3060
3061 for (i=0; i < hduptr->ncols; i++) {
3062 free(hduptr->datamin[i]);
3063 free(hduptr->datamax[i]);
3064 free(hduptr->tnull[i]);
3065 }
3066 if(hduptr->hdutype == ASCII_TBL && hduptr->hdutype == BINARY_TBL){
3067 if(hduptr->ncols > 0)free(ttype);
3068 if(hduptr->ncols > 0)free(tunit);
3069 if(hduptr->ncols > 0)free(tform);
3070 }
3071 if(hduptr->naxis) free(hduptr->naxes);
3072 if(hduptr->ncols > 0)free(hduptr->datamax);
3073 if(hduptr->ncols > 0)free(hduptr->datamin);
3074 if(hduptr->ncols > 0)free(hduptr->tnull);
3075 free(hduptr->kwds);
3076 free(cards);
3077 free(tmpkwds);
3078 return;
3079 }
3080