OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
ANCroutines.c
Go to the documentation of this file.
1 #include <mfhdf.h>
2 #include "ancil.h"
3 #include "l1io.h"
4 
5 
6 /*********************************************************************
7  * NAME: startHDF
8  *
9  * PURPOSE: open HDF file structure using SDstart and Hopen routines
10  *
11  * ARGS:
12  * outfile - output filename
13  * sdfid - SD file id
14  * fid - HDF file id
15  * mode - DFACC_RDONLY, DFACC_CREATE, DFACC_RDWR
16  *
17  * OUTPUTS: returns a SD structure ID and a File ID.
18  *
19  * EFFECTS: opens HDF file structures
20  *
21  * RETURNS: status flag
22  * Mods: BDS 2/10/94 ver 3.3, (pg: SD32) does not use DFAAC_WRITE so
23  * its removed here as an option arg.
24  * 8/21/96 BDS - renamed 'perror' to 'pexit' to avoid HDF4.0 conflict.
25  *********************************************************************/
26 
27 int startHDF(outfile, sdfid, fid, mode)
28 char *outfile;
29 int32_t *sdfid, *fid, mode;
30 {
31  int32 lsdfid, lfid;
32 
33  if ((lsdfid = SDstart(outfile, mode)) < 0) return FAIL;
34  if ((lfid = Hopen(outfile, DFACC_RDONLY, 0)) < 0) return FAIL;
35  Vstart(lfid);
36 
37  *sdfid = lsdfid;
38  *fid = lfid;
39 
40  return SUCCESS;
41 
42 } /* startHDF */
43 
44 /*********************************************************************
45  * setupGrid
46  *
47  * create and HDF Vgroup grid and name it with passed arguments
48  *
49  *********************************************************************/
50 
51 int32_t setupGrid(fid, grpname)
52 int32_t fid;
53 char *grpname;
54 {
55  int32 gridid;
56 
57  gridid = Vattach(fid, -1, "w");
58  /* Vsetclass(gridid, vgroupclass); */
59  Vsetname(gridid, grpname);
60 
61  return gridid;
62 }
63 
64 /*********************************************************************
65  * gridToGrid
66  *
67  * attach inner grid to outer grid: nested Vgroups
68  *
69  *********************************************************************/
70 
71 int32_t gridToGrid(outergridid, innergridid)
72 int32_t outergridid, innergridid;
73 {
74  int32 groupref;
75 
76  groupref = VQueryref(innergridid);
77  if (groupref < 0) return -1;
78 
79  Vaddtagref(outergridid, DFTAG_VG, groupref);
80 
81  return 0;
82 }
83 
84 /*********************************************************************
85  * writeGeom
86  *
87  * write HDF geometry Vdata using SeaWiFS defined geometry structure
88  *
89  * return geometry ID
90  *
91  *********************************************************************/
92 
93 int32_t writeGeom(int32_t fid, int32_t gridid, char *geomname, int32_t bin_meth, int32_t registration,
94  float vsize, float hsize, float max_north, float max_south, float max_west, float max_east)
95 {
96  int32 geomid, geomref, *i32;
97  int result;
98  float *f32;
99  unsigned char arrhold[GEOMSIZE];
100 
101  /*
102  * --- Write geometry struct for data array and QC data array ----
103  */
104 
105  geomid = VSattach(fid, -1, "w");
106  result = VSfdefine(geomid, "bin_meth", DFNT_INT32, 1);
107  result = VSfdefine(geomid, "registration", DFNT_INT32, 1);
108  result = VSfdefine(geomid, "vsize", DFNT_FLOAT32, 1);
109  result = VSfdefine(geomid, "hsize", DFNT_FLOAT32, 1);
110  result = VSfdefine(geomid, "max_north", DFNT_FLOAT32, 1);
111  result = VSfdefine(geomid, "max_south", DFNT_FLOAT32, 1);
112  result = VSfdefine(geomid, "max_west", DFNT_FLOAT32, 1);
113  result = VSfdefine(geomid, "max_east", DFNT_FLOAT32, 1);
114 
115  VSsetclass(geomid, GEOMCLASS);
116  VSsetname(geomid, geomname);
117 
118  result = VSsetfields(geomid,
119  "bin_meth,registration,vsize,hsize,max_north,max_south,max_west,max_east");
120 
121  i32 = (void *) &arrhold[0];
122  *i32 = bin_meth;
123  i32 = (void *) &arrhold[4];
124  *i32 = registration;
125 
126  f32 = (void *) &arrhold[8];
127  *f32 = vsize;
128  f32 = (void *) &arrhold[12];
129  *f32 = hsize;
130  f32 = (void *) &arrhold[16];
131  *f32 = max_north;
132  f32 = (void *) &arrhold[20];
133  *f32 = max_south;
134  f32 = (void *) &arrhold[24];
135  *f32 = max_west;
136  f32 = (void *) &arrhold[28];
137  *f32 = max_east;
138 
139  result = VSwrite(geomid, arrhold, 1, FULL_INTERLACE);
140  VSdetach(geomid);
141 
142  /*
143  * get geometry reference and add to vgroup
144  */
145 
146  geomref = VSQueryref(geomid);
147  Vaddtagref(gridid, DFTAG_VH, geomref);
148 
149  if (result < 0)
150  return ERROR;
151  else
152  return geomid;
153 
154 } /* writeGeom */
155 
156 /*********************************************************************
157  * findGeomId
158  *
159  * find existing HDF geometry ID
160  *
161  *********************************************************************/
162 
163 int32 findGeomId(fid, geomname)
164 int32 fid;
165 char *geomname;
166 {
167  int32 geomid, vsid;
168 
169  if ((vsid = VSfind(fid, geomname)) < 0)
170  pexit("getting geom vsid");
171 
172  if ((geomid = VSattach(fid, vsid, "r")) < 0)
173  pexit("attaching geom vsid");
174 
175  return geomid;
176 
177 } /* findGeomId */
178 
179 /*********************************************************************
180  * linkGeom
181  *
182  * link to existing HDF geometry Vdata
183  * get geometry reference and add to vgroup
184  *
185  *********************************************************************/
186 
187 int32 linkGeom(gridid, geomid)
188 int32 gridid, geomid;
189 {
190  int32 geomref, result;
191 
192  geomref = VSQueryref(geomid);
193  result = Vaddtagref(gridid, DFTAG_VH, geomref);
194 
195  return result;
196 
197 } /* linkGeom */
198 
199 /*********************************************************************
200  * detachGeom
201  *
202  * detach Geometry ID
203  *
204  *********************************************************************/
205 
206 int32 detachGeom(geomid)
207 int32 geomid;
208 {
209 
210  VSdetach(geomid);
211 
212  return 0;
213 
214 } /* detachGeom */
215 
216 /*********************************************************************
217  * addAttr
218  *
219  * add an attribute to an existing SDS
220  *
221  *********************************************************************/
222 
223 int addAttr(sdsid, dataattr, datatype, dataunit)
224 int32 sdsid;
225 char *dataattr;
226 int32 datatype;
227 char *dataunit;
228 {
229  int result;
230 
231  if ((result = SDsetattr(sdsid, dataattr, datatype, strlen(dataunit) + 1,
232  dataunit)) != 0) return (-1);
233 
234  return result;
235 
236 } /* addAttr */
237 
238 /*********************************************************************
239  * setSDSref
240  *
241  * get and SDS reference number and add it to an existing Vgroup
242  * end SDS access
243  *
244  *********************************************************************/
245 
246 int setSDSref(sdsid, gridid)
247 int32 sdsid, gridid;
248 {
249  int32 sdsref;
250  int result;
251 
252  if ((sdsref = (int32) SDidtoref(sdsid)) < 0) return (-1);
253 
254  Vaddtagref(gridid, DFTAG_NDG, sdsref);
255  if ((result = SDendaccess(sdsid)) < 0) return result;
256 
257  return 0;
258 
259 } /* setSDSref */
260 
261 /*********************************************************************
262  * deattachHDFgrid
263  *
264  * make HDF grid structure inactive
265  *
266  *********************************************************************/
267 
268 int deattachHDFgrid(gridid)
269 int32 gridid;
270 {
271  return Vdetach(gridid);
272 
273 } /* deattachHDFgrid */
274 
275 /*********************************************************************
276  * closeHDFstructs
277  *
278  * close HDF file structures
279  *
280  *********************************************************************/
281 
282 int closeHDFstructs(sdfid, fid)
283 int32 sdfid, fid;
284 {
285  int result;
286 
287  if ((result = Vend(fid)) < 0) {
288  printf("Vend: result: %d\n", result);
289  return (-1);
290  }
291 
292  if ((result = SDend(sdfid)) < 0) {
293  printf("SDend: result: %d\n", result);
294  return (-1);
295  }
296 
297  if ((result = Hclose(fid)) < 0) {
298  printf("Error on Hclose(); stack follows:\n");
299  HEprint(stderr, 0);
300  printf("Stack complete\n");
301  return (-1);
302  }
303 
304  return result;
305 
306 } /* closeHDFstructs */
307 
308 /*****************************************************************
309  * File: wrtsds
310  *
311  * Purpose: write an SDS file
312  *
313  * Description: writes an SDS given labels, formats, units, and a
314  * data block.
315  *
316  * Input parms:
317  * char *sdsfid - file id
318  * int rank - number of dimensions in SDS
319  * int32 shape[] - dimension sizes for each dimension
320  * int32 datatype - HDF datatype of data block
321  * char *datalabel - label descriptor for SDS
322  * char *dataunit - unit descriptor for SDS
323  * char *datafmt - format descriptor for SDS
324  * void *data - array of data values
325  *
326  * Output parms: none
327  *
328  * Returns: 0 on success, non-zero on failure
329  *
330  * Local vars:
331  * int result - HDF routine return value
332  *
333  * Subs called: HDF library routines SDcreate, SDwritedata
334  *
335  * History: none
336  *
337  * Note: uses "ancil.h"
338  *
339  * Author: Brian D. Schieber, GSC, 2/93
340  *
341  * Modification history:
342  * BDS, 9/3/93 - modified for new HDF interface
343  *
344  *****************************************************************/
345 
346 int32 wrtsds(sdfid, rank, shape, datatype, datalabel, data)
347 
348 int32 sdfid, shape[], datatype;
349 int rank;
350 char *datalabel;
351 void *data;
352 {
353  int result = 0;
354  int32 sdsid;
355  static int32 start[2] = {0, 0};
356 
357  if ((sdsid = SDcreate(sdfid, datalabel, datatype, rank, shape)) < 0)
358  return sdsid;
359 
360  if ((result = SDwritedata(sdsid, start, NULL, shape, data)) < 0)
361  return result;
362 
363  return sdsid;
364 
365 } /* wrtsds */
366 
367 /*****************************************************************
368  * File: rewrtsds
369  *
370  * Purpose: overwrite an SDS file
371  *
372  * Description: overwrite an SDS given prior sdsid, data shape, and
373  * data block.
374  *
375  * Input parms:
376  * char *sdsid - sds id
377  * int32 shape[] - dimension sizes for each dimension
378  * void *data - array of data values
379  *
380  * Output parms: none
381  *
382  * Returns: 0 on success, non-zero on failure
383  *
384  * Local vars:
385  * int result - HDF routine return value
386  *
387  * Subs called: HDF library routines SDwritedata
388  *
389  * History: none
390  *
391  * Note: uses "ancil.h"
392  *
393  * Author: Brian D. Schieber, GSC, 2/93
394  *
395  * Modification history:
396  * BDS, 9/3/93 - modified for new HDF interface
397  *
398  *****************************************************************/
399 
400 int32 rewrtsds(sdsid, shape, data)
401 int32 sdsid, shape[];
402 void *data;
403 {
404  int result = 0;
405  static int32 start[2] = {0, 0};
406 
407  printf("rewrtsds sdsid %d, shape[0] %d, shape[1] %d\n",
408  sdsid, shape[0], shape[1]);
409 
410  result = SDwritedata(sdsid, start, NULL, shape, data);
411  printf("rewrtsds SDwritedata result: %d\n", result);
412 
413  result += SDendaccess(sdsid);
414  printf("rewrtsds SDendaccess result: %d\n", result);
415 
416  return result;
417 
418 } /* rewrtsds */
419 
420 /*****************************************************************
421  * File: rdsds
422  *
423  * Purpose: read HDF Scientific Data Set (SDS)
424  *
425  * Description: read HDF Scientific Data Set (SDS) and return
426  * descriptors and data values. Reads one SDS at a time.
427  *
428  * Input parameters:
429  * char *filename - HDF base name (no ext)
430  * char *vgname - name of vgroup where SDS exists
431  * char *sdsname - name of SDS data grid
432  *
433  * Output parameters:
434  * int32 dimsizes[] - size of each dimension
435  * void *inData - array of data
436  *
437  * Returns: -1 on failure, 0 on success
438  *
439  * Local variables:
440  * int result - counters, return value
441  *
442  * Subroutines called: HDF library routines
443  *
444  * History: none
445  *
446  * Note: arrays returned from this routine must 'fit' the variables
447  * allocated space in the calling routine. Any dimension, any size
448  * SDS can be returned. The 'dimsizes' returned should be verified
449  * to determine the SDS size retreived.
450  *
451  * Author: Brian D. Schieber, GSC, 4/93
452  *
453  * Modification history:
454  * modified for the new HDF formats 10/8/93, BDS, GSC/SAIC
455  * BDS, 8/14/95 Mods per OAPS spec 2.7
456  *****************************************************************/
457 
458 int rdsds(filename, vgname, sdsname, dimsizes, inData)
459 char *filename, *sdsname;
460 char *vgname;
461 int32 dimsizes[];
462 void *inData;
463 {
464  int result;
465  int j;
466  int32 sdfid, fid, vid, vg;
467  int32 sdsindex, sdsid;
468  int32 rank, numbertype;
469  int32 start[2];
470  int32 tagarray1[255], refarray1[255], nrefs1, nattrs1;
471  char lname[MAXNAMELNG];
472 
473  /*
474  * Default settings for SDreaddata
475  */
476 
477  start[0] = 0;
478  start[1] = 0;
479 
480  /*
481  * ---- Open data file ------------
482  */
483 
484  if ((result = startHDF(filename, &sdfid, &fid, DFACC_RDONLY)) != 0) {
485  pwarning("Fatal error starting HDF file");
486  return (ERROR);
487  }
488 
489  /*
490  * Traverse down to the correct SDS
491  */
492 
493  /* Open the Vgroup by name and fileid, attach to it and get the number
494  * and tag type (SDG, VH, etc) in it, loop over each item and find
495  * the ones that match the desired SDS and then use the SDS reference
496  * and extract the SDS array to the calling procedure.
497  */
498 
499  if ((vid = Vfind(fid, vgname)) <= 0) return (ERROR);
500  vg = Vattach(fid, vid, "r");
501  nrefs1 = Vntagrefs(vg);
502  nattrs1 = nrefs1;
503  Vgettagrefs(vg, tagarray1, refarray1, nattrs1);
504 
505  for (j = 0; j < nrefs1; j++) {
506  if ((tagarray1[j] == DFTAG_NDG) ||
507  (tagarray1[j] == DFTAG_SD)) { /* SDS found */
508  sdsindex = SDreftoindex(sdfid, refarray1[j]);
509  sdsid = SDselect(sdfid, sdsindex);
510  SDgetinfo(sdsid, lname, &rank, dimsizes, &numbertype, &nattrs1);
511  if (!strcmp(sdsname, lname)) {
512  if ((SDreaddata(sdsid, start, (int32 *) NULL, dimsizes, inData)) != 0) {
513  pwarning("Fatal error reading SDS data array");
514  return (ERROR);
515  }
516  Vdetach(vg);
517  return (0); /* SUCCESS */
518  } /* if (!strcmp(vgname, lname)) */
519  } /* tagarray1[k] */
520  } /* for j */
521  Vdetach(vg);
522  pwarning("Fatal error: Case 1 SDS data array not found");
523  return (ERROR);
524 
525  /*
526  * ---- Close data file ------------
527  */
528 
529  if ((closeHDFstructs(sdfid, fid)) < 0) {
530  pwarning("Fatal error closing SDS: closeHDFstructs");
531  return (ERROR);
532  }
533 
534  return (result);
535 
536 } /* rdsds */
537 
538 /**********************************************************************
539  * SUBROUTINE: SDSinFile
540  *
541  * PURPOSE: assign attributes, add to Vgroup and deattach SDS
542  *
543  * AUTHOR: B.D.Schieber, GSC, 10/93
544  * Mods: BDS 5/19/95 Support SeaWiFS Specs 2.7
545  **********************************************************************/
546 
547 int32 SDSinFile(sdsname, longname, units, datafmt,
548  datatype, sdfid, rank, shape, data, gridid)
549 char *sdsname, *longname, *units, *datafmt;
550 int32 sdfid, datatype, rank, shape[], gridid;
551 void *data;
552 {
553  int result;
554  int32 sdsid;
555 
556  /*
557  * write SDS array
558  */
559 
560  if ((sdsid = wrtsds(sdfid, rank, shape, datatype, sdsname, data)) < 0) {
561  pwarning("wrtsds");
562  return (ERROR);
563  }
564 
565  /*
566  * set SDS attributes
567  */
568 
569  if ((result = addAttr(sdsid, "long_name", DFNT_CHAR, longname)) != 0) {
570  pwarning("addAttr");
571  return (ERROR);
572  }
573 
574  if (strlen(units) > 0) /* don't write "" attributes */
575  if ((result = addAttr(sdsid, "units", DFNT_CHAR, units)) != 0) {
576  pwarning("addAttr");
577  return (ERROR);
578  }
579 
580  /*
581  * add SDS to Vgroup and deattach SDS
582  */
583 
584  if ((result = setSDSref(sdsid, gridid)) != 0) {
585  pwarning("setSDSref");
586  return (ERROR);
587  }
588 
589  return 0;
590 
591 } /* SDSinFile */
592 
593 /*****************************************************************
594  * File: wrtattr
595  *
596  * Purpose: write DAAC style global attributes to an HDF file
597  *
598  * Description: string arrays of label/value pairs written to HDF
599  * header file.
600  *
601  * Input parms:
602  * dfile - HDF file id
603  * num - number of strings
604  *
605  * Output parms:none
606  *
607  * Returns: -1 on failure, 0 on success
608  *
609  * Local vars:
610  * int i - counter
611  * char outlabel[MAXLABLEN+1] - local label string
612  * char outdescr[MAXDESCLEN+1] - local description string
613  * int32 dfile - file id number
614  * int32 result - return value for HDF calls
615  *
616  * Subs called: HDF library routines
617  *
618  * Note: uses header (ancil.h) definitions for label length,
619  * description length, and name length
620  * uses argument setting for numannarr
621  *
622  * History: based on DAAC "Metadata Submission Guide" 2/93
623  *
624  * Author: Brian D. Schieber, GSC, 2/93
625  *
626  * Mod history:
627  * BDS, 8/30/93 - modified to work with new HDF design.
628  *
629  *****************************************************************/
630 
631 int wrtattr(dfile, annot, numannarr)
632 int32 dfile;
633 struct annotation *annot;
634 int numannarr;
635 {
636 
637  /*
638  * local variables
639  */
640 
641  char outlabel[MAXLABLEN + 1], outchar[MAXDESCLEN + 1];
642  int16 outint16[1];
643  int32 outint32[1];
644  float outfloat32[1];
645  int i = 0;
646  int32 result = 0;
647 
648  /*
649  * Place each label/description pair into HDF header
650  */
651 
652  for (i = 0; i < numannarr; i++) {
653 
654  /* printf ("label [%d] [%s]\n",i, annot[i].label); */
655  /* printf ("descr [%d] [%s]\n",i, annot[i].descr); */
656  strcpy(outlabel, annot[i].label);
657 
658  switch (annot[i].type) {
659  case (DFNT_CHAR8):
660  strcpy(outchar, annot[i].descr);
661  result = SDsetattr(dfile, outlabel, DFNT_CHAR8,
662  strlen(outchar) + 1, outchar);
663  break;
664 
665  case (DFNT_INT16):
666  /* strcpy (outchar, annot[i].descr); */
667  /* sscanf(&outchar[0], "%hd", &outint16[0]); */
668  sscanf(annot[i].descr, "%hd", &outint16[0]);
669  /* printf("outint16 [%hd]\n", outint16[0]); */
670 
671  result = SDsetattr(dfile, outlabel, DFNT_INT16, 1, outint16);
672  break;
673 
674  case (DFNT_INT32):
675  sscanf(annot[i].descr, "%d", &outint32[0]);
676  result = SDsetattr(dfile, outlabel, DFNT_INT32, 1, outint32);
677  break;
678 
679  case (DFNT_FLOAT32):
680  /* strcpy (outchar, annot[i].descr); */
681  /* sscanf(&outchar[0], "%f", &outfloat32[0]); */
682  sscanf(annot[i].descr, "%f", &outfloat32[0]);
683  /* printf("outfloat32 [%f]\n", outfloat32[0]); */
684  result = SDsetattr(dfile, outlabel, DFNT_FLOAT32, 1, outfloat32);
685  break;
686 
687  default:
688  printf("Error in function WRTATTR, default CASE encountered\n");
689  return (-1);
690  break;
691 
692  } /* end switch */
693  if (result) printf("Error in writing header annotations\n");
694  }
695  return (result);
696 } /* wrtattr */
697 
int closeHDFstructs(int32_t sdfid, int32_t fid)
Definition: ANCroutines.c:281
integer, parameter int16
Definition: cubeio.f90:3
#define SUCCESS
Definition: ObpgReadGrid.h:15
int addAttr(int32_t sdsid, char *dataattr, int32_t datatype, char *dataunit)
Definition: ANCroutines.c:222
int j
Definition: decode_rs.h:73
int32_t wrtsds(int32_t sdfid, int rank, shape, int32_t datatype, char *datalabel, void *data)
Definition: ANCroutines.c:346
#define GEOMCLASS
Definition: ancil.h:45
int32 gridToGrid(int32 outergridid, int32 innergridid)
Definition: ANCroutines.c:70
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
int32 setupGrid(int32 fid, char *grpname)
Definition: ANCroutines.c:50
int32_t rewrtsds(int32_t sdsid, shape, void *data)
Definition: ANCroutines.c:400
#define MAXDESCLEN
Definition: ancil.h:42
README for MOD_PR02AQUA(AQUA) Version to set to For disabling creating and output data sets when in night mode
Definition: README.txt:96
int pwarning(char *string)
Definition: pexit.c:21
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
int32_t detachGeom(int32_t geomid)
Definition: ANCroutines.c:205
int32 linkGeom(int32 gridid, int32 geomid)
Definition: ANCroutines.c:186
char descr[MAXDESCLEN]
Definition: ancil.h:72
int deattachHDFgrid(int32_t gridid)
Definition: ANCroutines.c:267
int wrtattr(int32_t dfile, struct annotation *lannot, int numannarr)
Definition: ANCroutines.c:631
int32_t writeGeom(int32_t fid, int32_t gridid, char *geomname, int32_t bin_meth, int32_t registration, float vsize, float hsize, float max_north, float max_south, float max_west, float max_east)
Definition: ANCroutines.c:92
int32_t findGeomId(int32_t fid, char *geomname)
Definition: ANCroutines.c:162
#define MAXLABLEN
Definition: ancil.h:41
char filename[FILENAME_MAX]
Definition: atrem_corl1.h:122
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
void pexit(char *string)
Definition: pexit.c:10
Extra metadata that will be written to the HDF4 file l2prod rank
int startHDF(char *outfile, int32 *sdfid, int32 *fid, int32 mode)
Definition: ANCroutines.c:26
struct annotation * annot
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
int setSDSref(int32_t sdsid, int32_t gridid)
Definition: ANCroutines.c:245
#define MAXNAMELNG
Definition: ancil.h:43
int rdsds(char *filename, char *vgname, char *sdsname, dimsizes, void *inData)
Definition: ANCroutines.c:458
int i
Definition: decode_rs.h:71
int32_t SDSinFile(char *sdsname, char *longname, char *units, char *datafmt, int32_t datatype, int32_t sdfid, int32_t rank, shape, void *data, int32_t gridid)
Definition: ANCroutines.c:547
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
float32 f32
Definition: l2bin.cpp:104
#define ERROR
Definition: ancil.h:24
#define GEOMSIZE
Definition: ancil.h:46