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