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 #ifndef STANDALONE
8 #include "pil.h"
9 #include "headas.h"
10 #include "headas_error.h"
11 #endif
12
13 #define MAXMSG 256
14
15 /*
16 HISTORY
17 -------
18
19 The original fverify.f Fortran program was written by William Pence in 1994.
20 Ning Gan rewrote fverify in C in 1998, and continued to make enhancements
21 throughout 1999 and 2000.
22 Ziqin Pan adapted fverify to build in the new HEADAS environment
23 in 2002, renaming it to ftverify.
24 William Pence made additional enhancements, and rationalized the code
25 so that fverify and ftverify share many of the same source files
26 in January 2003
27
28
29 * Detailed modification History
30 *
31 * MODIFICATION HISTORY:
32 * 1998-08-24 Ning Gan, v3.0.0
33 * Beta version: xverify v1.0
34 * 1998-12-18 Ning Gan, v3.0.1
35 * Beta version: xverify v1.1
36 * 1999-02-18 Ning Gan, v3.0.2
37 * Beta version: xverify v1.2
38 * Added more checks for keywords.
39 * 1999-03-04 Ning Gan, v3.0.3
40 * Added a feature of multiple input files.
41 * 1999-05-19 Ning Gan, v3.0.5
42 * Wrote numwrns and numerrs to the par file.
43 * If the # of errors exceeds the MAXERRORS,
44 * quit and wrote the summary.
45 * Took out the limits on warnings.
46 * 1999-06-03 Ning Gan, v3.0.6
47 * Wrote the version number of underlying
48 * cfitsio.
49 * 1999-06-07 Ning Gan, v3.0.7
50 * Improve the error handling. If there are
51 * errors on opening fitsfile, the program set
52 * numerr to 1 and quit.
53 * 1999-06-30 Ning Gan, v3.0.8
54 * Improve the layout of the output.
55 * 1999-08-25 Ning Gan, v3.0.9
56 * Always write errors to stderr.
57 * Added ffnchk
58 * Took out the checks of rejecting the
59 * TDISP like I2.0 and the column name
60 * startingnerror with a digit.
61 * 1999-10-25 Ning Gan, v3.1.0
62 * The TDISP can take format I4.
63 * Beutified the CFISIO error stack output
64 * The numerrs and numwrns are the accumulated
65 * number of errors and warnings if multiple
66 * FITS file are tested in on fverify session.
67 * Checked the X Column is left justified.
68 * 1999-12-12 Ning Gan, v3.1.1
69 * Added the basiconly and heasarc parameters.
70 * 1999-12-20 Ning Gan, v3.1.2
71 * Added the parameters of errreport and prstat,
72 * removed the parameters of basiconly, erronly and
73 * errpluswrn.
74 * 1999-12-29 Ning Gan, v3.1.3
75 * fixed a bug on solaris
76 * 2000-05-03 Ning Gan, v3.1.4
77 * Skip the blank column names in column name
78 * tests.
79 * 2000-06-09 Ning Gan, v3.1.5
80 * Fixed the memory problem(The bug will crash
81 * 2000-09-26 Ning Gan, v3.1.6
82 * Fixed the TDISP format bug (not accept
83 * format such as E15.5E3).
84 * 2002-09-30 Ziqin Pan converted fverify to ftverify for HEADAS environ.
85 * 2003-01-09 W Pence v4.0
86 * Added support for the new WCSAXES keyword
87 * Added support for random groups
88 * several small changes to the output report format
89 *
90 * 2004-06-21 W Pence fixed reporting error when prstat=no and when
91 * opening a nonexistent or non-FITS file.
92 * Also fixed elusive memory allocation error.
93 *
94 * 2009-06-08 W Pence updates to comply with V3.0 of the FITS Standard
95 * 2010-07-26 W Pence Updates to WCS keyword checks, plux other V3.0 issues
96 */
97
98 #define TOOLSUB ftverify
99 /* headas_main() requires that TOOLSUB be defined first */
100
101 long totalerr, totalwrn;
102
103 #ifdef STANDALONE
104 #include "fitsverify.c"
105 #else
106 #include "headas_main.c"
107 #endif
108
109 /* Function Prototypes */
110 int ftverify (void);
111 int ftverify_getpar (char *infile, char *outfile,int * prehead,
112 int* prstat, char* errreport, int* testdata, int* testcsum,
113 int* testfill, int* heasarc_conv);
114 int ftverify_work (char *infile, char *outfile,int prehead,
115 int prstat, char* errreport, int testdata, int testcsum,
116 int testfill, int heasarc_conv);
117
118 int err_report=0;
119 int prhead=0;
120 int prstat=1;
121 int testdata=1;
122 int testcsum=1;
123 int testfill=1;
124 int heasarc_conv=1;
125 int totalhdu=0;
126
127
128 /*---------------------------------------------------------------------------*/
ftverify(void)129 int ftverify (void)
130 {
131 /* Read a FITS file and verify that it conforms to the FITS standard */
132
133 char infile[PIL_LINESIZE],outfile[PIL_LINESIZE];
134 int status;
135 char errreport[PIL_LINESIZE];
136
137 static char taskname[80] = "ftverify";
138 static char version[8] = "4.16";
139
140 /* Register taskname and version. */
141
142 set_toolname(taskname);
143 set_toolversion(version);
144
145 /* get input parameters */
146 status = ftverify_getpar(infile, outfile,&prhead,&prstat,
147 errreport,&testdata,&testcsum,&testfill,&heasarc_conv);
148
149 /* call work function to verify that infile conforms to the FITS
150 standard and write report to the output file */
151 if (!status)
152 status = ftverify_work(infile, outfile,prhead,prstat,
153 errreport,testdata,testcsum,testfill,heasarc_conv);
154
155 return(status);
156 }
157 /*---------------------------------------------------------------------------*/
ftverify_getpar(char * infile,char * outfile,int * prhead,int * prstat,char * errreport,int * testdata,int * testcsum,int * testfill,int * heasarc_conv)158 int ftverify_getpar(
159 char *infile, /* O - Input file name (Fits) */
160 char *outfile, /* O - Output file name (ASCII) */
161 int * prhead,
162 int * prstat,
163 char * errreport,
164 int * testdata,
165 int * testcsum,
166 int * testfill,
167 int * heasarc_conv)
168
169 /* read input parameters for the ftverify task from the .par file */
170 {
171 int status;
172 char msg[MAXMSG];
173
174 if ((status = PILGetString("infile", infile))) {
175 sprintf(msg, "Error reading the 'infile' parameter.");
176 HD_ERROR_THROW(msg,status);
177 }
178
179
180 else if ((status = PILGetString("outfile", outfile))) {
181 sprintf(msg, "Error reading the 'outfile' parameter.");
182 HD_ERROR_THROW(msg,status);
183 }
184
185 else if ((status = PILGetBool("prhead", prhead))) {
186 sprintf(msg, "Error reading the 'prhead' parameter.");
187 HD_ERROR_THROW(msg,status);
188 }
189
190 else if ((status = PILGetBool("prstat", prstat))) {
191 sprintf(msg, "Error reading the 'prstat' parameter.");
192 HD_ERROR_THROW(msg,status);
193 }
194
195 else if ((status = PILGetString("errreport", errreport))) {
196 sprintf(msg, "Error reading the 'errreport' parameter.");
197 HD_ERROR_THROW(msg,status);
198 }
199
200 else if ((status = PILGetBool("testdata", testdata))) {
201 sprintf(msg, "Error reading the 'testdata' parameter.");
202 HD_ERROR_THROW(msg,status);
203 }
204
205 else if ((status = PILGetBool("tchksum", testcsum))) {
206 sprintf(msg, "Error reading the 'tchksum' parameter.");
207 HD_ERROR_THROW(msg,status);
208 }
209
210 else if ((status = PILGetBool("testfill", testfill))) {
211 sprintf(msg, "Error reading the 'testfill' parameter.");
212 HD_ERROR_THROW(msg,status);
213 }
214
215 else if ((status = PILGetBool("heasarc", heasarc_conv))) {
216 sprintf(msg, "Error reading the 'heasarc' parameter.");
217 HD_ERROR_THROW(msg,status);
218 }
219
220 return(status);
221 }
222 /*---------------------------------------------------------------------------*/
ftverify_work(char * infile,char * outfile,int prehead,int prstat,char * errreport,int testdata,int testcsum,int testfill,int heasarc_conv)223 int ftverify_work(
224 char *infile, /* I - Input file name (Fits) */
225 char *outfile, /* I - Output file name (ASCII) */
226 int prehead,
227 int prstat,
228 char * errreport,
229 int testdata,
230 int testcsum,
231 int testfill,
232 int heasarc_conv)
233
234 /* call work function to verify that infile conforms to the FITS
235 standard and write report to the output file */
236 {
237 FILE *runfile = 0;
238 FILE *outfptr = 0;
239 FILE *list=0;
240 int status = 0, filestatus, runnum;
241 char * p;
242 char task[80],runchars[30];
243 char tversion[80];
244 float fversion;
245 int i, nerrs, nwarns;
246 char msg[MAXMSG];
247
248 /* determine 'Severe error", "Error", or "Warning" report level */
249 if( *errreport == 's' || *errreport == 'S') err_report = 2;
250 if( *errreport == 'e' || *errreport == 'E') err_report = 1;
251
252 p = infile;
253 if (*p == '@') {
254 p++;
255 if( (list = fopen(p,"r")) == NULL ) {
256 fprintf(stderr,"Cannot open the list file: %s.",p);
257 leave_early(NULL);
258 return (FILE_NOT_OPENED);
259 }
260 }
261
262 headas_clobberfile(outfile); /* delete existing file if clobber=YES */
263 p = outfile;
264
265 /* test if writing output log to a disk file */
266 if(prstat && strlen(p) && strcmp(p, "STDOUT") && strcmp(p, "STDERR")
267 && (outfptr = fopen(p,"r") ) != NULL ) {
268 sprintf(msg,"Clobber is not set. Cannot overwrite the file%s",p);
269 status = FILE_NOT_CREATED;
270 HD_ERROR_THROW(msg,status);
271 leave_early(NULL);
272 fclose(outfptr);
273 return (status);
274 }
275
276 if(prstat && (!strlen(p) || !strcmp(p, "STDOUT"))) {
277 outfptr = stdout;
278 }
279 else if(prstat && (!strlen(p) || !strcmp(p, "STDERR"))) {
280 outfptr = stderr;
281 }
282 else if (!prstat) {
283 outfptr=NULL;
284 }
285 else if( (outfptr = fopen(p,"w") ) == NULL) {
286 fprintf(stderr,"Error open output file %s. Using stdout instead.",
287 outfile);
288 outfptr = stdout;
289 }
290
291 #ifdef WEBTOOL
292 /* try opening and incrementing the file containing cumulative # of runs */
293 runfile=fopen("/tmp.shared/fits/tmpverify/counter.fitsverify","r+");
294 /* runfile=fopen("counter.fitsverify","r+"); */
295 if (runfile) {
296 fgets(runchars,20,runfile);
297 runnum=atoi(runchars);
298 runnum++;
299 sprintf(comm," Run Number %d",runnum);
300 wrtout(outfptr,comm);
301 sprintf(runchars, "%d", runnum);
302 fflush(runfile);
303 rewind(runfile);
304 fputs(runchars, runfile);
305 }
306
307 #endif
308
309 wrtout(outfptr," ");
310 fits_get_version(&fversion);
311 get_toolname(task);
312 get_toolversion(tversion);
313 sprintf(comm,"%s %s (CFITSIO V%.3f)",task,tversion,fversion);
314 wrtsep(outfptr,' ',comm,60);
315 for(i = 0; comm[i]!='\0'; i++) comm[i] = '-';
316 wrtsep(outfptr,' ',comm,60);
317 wrtout(outfptr," ");
318 switch (err_report) {
319 case 2:
320 sprintf(comm, "Caution: Only checking for the most severe FITS format errors.");
321 wrtout(outfptr,comm);
322 break;
323 case 1:
324 break;
325 case 0:
326 break;
327 }
328
329 if(heasarc_conv) {
330 sprintf(comm, "HEASARC conventions are being checked.");
331 wrtout(outfptr,comm);
332 }
333
334 /* process each file */
335 if (list == NULL) {
336 verify_fits(infile,outfptr);
337 if (outfptr == NULL) { /* print one-line file summary */
338 nerrs = get_total_err();
339 nwarns = get_total_warn();
340 filestatus = ((nerrs+nwarns)>0) ? 1 : 0;
341 if (filestatus)
342 {
343 if (err_report)
344 printf("verification FAILED: %-20s, %d errors\n",
345 infile, nerrs);
346 else
347 printf("verification FAILED: %-20s, %d warnings and %d errors\n",
348 infile, nwarns, nerrs);
349 }
350 else
351 printf("verification OK: %-20s\n", infile);
352 }
353 }
354 else {
355 while((p = fgets(infile, FLEN_FILENAME, list))!= NULL) {
356 verify_fits(infile,outfptr);
357
358 if (outfptr == NULL) { /* print one-line file summary */
359 nerrs = get_total_err();
360 nwarns = get_total_warn();
361 filestatus = ((nerrs+nwarns) >0) ? 1 : 0;
362 if (filestatus)
363 {
364 if (err_report)
365 printf("verification FAILED: %-20s, %d errors\n",
366 infile, nerrs);
367 else
368 printf("verification FAILED: %-20s, %d warnings and %d errors\n",
369 infile, nwarns, nerrs);
370 }
371 else
372 printf("verification OK: %-20s\n", infile);
373 }
374
375 for (i = 1; i < 3; i++) wrtout(outfptr," ");
376 }
377 fclose(list);
378 }
379
380 /* close the output file */
381 if (outfptr != stdout && outfptr != NULL) fclose(outfptr);
382
383 return(status);
384 }
385
386 /******************************************************************************
387 * Function
388 * update_parfile
389 *
390 *
391 * DESCRIPTION:
392 * Update the numerrs and numwrns parameters in the parfile.
393 *
394 *******************************************************************************/
update_parfile(int nerr,int nwrn)395 void update_parfile(int nerr, int nwrn)
396 {
397 int status = 0;
398 char parname[32];
399
400 totalerr += (long )nerr;
401 totalwrn += (long )nwrn;
402 /* write the total accumulated total warnings and errors to the
403 parfile */
404 strcpy(parname, "numwrns");
405 status=PILPutInt(parname, totalwrn);
406 if(status) {
407 fprintf(stderr,"Error to update the numwrns keyword.\n");
408 status = 0;
409 }
410 strcpy(parname, "numerrs");
411 status=PILPutInt(parname, totalerr);
412 if(status) {
413 fprintf(stderr,"Error to update the numerrs keyword.\n");
414 status = 0;
415 }
416 }
417
418
419