1 /*
2 Copyright (c) 1994 - 2010, Lawrence Livermore National Security, LLC.
3 LLNL-CODE-425250.
4 All rights reserved.
5 
6 This file is part of Silo. For details, see silo.llnl.gov.
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 
12    * Redistributions of source code must retain the above copyright
13      notice, this list of conditions and the disclaimer below.
14    * Redistributions in binary form must reproduce the above copyright
15      notice, this list of conditions and the disclaimer (as noted
16      below) in the documentation and/or other materials provided with
17      the distribution.
18    * Neither the name of the LLNS/LLNL nor the names of its
19      contributors may be used to endorse or promote products derived
20      from this software without specific prior written permission.
21 
22 THIS SOFTWARE  IS PROVIDED BY  THE COPYRIGHT HOLDERS  AND CONTRIBUTORS
23 "AS  IS" AND  ANY EXPRESS  OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT
24 LIMITED TO, THE IMPLIED  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 A  PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN  NO  EVENT SHALL  LAWRENCE
26 LIVERMORE  NATIONAL SECURITY, LLC,  THE U.S.  DEPARTMENT OF  ENERGY OR
27 CONTRIBUTORS BE LIABLE FOR  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR  CONSEQUENTIAL DAMAGES  (INCLUDING, BUT NOT  LIMITED TO,
29 PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS  OF USE,  DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 LIABILITY, WHETHER  IN CONTRACT, STRICT LIABILITY,  OR TORT (INCLUDING
32 NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT  OF THE USE  OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 
35 This work was produced at Lawrence Livermore National Laboratory under
36 Contract No.  DE-AC52-07NA27344 with the DOE.
37 
38 Neither the  United States Government nor  Lawrence Livermore National
39 Security, LLC nor any of  their employees, makes any warranty, express
40 or  implied,  or  assumes  any  liability or  responsibility  for  the
41 accuracy, completeness,  or usefulness of  any information, apparatus,
42 product, or  process disclosed, or  represents that its use  would not
43 infringe privately-owned rights.
44 
45 Any reference herein to  any specific commercial products, process, or
46 services by trade name,  trademark, manufacturer or otherwise does not
47 necessarily  constitute or imply  its endorsement,  recommendation, or
48 favoring  by  the  United  States  Government  or  Lawrence  Livermore
49 National Security,  LLC. The views  and opinions of  authors expressed
50 herein do not necessarily state  or reflect those of the United States
51 Government or Lawrence Livermore National Security, LLC, and shall not
52 be used for advertising or product endorsement purposes.
53 */
54 
55 /* File-wide modifications:
56  *
57  *  Sean Ahern, Mon Mar 3 15:38:51 PST 1997 Rearranged most functions, adding
58  *  local storage of the return value, to facilitate instrumenting each
59  *  function.  (e.g. timing routines)
60  *
61  *  Sean Ahern, Thu Apr 29 15:41:27 PDT 1999
62  *  Made all function definitions ANSI.  Removed unused local variables.
63  *
64  *  Jeremy Meredith, Fri May 21 10:04:25 PDT 1999
65  *  Added a global _uzl structure.
66  *
67  *  Brad Whitlock, Mon Apr 8 15:17:17 PST 2002
68  *  Changed some headers to allow compilation under windows.
69  *
70  *  Thomas R. Treadway, Fri Jan  5 13:46:26 PST 2007
71  *  Added backward compatible symbols
72  */
73 
74 /* Private SILO functions.  */
75 #include "config.h" /* For a possible redefinition of setjmp/longjmp.
76                        Also for SDX driver detection.  */
77 #include <stdio.h>
78 #include <float.h>
79 #include <math.h>
80 #if HAVE_STDLIB_H
81 #include <stdlib.h>         /* For abort(). */
82 #endif
83 #if !defined(_WIN32)
84 #include <sys/file.h>       /* For R_OK and F_OK definitions. */
85 #endif
86 #include <errno.h>          /* For errno definitions. */
87 #if HAVE_STRING_H
88 #include <string.h>         /* For strerror */
89 #endif
90 #if HAVE_STRINGS_H
91 #include <strings.h>
92 #endif
93 #if !defined(_WIN32)
94 #include <sys/errno.h>      /* For errno definitions. */
95 #endif
96 #if HAVE_SYS_TYPES_H
97 #include <sys/types.h>
98 #endif
99 #if HAVE_SYS_STAT_H
100 #include <sys/stat.h>
101 #endif
102 #include <ctype.h>          /* For isalnum */
103 #if HAVE_SYS_FCNTL_H
104 #include <sys/fcntl.h>      /* for O_RDONLY */
105 #endif
106 #if HAVE_FCNTL_H
107 #include <fcntl.h>          /* for O_RDONLY */
108 #endif
109 #ifdef _WIN32
110 #include <windows.h>        /* for FileInfo funcs */
111 #include <io.h>             /* for FileInfo funcs */
112 #endif
113 
114 /* DB_MAIN must be defined before including silo_private.h. */
115 #define DB_MAIN
116 #include "silo_private.h"
117 #include "silo_drivers.h"
118 
119 /* The Silo_version_* variable is used to guarantee that code can't include
120  * one version of silo.h and link with a different version of libsilo.a.  This
121  * variable's name must change with every version of Silo.
122  *
123  * I would ordinary have silo.h be generated by configure so that the
124  * version number will automatically get compiled in.  But this isn't good
125  * for development with clearmake, since that would make silo.h be a
126  * view-private file.  Thus, any object that depends on silo.h would be
127  * invalid as a wink-in candidate.  */
128 int SILO_VERS_TAG = 0;
129 
130 /* Specify versions which are backward compatible with the current. */
131 /* No lines of  the form 'int Silo_version_Maj_Min_Pat = 0;' below
132    here indicates that this version is not backwards compatible with
133    any previous versions.*/
134 int Silo_version_4_10 = 0;
135 int Silo_version_4_10_0 = 0;
136 int Silo_version_4_10_1 = 0;
137 
138 /* Symbols for error handling */
139 PUBLIC int     DBDebugAPI = 0;  /*file desc for API debug messages      */
140 PUBLIC int     db_errno = 0;    /*last error number                     */
141 PUBLIC char    db_errfunc[64];  /*name of erring function               */
142 PUBLIC char   *_db_err_list[] =
143 {
144     "No error",                               /*00 */
145     "Bad file format type",                   /*01 */
146     "Not implemented",                        /*02 */
147     "File not found or invalid permissions",  /*03 */
148     "<<Reserved>>",                           /*04 */
149     "Internal error",                         /*05 */
150     "Not enough memory",                      /*06 */
151     "Invalid argument",                       /*07 */
152     "Low-level function call failed",         /*08 */
153     "Object not found",                       /*09 */
154     "Taurus database state error",            /*10 */
155     "Too many server connections",            /*11 */
156     "Protocol error",                         /*12 */
157     "Not a directory",                        /*13 */
158     "Too many open files",                    /*14 */
159     "Requested filter(s) not found",          /*15 */
160     "Too many filters registered",            /*16 */
161     "File already exists",                    /*17 */
162     "Specified file is actually a directory", /*18 */
163     "File lacks read permission",             /*19 */
164     "System level error occured",             /*20 */
165     "File lacks write permission",            /*21 */
166     "Invalid variable name - only alphanumeric and `_'", /* 22 */
167     "Overwrite not allowed. See DBSetAllowOverwrites()", /* 23 */
168     "Checksum failure.",                      /* 24 */
169     "Compression failure.",                   /* 25 */
170     "Grab driver enabled.",                   /* 26 */
171     "File was closed or never opened/created.",/* 27 */
172     "File multiply opened w/>1 not read-only.", /* 28 */
173     "Specified driver cannot open this file.",/* 29 */
174     "Optlist contains options for wrong class.",/* 30 */
175     "Feature not enabled in this build.", /* 31 */
176     "Too many file options sets (missing DBUnregisterFileOptionsSet?).", /* 32 */
177     "\nYou have tried to open or create a Silo file using\n"
178     "the HDF5 driver. However, the installation of Silo\n"
179     "you are using does not have the HDF5 driver enabled.\n"
180     "You need to configure the Silo library using the\n"
181     "--with-hdf5=<INC,LIB> option and re-compile and\n"
182     "re-install Silo. If you do not have an installation\n"
183     "of HDF5 already on your sytem, you will also need\n"
184     "to obtain HDF5 from www.hdfgroup.org and install it.", /* 33 */
185     "Empty objects not permitted. See DBSetAllowEmptyObjects()." /* 34 */
186     "No more tiny array buffer space for custom object." /* 35 */
187 };
188 
189 PRIVATE unsigned char _db_fstatus[DB_NFILES];  /*file status  */
190 typedef struct reg_status_t {
191     DBfile *f;
192     unsigned int n;
193     int w;
194 } reg_status_t;
195 PRIVATE reg_status_t _db_regstatus[DB_NFILES] = /* DB_NFILES triples of zeros */
196     {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
197      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
198      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
199      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
200      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
201      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
202      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
203      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
204      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
205      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
206      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
207      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
208      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
209      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
210      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
211      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
212      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
213      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
214      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
215      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
216      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
217      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
218      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
219      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
220 
221 PRIVATE filter_t _db_filter[DB_NFILTERS];
222 const static char *api_dummy = 0;
223 
224 /* stat struct definition */
225 typedef struct db_silo_stat_t {
226 #ifndef SIZEOF_OFF64_T
227 #error missing definition for SIZEOF_OFF64_T in silo_private.h
228 #else
229     struct stat s;
230 #endif
231 #ifdef _WIN32
232     DWORD fileindexlo;
233     DWORD fileindexhi;
234 #endif
235 } db_silo_stat_t;
236 
237 /* This function is used in API_BEGIN macros and so we forward declare it */
238 PRIVATE int db_isregistered_file(DBfile *dbfile, const db_silo_stat_t *filestate);
239 
240 /* Global structures for option lists.  */
241 struct _ma     _ma;
242 struct _ms     _ms;
243 struct _csgm   _csgm;
244 struct _pm     _pm;
245 struct _qm     _qm;
246 struct _um     _um;
247 struct _uzl    _uzl;
248 struct _phzl   _phzl;
249 struct _csgzl  _csgzl;
250 struct _mm     _mm;
251 struct _cu     _cu;
252 struct _dv     _dv;
253 struct _mrgt   _mrgt;
254 
255 SILO_Globals_t SILO_Globals = {
256     DBAll, /* dataReadMask */
257     TRUE,  /* allowOverwrites */
258     FALSE, /* allowEmptyObjects */
259     FALSE, /* enableChecksums */
260     FALSE,  /* enableFriendlyHDF5Names */
261     FALSE, /* enableGrabDriver */
262     3,     /* maxDeprecateWarnings */
263     0,     /* compressionParams (null) */
264     2.0,   /* compressionMinratio */
265     0,     /* compressionErrmode (fallback) */
266     {      /* file options sets [32 of them] */
267         0, 0, 0, 0, 0, 0, 0, 0,
268 	0, 0, 0, 0, 0, 0, 0, 0,
269         0, 0, 0, 0, 0, 0, 0, 0,
270 	0, 0, 0, 0, 0, 0, 0, 0
271     },
272     DB_TOP,/* _db_err_level */
273     0,     /* _db_err_func */
274     DB_NONE,/* _db_err_level_drvr */
275     0,     /* Jstk */
276     DEFAULT_DRIVER_PRIORITIES
277 };
278 
279 INTERNAL int
db_FullyDeprecatedConvention(const char * name)280 db_FullyDeprecatedConvention(const char *name)
281 {
282     if (strcmp(name, "_visit_defvars") == 0)
283     {
284         DEPRECATE_MSG(name,4,6,"DBPutDefvars")
285     }
286     else if (strcmp(name, "_visit_domain_groups") == 0)
287     {
288         DEPRECATE_MSG(name,4,6,"DBPutMrgtree")
289     }
290     else if (strcmp(name, "_disjoint_elements") == 0)
291     {
292         DEPRECATE_MSG(name,4,6,"DBOPT_DISJOINT_MODE option")
293     }
294     else if (strncmp(name, "MultivarToMultimeshMap_",23) == 0)
295     {
296         DEPRECATE_MSG(name,4,6,"DBOPT_MMESH_NAME option for DBPutMultivar")
297     }
298     return 0;
299 }
300 
301 /*-------------------------------------------------------------------------
302  * Function:    db_perror
303  *
304  * Purpose:     Print error message to standard error
305  *
306  * Return:      Success:        -1
307  *
308  *              Failure:        never fails
309  *
310  * Programmer:  matzke@viper
311  *              Thu Nov  3 15:16:42 PST 1994
312  *
313  * Modifications:
314  *    Robb Matzke, Tue Dec 20 20:55:14 EST 1994
315  *    If s is "" then we use the previous value of s.
316  *-------------------------------------------------------------------------*/
317 INTERNAL int
db_perror(char const * s,int errorno,char const * fname)318 db_perror(char const *s, int errorno, char const *fname)
319 {
320     int            call_abort = 0;
321     static char    old_s[256] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
322                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
323                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
324                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
325                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
326                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
327                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
328                                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
329 
330     /*
331      * Save error number and function name so application
332      * can read them later.
333      */
334     db_errno = errorno;
335     if (fname)
336         strncpy(db_errfunc, fname, sizeof(db_errfunc) - 1);
337     db_errfunc[sizeof(db_errfunc) - 1] = '\0';
338 
339     /*
340      * If `s' is an empty string, then use the same string
341      * as last time.
342      */
343     if (s && !*s) {
344         s = old_s;
345     }
346     else if (s) {
347         strncpy(old_s, s, sizeof(old_s));
348         old_s[sizeof(old_s) - 1] = '\0';
349     }
350     else {
351         old_s[0] = '\0';
352     }
353 
354     switch (SILO_Globals._db_err_level) {
355         case DB_NONE:
356             if (SILO_Globals.Jstk)
357                 longjmp(SILO_Globals.Jstk->jbuf, -1);
358             return -1;
359         case DB_TOP:
360             if (SILO_Globals.Jstk)
361                 longjmp(SILO_Globals.Jstk->jbuf, -1);
362             break;
363         case DB_ALL:
364             break;
365         case DB_ABORT:
366             call_abort = 1;
367             break;
368         default:
369             call_abort = 1;
370             break;
371     }
372 
373     /*
374      * Issue the error message to standard error or by calling
375      * the indicated error handling routine.
376      */
377     if (SILO_Globals._db_err_func) {
378         int flen = 0, elen = 0, slen = 0;
379         char *better_s;
380 
381         elen = strlen(db_strerror(errorno));
382         if (fname && *fname) flen = strlen(fname) + 2;
383         if (s && *s) slen = strlen(s) + 2;
384         better_s = (char *) malloc(elen + flen + slen + 1);
385 
386         if (fname && *fname)
387             sprintf(better_s, "%s: ", fname);
388         sprintf(better_s + flen, "%s", db_strerror(errorno));
389         if (s && *s)
390             sprintf(better_s + flen + elen, ": %s", s);
391 
392         SILO_Globals._db_err_func((char*)better_s);
393 
394         free(better_s);
395     }
396     else {
397         if (fname && *fname)
398             fprintf(stderr, "%s: ", fname);
399         fprintf(stderr, "%s", db_strerror(errorno));
400         if (s && *s)
401             fprintf(stderr, ": %s", s);
402         putc('\n', stderr);
403     }
404 
405     if (call_abort) {
406         fflush(stdout);
407         fprintf(stderr, "SILO Aborting...\n");
408         fflush(stderr);
409         abort();
410     }
411 
412     return -1;
413 }
414 
415 /*-------------------------------------------------------------------------
416  * Function:    db_strerror
417  *
418  * Purpose:     Return message associated with error number
419  *
420  * Return:      Success:        ptr to string
421  *
422  *              Failure:        ptr to "No error"
423  *
424  * Programmer:  matzke@viper
425  *              Thu Nov  3 15:18:15 PST 1994
426  *
427  * Modifications:
428  *    Robb Matzke, Tue Feb 28 11:08:47 EST 1995
429  *    If error number is out of range, we make a new error message that
430  *    has the error number.  That makes this function act like DBErrString
431  *    and allows for the use of user-defined error numbers that are
432  *    larger than E_NERRORS or less than zero.
433  *-------------------------------------------------------------------------*/
434 INTERNAL char *
db_strerror(int errorno)435 db_strerror(int errorno)
436 {
437     static char    s[32];
438 
439     if (errorno < 0 || errorno >= NELMTS(_db_err_list)) {
440         sprintf(s, "Error %d", errorno);
441         return s;
442     }
443     return _db_err_list[errorno];
444 }
445 
446 /*----------------------------------------------------------------------
447  *  Function                                                  db_strndup
448  *
449  *  Purpose
450  *
451  *      Return a duplicate of the given string (with length), where
452  *      default mem-mgr was used to allocate the necessary space.
453  *
454  *  Modified
455  *    Robb Matzke, Thu Nov 10 12:27:10 EST 1994
456  *    Added error mechanism
457  *
458  *    Eric Brugger, Wed Jul 25 14:57:28 PDT 2001
459  *    Renamed the routine.
460  *
461  *---------------------------------------------------------------------*/
462 INTERNAL char *
db_strndup(const char * string,int len)463 db_strndup(const char *string, int len)
464 {
465     char          *out = NULL;
466     char          *me = "strndup";
467 
468     if (string == NULL || len <= 0)
469         return (NULL);
470 
471     if (NULL == (out = ALLOC_N(char, len + 1))) {
472         db_perror(NULL, E_NOMEM, me);
473         return NULL;
474     }
475 
476     strncpy(out, string, len);
477     out[len] = '\0';
478 
479     return (out);
480 }
481 
482 /*----------------------------------------------------------------------
483  * Function: DBVariableNameValid
484  *
485  * Purpose   Check the validity of a Silo variable name.
486  *
487  * Author:   Sean Ahern, Tue Sep 28 10:47:52 PDT 1999
488  *
489  * Returns:  1 if the name is valid
490  *           0 otherwise
491  *
492  * Modified:
493  *    Sean Ahern, Fri Oct  1 11:36:34 PDT 1999
494  *    Added '/' to the list of allowed characters.  We need this for putting
495  *    variables in subdirectories.
496  *
497  *    Sean Ahern, Tue Oct  5 13:51:07 PDT 1999
498  *    Added ':' processing so that we can reference variables in other files.
499  *
500  *    Lisa J. Roberts, Thu Dec 16 17:33:26 PST 1999
501  *    Removed the abort called if the name validation fails.
502  *
503  *    Robb Matzke, 2000-06-02
504  *    Omit printing error message if error handling mode is DB_NONE. After
505  *    all, some applications check return values and then print their own
506  *    error message.
507  *
508  *    Hank Childs, Thu Sep  7 14:17:13 PDT 2000
509  *    Allow variable names to be relative. [HYPer02087]
510  *
511  *    Mark C. Miller, Mon Oct 22 22:08:09 PDT 2007
512  *    Made it part of the public API.
513  *
514  *---------------------------------------------------------------------*/
515 PUBLIC int
DBVariableNameValid(const char * s)516 DBVariableNameValid(const char *s)
517 {
518     int             len;
519     int             i;
520     char           *p = NULL;
521 
522     /* If there's a ':' in the name, allow anything before the ':'.  After the
523      * ':' we have to be more strict. */
524 
525     p = (char *)strchr(s,':');
526     if (p == NULL)
527         p = (char *)s;
528     else
529         p++;    /* Move one character past the ':'. */
530 
531     len = strlen(p);
532 
533     /* Every character has to be alphanumeric or the `_' character. */
534     for(i=0;i<len;i++)
535     {
536         int  okay = 0;
537 
538         if (isalnum(p[i]) || (p[i] == '_') || (p[i] == '/'))
539         {
540             okay = 1;
541         }
542 
543         /* Don't need to check for the end of the string because of the
544          * short circuit rule and the null character at end of string. */
545         if ((p[i] == '.') && (p[i+1] == '.') && (p[i+2] == '/'))
546         {
547             okay = 1;
548             i += 2;  /* 2 = strlen("../") - 1 (from `for' loop's i++) */
549         }
550 
551         if (! okay)
552         {
553             if (DB_NONE!=SILO_Globals._db_err_level)
554             {
555                 fprintf(stderr,"\"%s\" is an invalid name.  Silo variable\n"
556                         "names may contain only alphanumeric characters\n"
557                         "or the _ character.\n", s);
558             }
559             return 0;
560         }
561     }
562 
563     return 1;
564 }
565 /* kept this to deal with non-const qualified API */
566 INTERNAL int
db_VariableNameValid(char const * s)567 db_VariableNameValid(char const *s)
568 {
569     return DBVariableNameValid(s);
570 }
571 
572 
573 /*----------------------------------------------------------------------
574  *  Routine                                              _DBQQCalcStride
575  *
576  *  Purpose
577  *
578  *      Calculate the strides given the dimensions and major-order.
579  *
580  *      Works for 1D, 2D and 3D variables/meshes, collinear or
581  *      non-collinear, materials, too.
582  *
583  *--------------------------------------------------------------------*/
584 INTERNAL void
_DBQQCalcStride(int stride[],int dims[],int ndims,int major_order)585 _DBQQCalcStride(int stride[], int dims[], int ndims, int major_order)
586 {
587     int            i;
588 
589      /*------------------------------------------------------
590       * Define strides for accessing adjacent elements based
591       * on whether arrays are stored row-major or column-major.
592       *-----------------------------------------------------*/
593 
594     if (major_order == DB_ROWMAJOR) {
595         stride[0] = 1;
596 
597         for (i = 1; i < ndims; i++) {
598             stride[i] = stride[i - 1] * dims[i - 1];
599         }
600     }
601     else {
602         stride[ndims - 1] = 1;
603 
604         for (i = ndims - 2; i >= 0; i--) {
605             stride[i] = stride[i + 1] * dims[i + 1];
606         }
607     }
608 }
609 
610 /*----------------------------------------------------------------------
611  *  Routine                                                 _DBQMSetStride
612  *
613  *  Purpose
614  *
615  *      Set the stride component for the given quad mesh.
616  *
617  *      Works for 1D, 2D and 3D meshes, collinear or non-collinear.
618  *
619  * Modified
620  *    Robb Matzke, Wed Jan 11 06:35:33 PST 1995
621  *    Changed name from QM_SetStride because it conflicted with MeshTV.
622  *--------------------------------------------------------------------*/
623 INTERNAL void
_DBQMSetStride(DBquadmesh * qmesh)624 _DBQMSetStride(DBquadmesh *qmesh)
625 {
626     _DBQQCalcStride(qmesh->stride, qmesh->dims, qmesh->ndims,
627                     qmesh->major_order);
628 }
629 
630 /*----------------------------------------------------------------------
631  *  Routine                                         SW_GetDatatypeString
632  *
633  *  Function
634  *
635  *      Return the string representation of the given SWAT data type.
636  *
637  *  Modified
638  *    Robb Matzke, Thu Nov 10 12:28:44 EST 1994
639  *    Added error mechanism
640  *
641  *    Robb Matzke, Thu Nov 10 12:30:43 EST 1994
642  *    An invalid `type' is now an error.
643  *
644  *    Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
645  *    Adding support for long long type.
646  *
647  *    Mark C. Miller, Fri Nov 13 15:32:02 PST 2009
648  *    Changed name of "long long" type to "longlong" as PDB is
649  *    sensitive to spaces in type names.
650  *
651  *    Mark C. Miller, Tue Nov 17 22:29:35 PST 2009
652  *    Fixed memory error by extending length of alloc'd string to
653  *    support "long_long". Changed name of long long data type
654  *    to match what PDB proper does.
655  *
656  *    Mark C. Miller, Mon Dec  7 09:50:19 PST 2009
657  *    Conditionally compile long long support only when its
658  *    different from long.
659  *
660  *    Mark C. Miller, Mon Jan 11 16:02:16 PST 2010
661  *    Made long long support UNconditionally compiled.
662  *---------------------------------------------------------------------*/
663 INTERNAL char *
db_GetDatatypeString(int type)664 db_GetDatatypeString(int type)
665 {
666     char          *str = NULL;
667     char          *me = "db_GetDatatypeString";
668 
669     if (NULL == (str = ALLOC_N(char, 10))) {
670         db_perror(NULL, E_NOMEM, me);
671         return NULL;
672     }
673 
674     switch (type) {
675         case DB_INT:
676             strcpy(str, "integer");
677             break;
678         case DB_SHORT:
679             strcpy(str, "short");
680             break;
681         case DB_LONG:
682             strcpy(str, "long");
683             break;
684         case DB_LONG_LONG:
685             strcpy(str, "long_long");
686             break;
687         case DB_FLOAT:
688             strcpy(str, "float");
689             break;
690         case DB_DOUBLE:
691             strcpy(str, "double");
692             break;
693         case DB_CHAR:
694             strcpy(str, "char");
695             break;
696         default:
697             db_perror("type", E_BADARGS, me);
698             FREE(str);
699             return NULL;
700     }
701 
702     return (str);
703 }
704 
705 /*-------------------------------------------------------------------------
706  * Function:    silo_db_close
707  *
708  * Purpose:     Free public parts of DBfile.  This function is called
709  *              after the file has been closed and the private parts
710  *              have been freed.
711  *
712  * Return:      Success:        NULL
713  *
714  *              Failure:        never fails
715  *
716  * Programmer:  matzke@viper
717  *              Wed Nov  2 13:55:22 PST 1994
718  *
719  * Modifications:
720  *   Mark C. Miller, Tue Feb  3 09:53:53 PST 2009
721  *   Changed name to silo_db_close to avoid collision with popular BRLCAD
722  *   libs. Added stuff to free GrabId and set Grab related stuff to zero.
723  *-------------------------------------------------------------------------*/
724 INTERNAL DBfile *
silo_db_close(DBfile * dbfile)725 silo_db_close(DBfile *dbfile)
726 {
727     if (dbfile) {
728         db_FreeToc(dbfile);
729         FREE(dbfile->pub.GrabId);
730         dbfile->pub.GrabId = 0;
731         dbfile->pub.Grab = FALSE;
732         FREE(dbfile->pub.name);
733         FREE(dbfile);
734     }
735 
736     return NULL;
737 }
738 
739 /*-------------------------------------------------------------------------
740  * Function:    db_AllocToc
741  *
742  * Purpose:     Allocate an empty table of contents for a new file.
743  *
744  * Return:      Success:        ptr to new DBtoc
745  *
746  *              Failure:        NULL, db_errno set.
747  *
748  * Modifications:
749  *    Eric Brugger, Thu Feb  9 14:43:50 PST 1995
750  *    I modified the routine to handle the obj in the table of contents.
751  *
752  *    Sean Ahern, Fri Aug 23 16:59:02 PDT 1996
753  *    Added multimats.
754  *
755  *    Jeremy Meredith, Sept 18 1998
756  *    Added multi-block material species.
757  *-------------------------------------------------------------------------*/
758 INTERNAL DBtoc *
db_AllocToc(void)759 db_AllocToc(void)
760 {
761     DBtoc         *toc = NULL;
762     char          *me = "db_AllocToc";
763 
764     if (NULL == (toc = ALLOC(DBtoc))) {
765         db_perror(NULL, E_NOMEM, me);
766         return NULL;
767     }
768 
769     toc->curve_names = NULL;
770     toc->ncurve = 0;
771 
772     toc->csgmesh_names = NULL;
773     toc->ncsgmesh = 0;
774 
775     toc->csgvar_names = NULL;
776     toc->ncsgvar = 0;
777 
778     toc->defvars_names = NULL;
779     toc->ndefvars = 0;
780 
781     toc->multimesh_names = NULL;
782     toc->nmultimesh = 0;
783 
784     toc->multimeshadj_names = NULL;
785     toc->nmultimeshadj = 0;
786 
787     toc->multivar_names = NULL;
788     toc->nmultivar = 0;
789 
790     toc->multimat_names = NULL;
791     toc->nmultimat = 0;
792 
793     toc->multimatspecies_names = NULL;
794     toc->nmultimatspecies = 0;
795 
796     toc->qmesh_names = NULL;
797     toc->nqmesh = 0;
798 
799     toc->qvar_names = NULL;
800     toc->nqvar = 0;
801 
802     toc->ucdmesh_names = NULL;
803     toc->nucdmesh = 0;
804 
805     toc->ucdvar_names = NULL;
806     toc->nucdvar = 0;
807 
808     toc->ptmesh_names = NULL;
809     toc->nptmesh = 0;
810 
811     toc->ptvar_names = NULL;
812     toc->nptvar = 0;
813 
814     toc->var_names = NULL;
815     toc->nvar = 0;
816 
817     toc->mat_names = NULL;
818     toc->nmat = 0;
819 
820     toc->obj_names = NULL;
821     toc->nobj = 0;
822 
823     toc->dir_names = NULL;
824     toc->ndir = 0;
825 
826     toc->array_names = NULL;
827     toc->narray = 0;
828 
829     toc->mrgtree_names = NULL;
830     toc->nmrgtree = 0;
831 
832     toc->groupelmap_names = NULL;
833     toc->ngroupelmap = 0;
834 
835     toc->mrgvar_names = NULL;
836     toc->nmrgvar = 0;
837 
838     return(toc);
839 }
840 
841 /*-------------------------------------------------------------------------
842  * Function:    db_FreeToc
843  *
844  * Purpose:     Free the table of contents associated with a file.
845  *
846  * Return:      Success:        0
847  *
848  *              Failure:        -1
849  *
850  * Modifications:
851  *    Robb Matzke, Thu Dec 1 10:22:11 PST 1994
852  *    Errors in device drivers might leave the table of
853  *    contents in a not-fully-initialized state.  Therefore,
854  *    this routine always checks for nil pointers before
855  *    dereferencing them.
856  *
857  *    Robb Matzke, Fri Dec 2 13:13:01 PST 1994
858  *    Removed all references to SCORE memory management.
859  *
860  *    Eric Brugger, Thu Feb  9 14:43:50 PST 1995
861  *    I modified the routine to handle the obj in the table of contents.
862  *
863  *    Sean Ahern, Fri Jun 21 10:56:15 PDT 1996
864  *    Added handling for multimats.
865  *
866  *    Jeremy Meredith, Sept 18 1998
867  *    Added multi-block species.
868  *-------------------------------------------------------------------------*/
869 INTERNAL int
db_FreeToc(DBfile * dbfile)870 db_FreeToc(DBfile *dbfile)
871 {
872     int            i;
873     DBtoc         *toc = NULL;
874     char          *me = "db_FreeToc";
875 
876     if (!dbfile)
877         return db_perror(NULL, E_NOFILE, me);
878     if (!dbfile->pub.toc)
879         return 0;
880 
881     toc = dbfile->pub.toc;
882 
883     if (toc->ncurve > 0) {
884         if (toc->curve_names) {
885             for (i = 0; i < toc->ncurve; i++) {
886                 FREE(toc->curve_names[i]);
887             }
888             FREE(toc->curve_names);
889         }
890     }
891 
892     if (toc->nmultimesh > 0) {
893         if (toc->multimesh_names) {
894             for (i = 0; i < toc->nmultimesh; i++) {
895                 FREE(toc->multimesh_names[i]);
896             }
897             FREE(toc->multimesh_names);
898         }
899     }
900 
901     if (toc->nmultimeshadj > 0) {
902         if (toc->multimeshadj_names) {
903             for (i = 0; i < toc->nmultimeshadj; i++) {
904                 FREE(toc->multimeshadj_names[i]);
905             }
906             FREE(toc->multimeshadj_names);
907         }
908     }
909 
910     if (toc->nmultivar > 0) {
911         if (toc->multivar_names) {
912             for (i = 0; i < toc->nmultivar; i++) {
913                 FREE(toc->multivar_names[i]);
914             }
915             FREE(toc->multivar_names);
916         }
917     }
918 
919     if (toc->nmultimat > 0) {
920         if (toc->multimat_names) {
921             for(i=0; i < toc->nmultimat; i++) {
922                 FREE(toc->multimat_names[i]);
923             }
924             FREE(toc->multimat_names);
925         }
926     }
927 
928     if (toc->nmultimatspecies > 0) {
929         if (toc->multimatspecies_names) {
930             for(i=0; i < toc->nmultimatspecies; i++) {
931                 FREE(toc->multimatspecies_names[i]);
932             }
933             FREE(toc->multimatspecies_names);
934         }
935     }
936 
937     if (toc->ncsgmesh > 0) {
938         if (toc->csgmesh_names) {
939             for (i = 0; i < toc->ncsgmesh; i++) {
940                 FREE(toc->csgmesh_names[i]);
941             }
942             FREE(toc->csgmesh_names);
943         }
944     }
945     if (toc->ncsgvar > 0) {
946         if (toc->csgvar_names) {
947             for (i = 0; i < toc->ncsgvar; i++) {
948                 FREE(toc->csgvar_names[i]);
949             }
950             FREE(toc->csgvar_names);
951         }
952     }
953 
954     if (toc->ndefvars > 0) {
955         if (toc->defvars_names) {
956             for (i = 0; i < toc->ndefvars; i++) {
957                 FREE(toc->defvars_names[i]);
958             }
959             FREE(toc->defvars_names);
960         }
961     }
962 
963     if (toc->nqmesh > 0) {
964         if (toc->qmesh_names) {
965             for (i = 0; i < toc->nqmesh; i++) {
966                 FREE(toc->qmesh_names[i]);
967             }
968             FREE(toc->qmesh_names);
969         }
970     }
971 
972     if (toc->nqvar > 0) {
973         if (toc->qvar_names) {
974             for (i = 0; i < toc->nqvar; i++) {
975                 FREE(toc->qvar_names[i]);
976             }
977             FREE(toc->qvar_names);
978         }
979     }
980 
981     if (toc->nptmesh > 0) {
982         if (toc->ptmesh_names) {
983             for (i = 0; i < toc->nptmesh; i++) {
984                 FREE(toc->ptmesh_names[i]);
985             }
986             FREE(toc->ptmesh_names);
987         }
988     }
989 
990     if (toc->nptvar > 0) {
991         if (toc->ptvar_names) {
992             for (i = 0; i < toc->nptvar; i++) {
993                 FREE(toc->ptvar_names[i]);
994             }
995             FREE(toc->ptvar_names);
996         }
997     }
998 
999     if (toc->nmat > 0) {
1000         if (toc->mat_names) {
1001             for (i = 0; i < toc->nmat; i++) {
1002                 FREE(toc->mat_names[i]);
1003             }
1004             FREE(toc->mat_names);
1005         }
1006     }
1007 
1008     if (toc->nucdmesh > 0) {
1009         if (toc->ucdmesh_names) {
1010             for (i = 0; i < toc->nucdmesh; i++) {
1011                 FREE(toc->ucdmesh_names[i]);
1012             }
1013             FREE(toc->ucdmesh_names);
1014         }
1015     }
1016 
1017     if (toc->nucdvar > 0) {
1018         if (toc->ucdvar_names) {
1019             for (i = 0; i < toc->nucdvar; i++) {
1020                 FREE(toc->ucdvar_names[i]);
1021             }
1022             FREE(toc->ucdvar_names);
1023         }
1024     }
1025 
1026     if (toc->nvar > 0) {
1027         if (toc->var_names) {
1028             for (i = 0; i < toc->nvar; i++) {
1029                 FREE(toc->var_names[i]);
1030             }
1031             FREE(toc->var_names);
1032         }
1033     }
1034 
1035     if (toc->nobj > 0) {
1036         if (toc->obj_names) {
1037             for (i = 0; i < toc->nobj; i++) {
1038                 FREE(toc->obj_names[i]);
1039             }
1040             FREE(toc->obj_names);
1041         }
1042     }
1043 
1044     if (toc->ndir > 0) {
1045         if (toc->dir_names) {
1046             for (i = 0; i < toc->ndir; i++) {
1047                 FREE(toc->dir_names[i]);
1048             }
1049             FREE(toc->dir_names);
1050         }
1051     }
1052 
1053     if (toc->narray > 0) {
1054         if (toc->array_names) {
1055             for (i = 0; i < toc->narray; i++) {
1056                 FREE(toc->array_names[i]);
1057             }
1058             FREE(toc->array_names);
1059         }
1060     }
1061 
1062     if (toc->nmrgtree > 0) {
1063         if (toc->mrgtree_names) {
1064             for (i = 0; i < toc->nmrgtree; i++) {
1065                 FREE(toc->mrgtree_names[i]);
1066             }
1067             FREE(toc->mrgtree_names);
1068         }
1069     }
1070 
1071     if (toc->ngroupelmap > 0) {
1072         if (toc->groupelmap_names) {
1073             for (i = 0; i < toc->ngroupelmap; i++) {
1074                 FREE(toc->groupelmap_names[i]);
1075             }
1076             FREE(toc->groupelmap_names);
1077         }
1078     }
1079 
1080     if (toc->nmrgvar > 0) {
1081         if (toc->mrgvar_names) {
1082             for (i = 0; i < toc->nmrgvar; i++) {
1083                 FREE(toc->mrgvar_names[i]);
1084             }
1085             FREE(toc->mrgvar_names);
1086         }
1087     }
1088 
1089     FREE(dbfile->pub.toc);
1090     return 0;
1091 }
1092 
1093 /*----------------------------------------------------------------------
1094  *  Routine                                          silo_GetMachDataSize
1095  *
1096  *  Purpose
1097  *
1098  *      Return the byte length of the given data type ON THE CURRENT
1099  *      MACHINE.
1100  *
1101  *  Notes
1102  *
1103  *  Modified
1104  *    Robb Matzke, Thu Nov 10 12:33:44 EST 1994
1105  *    Added error mechanism.  An invalid `datatype' is an error.
1106  *
1107  *    Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
1108  *    Adding support for long long type.
1109  *
1110  *    Mark C. Miller, Mon Dec  7 09:50:19 PST 2009
1111  *    Conditionally compile long long support only when its
1112  *    different from long.
1113  *
1114  *    Mark C. Miller, Mon Jan 11 16:02:16 PST 2010
1115  *    Made long long support UNconditionally compiled.
1116  *--------------------------------------------------------------------*/
1117 INTERNAL int
db_GetMachDataSize(int datatype)1118 db_GetMachDataSize(int datatype)
1119 {
1120     int            size;
1121     char          *me = "db_GetMachDataSize";
1122 
1123     switch (datatype)
1124     {
1125         case DB_CHAR:      size = sizeof(char); break;
1126         case DB_SHORT:     size = sizeof(short); break;
1127         case DB_INT:       size = sizeof(int); break;
1128         case DB_LONG:      size = sizeof(long); break;
1129         case DB_LONG_LONG: size = sizeof(long long); break;
1130         case DB_FLOAT:     size = sizeof(float); break;
1131         case DB_DOUBLE:    size = sizeof(double); break;
1132         default:           return db_perror("datatype", E_BADARGS, me);
1133     }
1134     return (size);
1135 }
1136 
1137 /*----------------------------------------------------------------------
1138  *  Routine                                         db_GetDatatypeID
1139  *
1140  *  Purpose
1141  *
1142  *      Return the SILO integer definition for the provided ascii datatype
1143  *      description. That is, convert "float" to SWAT_FLOAT (i.e., 19).
1144  *
1145  *  Notes
1146  *
1147  *  Modified
1148  *    Robb Matzke, Thu Nov 10 12:35:24 EST 1994
1149  *    Added error mechanism.  An invalid `dataname' is an error.
1150  *
1151  *    Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
1152  *    Adding support for long long type.
1153  *
1154  *    Mark C. Miller, Fri Nov 13 15:32:02 PST 2009
1155  *    Changed name of "long long" type to "longlong" as PDB is
1156  *    sensitive to spaces in type names.
1157  *
1158  *    Mark C. Miller, Tue Nov 17 22:30:30 PST 2009
1159  *    Changed name of long long datatype to match PDB proper.
1160  *
1161  *    Mark C. Miller, Mon Dec  7 09:50:19 PST 2009
1162  *    Conditionally compile long long support only when its
1163  *    different from long.
1164  *
1165  *    Mark C. Miller, Mon Jan 11 16:02:16 PST 2010
1166  *    Made long long support UNconditionally compiled.
1167  *--------------------------------------------------------------------*/
1168 INTERNAL int
db_GetDatatypeID(char const * const dataname)1169 db_GetDatatypeID(char const * const dataname)
1170 {
1171     int            size;
1172     char          *me = "db_GetDatatypeID";
1173 
1174     if (STR_BEGINSWITH(dataname, "integer"))
1175         size = DB_INT;
1176     else if (STR_BEGINSWITH(dataname, "short"))
1177         size = DB_SHORT;
1178     else if (STR_BEGINSWITH(dataname, "long_long"))
1179         size = DB_LONG_LONG;
1180     else if (STR_BEGINSWITH(dataname, "long"))
1181         size = DB_LONG;
1182     else if (STR_BEGINSWITH(dataname, "float"))
1183         size = DB_FLOAT;
1184     else if (STR_BEGINSWITH(dataname, "double"))
1185         size = DB_DOUBLE;
1186     else if (STR_BEGINSWITH(dataname, "char"))
1187         size = DB_CHAR;
1188     else
1189         return db_perror("dataname", E_BADARGS, me);
1190 
1191     return (size);
1192 }
1193 
1194 /*----------------------------------------------------------------------
1195  *  Routine                                              DBGetObjtypeTag
1196  *
1197  *  Purpose
1198  *
1199  *      Return the tag (integer ID) for the given object type.
1200  *
1201  *  Programmer
1202  *
1203  *      Jeffery W. Long, NSSD-B
1204  *
1205  *  Parameters
1206  *
1207  *      type_name         {In}    {Name of object type to inquire about}
1208  *
1209  *  Notes
1210  *
1211  *      This function and it's counterpart, DBGetObjtypeName(), must
1212  *      stay in sync. Changes to this function must be mirrored in
1213  *      the other.
1214  *
1215  *  Modifications
1216  *    Al Leibee,Mon Aug  1 16:16:00 PDT 1994
1217  *    Added material species.
1218  *
1219  *    Robb Matzke, Tue Oct 25 08:57:56 PDT 1994
1220  *    Added compound array.
1221  *
1222  *    Robb Matzke, Wed Nov 9 14:04:23 EST 1994
1223  *    Added error mechanism.
1224  *
1225  *    Robb Matzke, Fri Dec 2 09:58:51 PST 1994
1226  *    Added `zonelist' and `facelist' and `edgelist'
1227  *
1228  *    Eric Brugger, Tue Feb  7 11:05:39 PST 1995
1229  *    I modified the routine to return DB_USERDEF if the type_name
1230  *    is not known.
1231  *
1232  *    Katherine Price, Thu May 25 10:00:50 PDT 1995
1233  *    Added multi-block material.
1234  *
1235  *    Jeremy Meredith, Sept 18 1998
1236  *    Added multi-block material species.
1237  *--------------------------------------------------------------------*/
1238 PUBLIC int
DBGetObjtypeTag(char const * type_name)1239 DBGetObjtypeTag(char const *type_name)
1240 {
1241     int            tag;
1242     char          *me = "DBGetObjtypeTag";
1243 
1244     if (!type_name || !*type_name)
1245         return db_perror("type name", E_BADARGS, me);
1246 
1247     if (type_name[0] == 'D' && type_name[1] == 'B')
1248         type_name += 2;
1249 
1250     if (STR_EQUAL(type_name, "multiblockmesh") ||
1251         STR_EQUAL(type_name, "multimesh"))
1252         tag = DB_MULTIMESH;
1253 
1254     else if (STR_EQUAL(type_name, "multimeshadj"))
1255         tag = DB_MULTIMESHADJ;
1256 
1257     else if (STR_EQUAL(type_name, "multiblockvar") ||
1258              STR_EQUAL(type_name, "multivar"))
1259         tag = DB_MULTIVAR;
1260 
1261     else if (STR_EQUAL(type_name, "multiblockmat") ||
1262              STR_EQUAL(type_name, "multimat"))
1263         tag = DB_MULTIMAT;
1264 
1265     else if (STR_EQUAL(type_name, "multimatspecies"))
1266         tag = DB_MULTIMATSPECIES;
1267 
1268     else if (STR_EQUAL(type_name, "quadmesh-rect"))
1269         tag = DB_QUAD_RECT;
1270 
1271     else if (STR_EQUAL(type_name, "quadmesh-curv"))
1272         tag = DB_QUAD_CURV;
1273 
1274     else if (STR_EQUAL(type_name, "csgmesh"))
1275         tag = DB_CSGMESH;
1276 
1277     else if (STR_EQUAL(type_name, "csgvar"))
1278         tag = DB_CSGVAR;
1279 
1280     else if (STR_EQUAL(type_name, "defvars"))
1281         tag = DB_DEFVARS;
1282 
1283     else if (STR_EQUAL(type_name, "quadmesh"))
1284         tag = DB_QUADMESH;
1285 
1286     else if (STR_EQUAL(type_name, "quadvar"))
1287         tag = DB_QUADVAR;
1288 
1289     else if (STR_EQUAL(type_name, "ucdmesh"))
1290         tag = DB_UCDMESH;
1291 
1292     else if (STR_EQUAL(type_name, "ucdvar"))
1293         tag = DB_UCDVAR;
1294 
1295     else if (STR_EQUAL(type_name, "pointmesh"))
1296         tag = DB_POINTMESH;
1297 
1298     else if (STR_EQUAL(type_name, "pointvar"))
1299         tag = DB_POINTVAR;
1300 
1301     else if (STR_EQUAL(type_name, "curve"))
1302         tag = DB_CURVE;
1303 
1304     else if (STR_EQUAL(type_name, "material"))
1305         tag = DB_MATERIAL;
1306 
1307     else if (STR_EQUAL(type_name, "matspecies"))
1308         tag = DB_MATSPECIES;
1309 
1310     else if (STR_EQUAL(type_name, "compoundarray"))
1311         tag = DB_ARRAY;
1312 
1313     else if (STR_EQUAL(type_name, "facelist"))
1314         tag = DB_FACELIST;
1315 
1316     else if (STR_EQUAL(type_name, "zonelist"))
1317         tag = DB_ZONELIST;
1318 
1319     else if (STR_EQUAL(type_name, "polyhedral-zonelist"))
1320         tag = DB_PHZONELIST;
1321 
1322     else if (STR_EQUAL(type_name, "csgzonelist"))
1323         tag = DB_CSGZONELIST;
1324 
1325     else if (STR_EQUAL(type_name, "edgelist"))
1326         tag = DB_EDGELIST;
1327 
1328     else if (STR_EQUAL(type_name, "mrgtree"))
1329         tag = DB_MRGTREE;
1330 
1331     else if (STR_EQUAL(type_name, "groupelmap"))
1332         tag = DB_GROUPELMAP;
1333 
1334     else if (STR_EQUAL(type_name, "mrgvar"))
1335         tag = DB_MRGVAR;
1336 
1337     else
1338         tag = DB_USERDEF;
1339 
1340     return (tag);
1341 }
1342 
1343 /*----------------------------------------------------------------------
1344  *  Routine                                             DBGetObjtypeName
1345  *
1346  *  Purpose
1347  *
1348  *      Return the name associated with an object of the given type.
1349  *
1350  *  Programmer
1351  *
1352  *      Jeffery W. Long, NSSD-B
1353  *
1354  *  Parameters
1355  *
1356  *      type         {In}    {Type of object to inquire about}
1357  *
1358  *  Notes
1359  *
1360  *      The calling routine should NOT attempt to free the memory
1361  *      associated with the returned string.
1362  *
1363  *  Modifications
1364  *    Al Leibee, Tue Jul 26 08:44:01 PDT 1994
1365  *    Replaced composition by matspecies.
1366  *
1367  *    Robb Matzke, Fri Oct 21 15:23:18 EST 1994
1368  *    Added DB_ARRAY for Compound Array type.
1369  *
1370  *    Eric Brugger, Tue Feb  7 11:05:39 PST 1995
1371  *    I modified the routine to return "unknown" if the type is
1372  *    DB_USERDEF.
1373  *
1374  *    Katherine Price, Thu May 25 10:00:50 PDT 1995
1375  *    Added DB_MULTIMAT for Multi-Block Material type.
1376  *
1377  *    Jeremy Meredith, Sept 18 1998
1378  *    Added DB_MULTIMATSPECIES for Multi-block Species.
1379  *--------------------------------------------------------------------*/
1380 INTERNAL char *
DBGetObjtypeName(int type)1381 DBGetObjtypeName(int type)
1382 {
1383     char          *me = "DBGetObjtypeName";
1384 
1385     switch (type) {
1386         case DB_CSGMESH:
1387             return ("csgmesh");
1388         case DB_CSGVAR:
1389             return ("csgvar");
1390         case DB_CSGZONELIST:
1391             return ("csgzonelist");
1392         case DB_DEFVARS:
1393             return ("defvars");
1394         case DB_QUADMESH:
1395             return ("quadmesh");
1396         case DB_QUAD_RECT:
1397             return ("quadmesh-rect");
1398         case DB_QUAD_CURV:
1399             return ("quadmesh-curv");
1400         case DB_QUADVAR:
1401             return ("quadvar");
1402         case DB_UCDMESH:
1403             return ("ucdmesh");
1404         case DB_UCDVAR:
1405             return ("ucdvar");
1406         case DB_POINTMESH:
1407             return ("pointmesh");
1408         case DB_POINTVAR:
1409             return ("pointvar");
1410         case DB_MULTIMESH:
1411             return ("multiblockmesh");
1412         case DB_MULTIMESHADJ:
1413             return ("multimeshadj");
1414         case DB_MULTIVAR:
1415             return ("multiblockvar");
1416         case DB_MULTIMAT:
1417             return ("multiblockmat");
1418         case DB_MULTIMATSPECIES:
1419             return ("multimatspecies");
1420         case DB_MATERIAL:
1421             return ("material");
1422         case DB_MATSPECIES:
1423             return ("matspecies");
1424         case DB_FACELIST:
1425             return ("facelist");
1426         case DB_ZONELIST:
1427             return ("zonelist");
1428         case DB_PHZONELIST:
1429             return ("polyhedral-zonelist");
1430         case DB_EDGELIST:
1431             return ("edgelist");
1432         case DB_CURVE:
1433             return ("curve");
1434         case DB_ARRAY:
1435             return ("compoundarray");
1436         case DB_MRGTREE:
1437             return ("mrgtree");
1438         case DB_GROUPELMAP:
1439             return ("groupelmap");
1440         case DB_MRGVAR:
1441             return ("mrgvar");
1442         case DB_USERDEF:
1443             return ("unknown");
1444     }
1445 
1446     db_perror("type-number", E_BADARGS, me);
1447     return ("unknown");
1448 }
1449 
1450 /*-------------------------------------------------------------------------
1451  * Function:    db_ListDir2
1452  *
1453  * Purpose:     Lists the contents of the given directories based on the
1454  *              listing options set in the `args' array.  Directory path
1455  *              arguments can be either absolute or relative.  The standard
1456  *              Unix directory syntax is understood: `..' is shorthand for
1457  *              the parent of te current directory and `.' is shorthand
1458  *              for the current directory.
1459  *
1460  * Return:      Success:        0
1461  *
1462  *              Failure:        -1
1463  *
1464  * Arguments:
1465  *      args          Argument array
1466  *      nargs         Number of arguments
1467  *      build_list    Sentinel: 1:build list instead of printing
1468  *      list          List of varnames matching request
1469  *      nlist         Returned length of list
1470  *
1471  * Programmer:  robb@cloud
1472  *              Tue Nov 15 15:07:26 EST 1994
1473  *
1474  * Modifications:
1475  *    Eric Brugger, Thu Feb  9 14:43:50 PST 1995
1476  *    I modified the routine to handle the obj in the table of contents.
1477  *
1478  *    Jeremy Meredith, Sept 18 1998
1479  *    Added multimatspecies to the toc
1480  *-------------------------------------------------------------------------*/
1481 INTERNAL int
db_ListDir2(DBfile * _dbfile,char * args[],int nargs,int build_list,char * list[],int * nlist)1482 db_ListDir2(DBfile *_dbfile, char *args[], int nargs, int build_list,
1483             char *list[], int *nlist)
1484 {
1485     int            i, k, npaths, nopts;
1486     int            ls_mesh, ls_var, ls_dir;
1487     int            ls_multimesh, ls_multivar, ls_multimat, ls_curve, ls_mat;
1488     int            ls_matspecies, ls_multimatspecies, ls_low, ls_array;
1489     char           opts[256], cwd[256], orig_dir[256], *paths[64];
1490     DBtoc         *toc = NULL;
1491     int            left_margin, col_margin, line_width;
1492     char          *me = "db_ListDir2";
1493 
1494      /*----------------------------------------
1495       *  Parse input options and pathnames.
1496       *----------------------------------------*/
1497 
1498     if (!list || !nlist) return -1;
1499 
1500     npaths = 0;
1501     nopts = 0;
1502 
1503     for (i = 0; i < nargs; i++) {
1504 
1505         switch (args[i][0]) {
1506             case '-':
1507 
1508                 strcpy(&opts[nopts], &args[i][1]);
1509                 nopts += strlen(args[i]) - 1;
1510                 break;
1511 
1512             default:
1513 
1514                 paths[npaths++] = args[i];
1515                 break;
1516         }
1517     }
1518 
1519      /*----------------------------------------
1520       *  Set listing options based on input.
1521       *----------------------------------------*/
1522     if (nopts > 0) {
1523         ls_mesh = ls_var = ls_dir = FALSE;
1524         ls_curve = ls_mat = ls_matspecies = ls_low = ls_array = FALSE;
1525         ls_multimat = ls_multimatspecies = FALSE;
1526     }
1527     else {
1528         /* Default values */
1529         ls_mesh = ls_var = ls_dir = ls_multimesh = ls_multivar = TRUE;
1530         ls_curve = ls_mat = ls_matspecies = ls_low = ls_array = FALSE;
1531         ls_multimat = ls_multimatspecies = FALSE;
1532     }
1533 
1534     for (i = 0; i < nopts; i++) {
1535 
1536         switch (opts[i]) {
1537             case 'a':
1538                 ls_curve = TRUE;
1539                 ls_dir = TRUE;
1540                 ls_low = TRUE;
1541                 ls_mat = TRUE;
1542                 ls_matspecies = TRUE;
1543                 ls_mesh = TRUE;
1544                 ls_var = TRUE;
1545                 ls_multimesh = TRUE;
1546                 ls_multivar = TRUE;
1547                 ls_multimat = TRUE;
1548                 ls_multimatspecies = TRUE;
1549                 ls_array = TRUE;
1550                 break;
1551             case 'A':
1552                 ls_array = TRUE;
1553                 break;
1554             case 'c':
1555                 ls_curve = TRUE;
1556                 break;
1557             case 'd':
1558                 ls_dir = TRUE;
1559                 break;
1560             case 'm':
1561                 ls_mesh = TRUE;
1562                 break;
1563             case 'M':
1564                 ls_multimesh = TRUE;
1565                 ls_multivar = TRUE;
1566                 ls_multimat  = TRUE;
1567                 ls_multimatspecies = TRUE;
1568                 break;
1569             case 'r':
1570                 ls_mat = TRUE;
1571                 break;
1572             case 's':
1573                 ls_matspecies = TRUE;
1574                 break;
1575             case 'v':
1576                 ls_var = TRUE;
1577                 break;
1578             case 'x':
1579                 ls_low = TRUE;
1580                 break;
1581             default:
1582                 return db_perror("invalid list option", E_BADARGS, me);
1583         }
1584     }
1585 
1586      /*----------------------------------------
1587       *  List all requested objects/dirs
1588       *----------------------------------------*/
1589 
1590     DBGetDir(_dbfile, orig_dir);
1591 
1592     if (npaths <= 0) {
1593         npaths = 1;
1594         paths[0] = ".";
1595     }
1596 
1597     left_margin = 10;
1598     col_margin = 5;
1599     line_width = 80;
1600 
1601     if (nlist)
1602         *nlist = 0;
1603 
1604     for (k = 0; k < npaths; k++) {
1605 
1606         DBGetDir(_dbfile, cwd);
1607 
1608         /* Change to requested directory, if necessary */
1609         if (!STR_EQUAL(".", paths[k]) &&
1610             !STR_EQUAL(cwd, paths[k]))
1611             DBSetDir(_dbfile, paths[k]);
1612 
1613         toc = DBGetToc(_dbfile);
1614         if (!toc)
1615             return db_perror("unable to get toc", E_INTERNAL, me);
1616 
1617         if (ls_curve && toc->ncurve > 0) {
1618             if (build_list) {
1619                 for (i = 0; i < toc->ncurve; i++) {
1620                     list[*nlist] = ALLOC_N(char,
1621                                strlen         (toc->curve_names[i]) + 1);
1622 
1623                     strcpy(list[(*nlist)++], toc->curve_names[i]);
1624                 }
1625             }
1626             else {
1627                 printf("%7d curves:\n", toc->ncurve);
1628                 _DBstrprint(stdout, toc->curve_names, toc->ncurve,
1629                             'c', left_margin, col_margin, line_width);
1630                 printf("\n");
1631             }
1632         }
1633 
1634         if (ls_low && toc->nvar > 0) {
1635             if (build_list) {
1636                 for (i = 0; i < toc->nvar; i++) {
1637                     list[*nlist] = ALLOC_N(char,
1638                                  strlen         (toc->var_names[i]) + 1);
1639 
1640                     strcpy(list[(*nlist)++], toc->var_names[i]);
1641                 }
1642             }
1643             else {
1644                 printf("%7d miscellaneous vars:\n", toc->nvar);
1645                 _DBstrprint(stdout, toc->var_names, toc->nvar,
1646                             'c', left_margin, col_margin, line_width);
1647                 printf("\n");
1648             }
1649         }
1650 
1651         if (ls_mat && toc->nmat > 0) {
1652             if (build_list) {
1653                 for (i = 0; i < toc->nmat; i++) {
1654                     list[*nlist] = ALLOC_N(char,
1655                                  strlen         (toc->mat_names[i]) + 1);
1656 
1657                     strcpy(list[(*nlist)++], toc->mat_names[i]);
1658                 }
1659             }
1660             else {
1661                 printf("%7d material vars:\n", toc->nmat);
1662                 _DBstrprint(stdout, toc->mat_names, toc->nmat,
1663                             'c', left_margin, col_margin, line_width);
1664                 printf("\n");
1665             }
1666         }
1667 
1668         if (ls_matspecies && toc->nmatspecies > 0) {
1669             if (build_list) {
1670                 for (i = 0; i < toc->nmatspecies; i++) {
1671                     list[*nlist] = ALLOC_N(char,
1672                           strlen         (toc->matspecies_names[i]) + 1);
1673 
1674                     strcpy(list[(*nlist)++], toc->matspecies_names[i]);
1675                 }
1676             }
1677             else {
1678                 printf("%7d material species vars:\n", toc->nmatspecies);
1679                 _DBstrprint(stdout, toc->matspecies_names,
1680                             toc->nmatspecies,
1681                             'c', left_margin, col_margin, line_width);
1682                 printf("\n");
1683             }
1684         }
1685 
1686         if (ls_array && toc->narray > 0) {
1687             if (build_list) {
1688                 for (i = 0; i < toc->narray; i++) {
1689                     list[*nlist] = ALLOC_N(char,
1690                                strlen         (toc->array_names[i]) + 1);
1691 
1692                     strcpy(list[(*nlist)++], toc->array_names[i]);
1693                 }
1694             }
1695             else {
1696                 printf("%7d compound arrays:\n", toc->narray);
1697                 _DBstrprint(stdout, toc->array_names, toc->narray,
1698                             'c', left_margin, col_margin, line_width);
1699                 printf("\n");
1700             }
1701         }
1702 
1703         if (ls_dir && toc->ndir > 0) {
1704             if (build_list) {
1705                 for (i = 0; i < toc->ndir; i++) {
1706                     list[*nlist] = ALLOC_N(char,
1707                                  strlen         (toc->dir_names[i]) + 1);
1708 
1709                     strcpy(list[(*nlist)++], toc->dir_names[i]);
1710                 }
1711             }
1712             else {
1713                 printf("%7d directories:\n", toc->ndir);
1714                 _DBstrprint(stdout, toc->dir_names, toc->ndir,
1715                             'c', left_margin, col_margin, line_width);
1716                 printf("\n");
1717             }
1718         }
1719 
1720         if (ls_multimesh && toc->nmultimesh > 0) {
1721             if (build_list) {
1722                 for (i = 0; i < toc->nmultimesh; i++) {
1723                     list[*nlist] = ALLOC_N(char,
1724                            strlen         (toc->multimesh_names[i]) + 1);
1725 
1726                     strcpy(list[(*nlist)++], toc->multimesh_names[i]);
1727                 }
1728             }
1729             else {
1730                 printf("%7d multi-block meshes:\n", toc->nmultimesh);
1731                 _DBstrprint(stdout, toc->multimesh_names, toc->nmultimesh,
1732                             'c', left_margin, col_margin, line_width);
1733                 printf("\n");
1734             }
1735         }
1736 
1737         if (ls_mesh && toc->nqmesh > 0) {
1738             if (build_list) {
1739                 for (i = 0; i < toc->nqmesh; i++) {
1740                     list[*nlist] = ALLOC_N(char,
1741                                strlen         (toc->qmesh_names[i]) + 1);
1742 
1743                     strcpy(list[(*nlist)++], toc->qmesh_names[i]);
1744                 }
1745             }
1746             else {
1747                 printf("%7d quad meshes:\n", toc->nqmesh);
1748                 _DBstrprint(stdout, toc->qmesh_names, toc->nqmesh,
1749                             'c', left_margin, col_margin, line_width);
1750                 printf("\n");
1751             }
1752         }
1753         if (ls_mesh && toc->nucdmesh > 0) {
1754             if (build_list) {
1755                 for (i = 0; i < toc->nucdmesh; i++) {
1756                     list[*nlist] = ALLOC_N(char,
1757                              strlen         (toc->ucdmesh_names[i]) + 1);
1758 
1759                     strcpy(list[(*nlist)++], toc->ucdmesh_names[i]);
1760                 }
1761             }
1762             else {
1763                 printf("%7d UCD meshes:\n", toc->nucdmesh);
1764                 _DBstrprint(stdout, toc->ucdmesh_names, toc->nucdmesh,
1765                             'c', left_margin, col_margin, line_width);
1766                 printf("\n");
1767             }
1768         }
1769         if (ls_mesh && toc->nptmesh > 0) {
1770             if (build_list) {
1771                 for (i = 0; i < toc->nptmesh; i++) {
1772                     list[*nlist] = ALLOC_N(char,
1773                               strlen         (toc->ptmesh_names[i]) + 1);
1774 
1775                     strcpy(list[(*nlist)++], toc->ptmesh_names[i]);
1776                 }
1777             }
1778             else {
1779                 printf("%7d Point meshes:\n", toc->nptmesh);
1780                 _DBstrprint(stdout, toc->ptmesh_names, toc->nptmesh,
1781                             'c', left_margin, col_margin, line_width);
1782                 printf("\n");
1783             }
1784         }
1785 
1786         if (ls_multivar && toc->nmultivar > 0) {
1787             if (build_list) {
1788                 for (i = 0; i < toc->nmultivar; i++) {
1789                     list[*nlist] = ALLOC_N(char,
1790                             strlen         (toc->multivar_names[i]) + 1);
1791 
1792                     strcpy(list[(*nlist)++], toc->multivar_names[i]);
1793                 }
1794             }
1795             else {
1796                 printf("%7d multi-block vars:\n", toc->nmultivar);
1797                 _DBstrprint(stdout, toc->multivar_names, toc->nmultivar,
1798                             'c', left_margin, col_margin, line_width);
1799                 printf("\n");
1800             }
1801         }
1802 
1803         if (ls_multimat  && toc->nmultimat > 0) {
1804             if (build_list) {
1805                 for (i = 0; i < toc->nmultimat; i++) {
1806                     list[*nlist] = ALLOC_N (char,
1807                        strlen (toc->multimat_names[i]) + 1);
1808                     strcpy (list[(*nlist)++], toc->multimat_names[i]);
1809                 }
1810             }
1811             else {
1812                 printf("%7d multi-block materials:\n", toc->nmultimat);
1813                 _DBstrprint (stdout, toc->multimat_names, toc->nmultimat,
1814                              'c', left_margin, col_margin, line_width);
1815                 printf("\n");
1816             }
1817         }
1818 
1819         if (ls_multimatspecies  && toc->nmultimatspecies > 0) {
1820             if (build_list) {
1821                 for (i = 0; i < toc->nmultimatspecies; i++) {
1822                     list[*nlist] = ALLOC_N (char,
1823                        strlen (toc->multimatspecies_names[i]) + 1);
1824                     strcpy (list[(*nlist)++], toc->multimatspecies_names[i]);
1825                 }
1826             }
1827             else {
1828                 printf("%7d multi-block material species:\n", toc->nmultimatspecies);
1829                 _DBstrprint (stdout, toc->multimatspecies_names,
1830                              toc->nmultimatspecies,
1831                              'c', left_margin, col_margin, line_width);
1832                 printf("\n");
1833             }
1834         }
1835 
1836         if (ls_var && toc->nqvar > 0) {
1837             if (build_list) {
1838                 for (i = 0; i < toc->nqvar; i++) {
1839                     list[*nlist] = ALLOC_N(char,
1840                                 strlen         (toc->qvar_names[i]) + 1);
1841 
1842                     strcpy(list[(*nlist)++], toc->qvar_names[i]);
1843                 }
1844             }
1845             else {
1846                 printf("%7d quad vars:\n", toc->nqvar);
1847                 _DBstrprint(stdout, toc->qvar_names, toc->nqvar,
1848                             'c', left_margin, col_margin, line_width);
1849                 printf("\n");
1850             }
1851         }
1852         if (ls_var && toc->nucdvar > 0) {
1853             if (build_list) {
1854                 for (i = 0; i < toc->nucdvar; i++) {
1855                     list[*nlist] = ALLOC_N(char,
1856                               strlen         (toc->ucdvar_names[i]) + 1);
1857 
1858                     strcpy(list[(*nlist)++], toc->ucdvar_names[i]);
1859                 }
1860             }
1861             else {
1862                 printf("%7d UCD vars:\n", toc->nucdvar);
1863                 _DBstrprint(stdout, toc->ucdvar_names, toc->nucdvar,
1864                             'c', left_margin, col_margin, line_width);
1865                 printf("\n");
1866             }
1867         }
1868         if (ls_var && toc->nptvar > 0) {
1869             if (build_list) {
1870                 for (i = 0; i < toc->nptvar; i++) {
1871                     list[*nlist] = ALLOC_N(char,
1872                                strlen         (toc->ptvar_names[i]) + 1);
1873 
1874                     strcpy(list[(*nlist)++], toc->ptvar_names[i]);
1875                 }
1876             }
1877             else {
1878                 printf("%7d Point vars:\n", toc->nptvar);
1879                 _DBstrprint(stdout, toc->ptvar_names, toc->nptvar,
1880                             'c', left_margin, col_margin, line_width);
1881                 printf("\n");
1882             }
1883         }
1884         if (ls_var && toc->nobj > 0) {
1885             if (build_list) {
1886                 for (i = 0; i < toc->nobj; i++) {
1887                     list[*nlist] = ALLOC_N(char,
1888                                  strlen         (toc->obj_names[i]) + 1);
1889 
1890                     strcpy(list[(*nlist)++], toc->obj_names[i]);
1891                 }
1892             }
1893             else {
1894                 printf("%7d miscellaneous objects:\n", toc->nobj);
1895                 _DBstrprint(stdout, toc->obj_names, toc->nobj,
1896                             'c', left_margin, col_margin, line_width);
1897                 printf("\n");
1898             }
1899         }
1900 
1901         /*
1902          * Return to original directory, since next path may
1903          * be relative to it.
1904          */
1905         DBSetDir(_dbfile, orig_dir);
1906 
1907     }
1908 
1909     return 0;
1910 }
1911 
1912 /*-------------------------------------------------------------------------
1913  * Function:    context_switch
1914  *
1915  * Purpose:     Many of the DB...() functions take an object name as a
1916  *              parameter.  The old protocol didn't specify whether the
1917  *              name could include a path, so some drivers allow one and
1918  *              other don't.  To fix the problem, each of the API functions
1919  *              that allow a name will call this routine to change to
1920  *              the specified directory and will call context_restore()
1921  *              to change back.
1922  *
1923  * Bugs:        This function doesn't protect calls to the other API
1924  *              directory setting/retrieving functions and thus might
1925  *              leak memory if one of those calls fail with a non-local
1926  *              return.
1927  *
1928  * Return:      Success:        ptr to the previous context.  This ptr
1929  *                              should be passed to context_restore().
1930  *
1931  *              Failure:        NULL, db_perror called.
1932  *
1933  * Arguments:
1934  *      base         output parameter
1935  *
1936  * Programmer:  matzke@viper
1937  *              Sun Jan 29 11:42:47 PST 1995
1938  *
1939  * Modifications:
1940  *-------------------------------------------------------------------------*/
1941 INTERNAL context_t *
context_switch(DBfile * dbfile,char const * name,char const ** base)1942 context_switch(DBfile *dbfile, char const *name, char const **base)
1943 {
1944     char          const *me = "context_switch";
1945     char          s[256], *b;
1946     context_t     *old = ALLOC(context_t);
1947 
1948     /*
1949      * Save the old information.  If the name doesn't contain a `/' then
1950      * we don't have to do anything.  We will mark this case by storing
1951      * NULL as the context name.
1952      */
1953     *base = name;
1954     if (!strchr(name, '/')) {
1955         old->dirid = 0;
1956         old->name = NULL;
1957         return old;
1958     }
1959     if (DBGetDir(dbfile, s) < 0) {
1960         FREE(old);
1961         return NULL;
1962     }
1963     old->dirid = dbfile->pub.dirid;
1964     old->name = STRDUP(s);
1965 
1966     /*
1967      * Split the name into a path and a base name.  The base name
1968      * is the stuff after the last `/'.  If the base name is empty
1969      * then we should raise an E_NOTFOUND right away.
1970      */
1971     b = (char *)strrchr(name, '/');
1972     if (!b || !b[1]) {
1973         FREE(old->name);
1974         FREE(old);
1975         db_perror(name, E_NOTFOUND, me);
1976         return NULL;
1977     }
1978     *base = b + 1;
1979     if (b == name) {
1980         /*
1981          * This is the root directory.
1982          */
1983         if (DBSetDir(dbfile, "/") < 0) {
1984             FREE(old->name);
1985             FREE(old);
1986             return NULL;
1987         }
1988     }
1989     else {
1990         /*
1991          * The path is everything before (not including) the last
1992          * `/'.  We would like to just change that slash to a null
1993          * terminator temporarily, but the name might be a static
1994          * string in a read-only data section, so we have to do it
1995          * the long way.  We assume (like the rest of SILO and most
1996          * drivers) that the name will not be longer than 255
1997          * characters.
1998          */
1999         strncpy(s, name, b - name);
2000         s[b - name] = '\0';
2001         if (DBSetDir(dbfile, s) < 0) {
2002             FREE(old->name);
2003             FREE(old);
2004             return NULL;
2005         }
2006     }
2007 
2008     return old;
2009 }
2010 
2011 /*-------------------------------------------------------------------------
2012  * Function:    context_restore
2013  *
2014  * Purpose:     Restore a previously saved context.  If the driver can
2015  *              change directories based on a directory ID, we do that.
2016  *              Otherwise, we change directories based on the old directory
2017  *              name.
2018  *
2019  * Return:      Success:        0
2020  *
2021  *              Failure:        -1, db_perror called.
2022  *
2023  * Programmer:  matzke@viper
2024  *              Sun Jan 29 12:01:21 PST 1995
2025  *
2026  * Modifications:
2027  *-------------------------------------------------------------------------*/
2028 INTERNAL int
context_restore(DBfile * dbfile,context_t * old)2029 context_restore(DBfile *dbfile, context_t *old)
2030 {
2031     if (!dbfile || !old)
2032         return 0;
2033     if (!old->name) {
2034         FREE(old);
2035         return 0;
2036     }
2037 
2038     DBSetDir(dbfile, old->name);
2039 
2040     FREE(old->name);
2041     FREE(old);
2042     return 0;
2043 }
2044 
2045 /*-------------------------------------------------------------------------
2046  * Function:    db_get_fileid
2047  *
2048  * Purpose:     Obtain a file ID number which is unique with respect to
2049  *              all other open files.
2050  *
2051  * Return:      Success:        ID number, [0..DB_NFILES-1]
2052  *
2053  *              Failure:        -1, too many files are open.
2054  *
2055  * Programmer:  robb@cloud
2056  *              Tue Feb 28 11:00:04 EST 1995
2057  *
2058  * Modifications:
2059  *-------------------------------------------------------------------------*/
2060 PRIVATE int
db_get_fileid(int flags)2061 db_get_fileid ( int flags )
2062 {
2063     static int     vhand = 0;
2064     int            i;
2065 
2066     for (i = 0; i < DB_NFILES; i++) {
2067         if (!_db_fstatus[(vhand + i) % DB_NFILES]) {
2068             i = (vhand + i) % DB_NFILES;
2069             _db_fstatus[i] = flags | DB_ISOPEN;
2070             vhand = (i + 1) % DB_NFILES;
2071             return i;
2072         }
2073     }
2074     return -1;
2075 }
2076 
2077 /*-------------------------------------------------------------------------
2078   Function: bjhash
2079 
2080   Purpose: Hash a variable length stream of bytes into a 32-bit value.
2081 
2082   Programmer: By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.
2083 
2084   You may use this code any way you wish, private, educational, or
2085   commercial.  It's free. However, do NOT use for cryptographic purposes.
2086 
2087   See http://burtleburtle.net/bob/hash/evahash.html
2088  *-------------------------------------------------------------------------*/
2089 
2090 #define bjhash_mix(a,b,c) \
2091 { \
2092   a -= b; a -= c; a ^= (c>>13); \
2093   b -= c; b -= a; b ^= (a<<8); \
2094   c -= a; c -= b; c ^= (b>>13); \
2095   a -= b; a -= c; a ^= (c>>12);  \
2096   b -= c; b -= a; b ^= (a<<16); \
2097   c -= a; c -= b; c ^= (b>>5); \
2098   a -= b; a -= c; a ^= (c>>3);  \
2099   b -= c; b -= a; b ^= (a<<10); \
2100   c -= a; c -= b; c ^= (b>>15); \
2101 }
2102 
bjhash(register const unsigned char * k,register unsigned int length,register unsigned int initval)2103 static unsigned int bjhash(register const unsigned char *k, register unsigned int length, register unsigned int initval)
2104 {
2105    register unsigned int a,b,c,len;
2106 
2107    len = length;
2108    a = b = 0x9e3779b9;
2109    c = initval;
2110 
2111    while (len >= 12)
2112    {
2113       a += (k[0] +((unsigned int)k[1]<<8) +((unsigned int)k[2]<<16) +((unsigned int)k[3]<<24));
2114       b += (k[4] +((unsigned int)k[5]<<8) +((unsigned int)k[6]<<16) +((unsigned int)k[7]<<24));
2115       c += (k[8] +((unsigned int)k[9]<<8) +((unsigned int)k[10]<<16)+((unsigned int)k[11]<<24));
2116       bjhash_mix(a,b,c);
2117       k += 12; len -= 12;
2118    }
2119 
2120    c += length;
2121 
2122    switch(len)
2123    {
2124       case 11: c+=((unsigned int)k[10]<<24);
2125       case 10: c+=((unsigned int)k[9]<<16);
2126       case 9 : c+=((unsigned int)k[8]<<8);
2127       case 8 : b+=((unsigned int)k[7]<<24);
2128       case 7 : b+=((unsigned int)k[6]<<16);
2129       case 6 : b+=((unsigned int)k[5]<<8);
2130       case 5 : b+=k[4];
2131       case 4 : a+=((unsigned int)k[3]<<24);
2132       case 3 : a+=((unsigned int)k[2]<<16);
2133       case 2 : a+=((unsigned int)k[1]<<8);
2134       case 1 : a+=k[0];
2135    }
2136 
2137    bjhash_mix(a,b,c);
2138 
2139    return c;
2140 }
2141 
2142 
2143 /*-------------------------------------------------------------------------
2144  * Functions:   db_register_file, db_unregister_file, db_isregistered_file
2145  *
2146  * Purpose:     Maintain list of files returned by DBCreate/DBOpen as well
2147  *              as closed by DBClose in order to detect possible operation
2148  *              on closed files.
2149  *
2150  * Return:      -1 if file limit exceeded. Otherwise [0..DB_NFILES-1]
2151  *              representing position in fixed size list.
2152  *
2153  * Programmer:  Mark C. Miller, Wed Jul 23 00:14:00 PDT 2008
2154  *
2155  * Modifications:
2156  *   Mark C. Miller, Wed Feb 25 23:46:44 PST 2009
2157  *   Replaced name of file which can be very different but still represent
2158  *   the same file stat structure. We wind up using st_dev/st_ino members
2159  *   of stat struct to identify a file. In fact, we use a bjhash of those
2160  *   members. This is not foolproof. Non posix filesystems can apparently
2161  *   result in st_dev/st_ino combinations which are the same but for
2162  *   different files.
2163  *
2164  *   Mark C. Miller, Fri Feb 12 08:20:03 PST 2010
2165  *   Replaced conditional compilation with SIZEOF_OFF64T with
2166  *   db_silo_stat_struct.
2167  *
2168  *   Mark C. Miller, Wed May 19 17:07:05 PDT 2010
2169  *   Added logic for _WIN32 form of the db_silo_stat_struct.
2170  *-------------------------------------------------------------------------*/
2171 PRIVATE int
db_register_file(DBfile * dbfile,const db_silo_stat_t * filestate,int writeable)2172 db_register_file(DBfile *dbfile, const db_silo_stat_t *filestate, int writeable)
2173 {
2174     int i;
2175     for (i = 0; i < DB_NFILES; i++)
2176     {
2177         if (_db_regstatus[i].f == 0)
2178         {
2179             unsigned int hval = 0;
2180 #ifndef _WIN32
2181             hval = bjhash((unsigned char *) &(filestate->s.st_dev), sizeof(filestate->s.st_dev), hval);
2182             hval = bjhash((unsigned char *) &(filestate->s.st_ino), sizeof(filestate->s.st_ino), hval);
2183 #else
2184             hval = bjhash((unsigned char *) &(filestate->fileindexlo), sizeof(filestate->fileindexlo), hval);
2185             hval = bjhash((unsigned char *) &(filestate->fileindexhi), sizeof(filestate->fileindexhi), hval);
2186 #endif
2187             _db_regstatus[i].f = dbfile;
2188             _db_regstatus[i].n = hval;
2189             _db_regstatus[i].w = writeable;
2190             return i;
2191         }
2192     }
2193     return -1;
2194 }
2195 
2196 PRIVATE int
db_unregister_file(DBfile * dbfile)2197 db_unregister_file(DBfile *dbfile)
2198 {
2199     int i;
2200     for (i = 0; i < DB_NFILES; i++)
2201     {
2202         if (_db_regstatus[i].f == dbfile)
2203         {
2204             int j;
2205             _db_regstatus[i].f = 0;
2206             for (j = i; (j < DB_NFILES-1) && (_db_regstatus[j+1].f != 0); j++)
2207             {
2208                 _db_regstatus[j].f = _db_regstatus[j+1].f;
2209                 _db_regstatus[j].n = _db_regstatus[j+1].n;
2210                 _db_regstatus[j].w = _db_regstatus[j+1].w;
2211             }
2212             _db_regstatus[j].f = 0;
2213             return i;
2214         }
2215     }
2216     return -1;
2217 }
2218 
2219 PRIVATE int
db_isregistered_file(DBfile * dbfile,const db_silo_stat_t * filestate)2220 db_isregistered_file(DBfile *dbfile, const db_silo_stat_t *filestate)
2221 {
2222     int i;
2223     if (dbfile)
2224     {
2225         for (i = 0; i < DB_NFILES; i++)
2226         {
2227             if (_db_regstatus[i].f == dbfile)
2228                 return i;
2229         }
2230     }
2231     else if (filestate)
2232     {
2233         unsigned int hval = 0;
2234 #ifndef _WIN32
2235         hval = bjhash((unsigned char *) &(filestate->s.st_dev), sizeof(filestate->s.st_dev), hval);
2236         hval = bjhash((unsigned char *) &(filestate->s.st_ino), sizeof(filestate->s.st_ino), hval);
2237 #else
2238         hval = bjhash((unsigned char *) &(filestate->fileindexlo), sizeof(filestate->fileindexlo), hval);
2239         hval = bjhash((unsigned char *) &(filestate->fileindexhi), sizeof(filestate->fileindexhi), hval);
2240 #endif
2241         for (i = 0; i < DB_NFILES; i++)
2242         {
2243             if (_db_regstatus[i].f != 0 &&
2244                 _db_regstatus[i].n == hval)
2245                 return i;
2246         }
2247     }
2248     return -1;
2249 }
2250 
2251 INTERNAL int
db_num_registered_files()2252 db_num_registered_files()
2253 {
2254     int i;
2255     int cnt = 0;
2256     for (i = 0; i < DB_NFILES; i++)
2257     {
2258         if (_db_regstatus[i].f) cnt++;
2259     }
2260     return cnt;
2261 }
2262 
2263 /*-------------------------------------------------------------------------
2264  * Function:   db_silo_stat_one_file
2265  *
2266  * Purpose:    Better stat method for silo taking into account stat/stat64
2267  *             as well as windows-specific notion of an 'inode'.
2268  *
2269  * Programmer: Mark C. Miller
2270  *
2271  * Modifications:
2272  *   Adjusted the windows-specific logic to obtain fileindex information so
2273  *   that if that work fails, it still returns stat retval and errno of stat.
2274  *-------------------------------------------------------------------------*/
2275 PRIVATE int
db_silo_stat_one_file(const char * name,db_silo_stat_t * statbuf)2276 db_silo_stat_one_file(const char *name, db_silo_stat_t *statbuf)
2277 {
2278     int retval;
2279     errno = 0;
2280     memset(&(statbuf->s), 0, sizeof(statbuf->s));
2281 
2282     retval = stat(name, &(statbuf->s));
2283 
2284 #ifdef _WIN32
2285     if (retval == 0)
2286     {
2287         /* this logic was copied by and large from HDF5 sec2 VFD */
2288         int errnotmp = errno;
2289         int fd = open(name, O_RDONLY);
2290         if (fd != -1)
2291         {
2292             struct _BY_HANDLE_FILE_INFORMATION fileinfo;
2293             GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &fileinfo);
2294             statbuf->fileindexhi = fileinfo.nFileIndexHigh;
2295             statbuf->fileindexlo = fileinfo.nFileIndexLow;
2296             close(fd);
2297         }
2298         errno = errnotmp;
2299     }
2300 #endif /* #ifdef _WIN32 */
2301 
2302     return retval;
2303 }
2304 
2305 /*-------------------------------------------------------------------------
2306  * Function:   db_silo_stat
2307  *
2308  * Purpose:    Better stat method for silo taking into account stat/stat64
2309  *             as well as issues with filenames used for split vfds.
2310  *
2311  * Programmer: Mark C. Miller, Fri Feb 12 08:21:52 PST 2010
2312  *-------------------------------------------------------------------------*/
2313 PRIVATE int
db_silo_stat(const char * name,db_silo_stat_t * statbuf,int opts_set_id)2314 db_silo_stat(const char *name, db_silo_stat_t *statbuf, int opts_set_id)
2315 {
2316     int retval = db_silo_stat_one_file(name, statbuf);
2317 
2318     /* check for case where we're opening a buffer as a file */
2319     if (opts_set_id > DB_FILE_OPTS_LAST)
2320     {
2321         const DBoptlist *opts = SILO_Globals.fileOptionsSets[opts_set_id-NUM_DEFAULT_FILE_OPTIONS_SETS];
2322         void *p; int vfd = -1;
2323         if ((p = DBGetOption(opts, DBOPT_H5_VFD)))
2324             vfd = *((int*)p);
2325         if (vfd == DB_H5VFD_FIC)
2326         {
2327             statbuf->s.st_mode = 0x0;
2328             statbuf->s.st_mode |= S_IREAD;
2329             return 0;
2330         }
2331     }
2332 
2333     if (opts_set_id == -1 ||
2334         opts_set_id == DB_FILE_OPTS_H5_DEFAULT_SPLIT ||
2335         opts_set_id > DB_FILE_OPTS_LAST)
2336     {
2337         int i;
2338         int imin = opts_set_id == -1 ? 0 : opts_set_id;
2339         int imax = opts_set_id == -1 ? MAX_FILE_OPTIONS_SETS: opts_set_id;
2340         int tmperrno = errno;
2341 
2342         for (i = imin; i < imax; i++)
2343         {
2344             db_silo_stat_t tmpstatbuf;
2345             static char tmpname[4096];
2346             char *meta_ext="", *raw_ext="-raw";
2347             void *p; int vfd = -1;
2348             const DBoptlist *opts;
2349 
2350             if (opts_set_id == -1)
2351                 opts = SILO_Globals.fileOptionsSets[i];
2352             else if (opts_set_id == DB_FILE_OPTS_H5_DEFAULT_SPLIT)
2353                 opts = 0;
2354             else
2355                 opts = SILO_Globals.fileOptionsSets[i-NUM_DEFAULT_FILE_OPTIONS_SETS];
2356 
2357             /* ignore if options set id does not yield a valid options set */
2358             if (opts)
2359             {
2360                 /* ignore if options set unrelated to split vfds */
2361                 if ((p = DBGetOption(opts, DBOPT_H5_VFD)))
2362                     vfd = *((int*)p);
2363 
2364                 if (vfd != DB_H5VFD_SPLIT)
2365                     continue;
2366 
2367                 /* ok, get meta/raw filenaming extension conventions */
2368                 if ((p = DBGetOption(opts, DBOPT_H5_META_EXTENSION)))
2369                     meta_ext = (char *) p;
2370                 if ((p = DBGetOption(opts, DBOPT_H5_RAW_EXTENSION)))
2371                     raw_ext = (char *) p;
2372             }
2373 
2374             /* try the raw file name, first */
2375             if (strstr(raw_ext,"%s"))
2376                 sprintf(tmpname, raw_ext, name);
2377             else
2378                 sprintf(tmpname, "%s%s", name, raw_ext);
2379             errno = 0;
2380             if (db_silo_stat_one_file(tmpname, &tmpstatbuf) != 0 || errno != 0)
2381                 continue;
2382 
2383             /* try the meta file last and return its statbuf */
2384             if (strstr(meta_ext,"%s"))
2385                 sprintf(tmpname, meta_ext, name);
2386             else
2387                 sprintf(tmpname, "%s%s", name, meta_ext);
2388             memset(&tmpstatbuf, 0, sizeof(tmpstatbuf));
2389             if (db_silo_stat_one_file(tmpname, &tmpstatbuf) == 0 && errno == 0)
2390             {
2391                 memcpy(statbuf, &tmpstatbuf, sizeof(tmpstatbuf));
2392                 return 0;
2393             }
2394         }
2395 
2396         errno = tmperrno;
2397     }
2398 
2399     return retval;
2400 }
2401 
2402 /*-------------------------------------------------------------------------
2403  * Function:    db_filter_install
2404  *
2405  * Purpose:     Install the database-requested filters, calling the filter
2406  *              `open' routine for each named filter and reporting errors
2407  *              for filters that can't be found.  Filters are requested
2408  *              through the `_filters' character variable which is
2409  *              optional.  This variable should contain a list of filter
2410  *              names separated by `;' (extra `;' may appear at the beginning
2411  *              or end of the string).  The first filter in the list is
2412  *              the one that will be installed closest to the device
2413  *              driver while the last filter is installed closest to the
2414  *              API.
2415  *
2416  * Return:      Success:        0
2417  *
2418  *              Failure:        -1
2419  *
2420  * Programmer:  robb@cloud
2421  *              Tue Feb 28 11:58:01 EST 1995
2422  *
2423  * Modifications:
2424  *    Eric Brugger, Fri Mar  7 15:26:29 PST 1997
2425  *    I modified the routine to copy the filter name string to a scratch
2426  *    so array so that a NULL character could be added without overwriting
2427  *    the last character in the string.
2428  *-------------------------------------------------------------------------*/
2429 PRIVATE int
db_filter_install(DBfile * dbfile)2430 db_filter_install ( DBfile *dbfile )
2431 {
2432     char          *me = "db_filter_install";
2433     int            len, i;
2434     char          *var, *var2, *s, *filter_name;
2435     static char    not_found[128];
2436 
2437     /*
2438      * There should be a miscellaneous variable called `_filters' in
2439      * the current (root) directory.  If not, then no filters are
2440      * requested.
2441      */
2442     if (!DBInqVarExists(dbfile,"_filters"))
2443         return(0);
2444 
2445     /*
2446      * Read the `_filters' variable and make sure it is a character
2447      * string.
2448      */
2449     if (DB_CHAR != DBGetVarType(dbfile, "_filters")) {
2450         db_perror("`_filters' is not a character variable",
2451                   E_NOTFILTER, me);
2452         return -1;
2453     }
2454     len = DBGetVarLength(dbfile, "_filters");
2455     if (len <= 0)
2456         return 0;               /*no filters requested */
2457     if (NULL == (var = (char*)DBGetVar(dbfile, "_filters")))
2458         return -1;
2459 
2460     /*
2461      * Copy the variable and add a terminating NULL character.
2462      */
2463     var2 = ALLOC_N (char, len+1);
2464     strncpy (var2, var, len);
2465     var2[len] = '\0';
2466 
2467     /*
2468      * Process each filter.  Names are separated from one another
2469      * by semicolons which may also appear at the beginning and end
2470      * of the string.  Be careful for things like `;;'.
2471      */
2472     not_found[0] = '\0';
2473     s = var2;
2474     while ((filter_name = strtok(s, ";\n\r"))) {
2475         s = NULL;
2476         if (!filter_name[0])
2477             continue;
2478 
2479         for (i = 0; i < DB_NFILTERS; i++) {
2480             if (_db_filter[i].name &&
2481                 !strcmp(_db_filter[i].name, filter_name)) {
2482                 break;
2483             }
2484         }
2485 
2486         /*
2487          * If the filter isn't found, tack the name onto the end
2488          * of a list of names that weren't found, being careful
2489          * not to overflow that buffer.  Each name should be
2490          * separated from the others by a semicolon as in the `_filters'
2491          * database variable.
2492          */
2493         if (i >= DB_NFILTERS) {
2494             int q = 0;
2495             len = strlen(not_found);
2496             if (len && len + 1 < sizeof(not_found)) {
2497                 strcat(not_found, ";");
2498                 len++;
2499             }
2500             while (len + 1 < sizeof(not_found))
2501                 not_found[len++] = filter_name[q++];
2502             not_found[len] = '\0';
2503             continue;
2504         }
2505 
2506         /*
2507          * If the filter has an `open' routine, call it now.
2508          */
2509         if (_db_filter[i].open) {
2510             (void)(_db_filter[i].open) (dbfile, _db_filter[i].name);
2511         }
2512     }
2513 
2514     FREE (var2);
2515 
2516     /*
2517      * If we failed to find some filters, we should notify the user.
2518      * Should we return success or failure???  For now, we return
2519      * success so that failure to find a filter is a warning at
2520      * this level but an error if db_perror calls longjmp().  This
2521      * gives the application a little control.
2522      */
2523     if (not_found[0]) {
2524         db_perror(not_found, E_NOTFILTER, me);
2525     }
2526     return 0;
2527 }
2528 
2529 /*-------------------------------------------------------------------------
2530  * Function:    DBFilterRegistration
2531  *
2532  * Purpose:     Manipulate the global filter table by adding, changing,
2533  *              or removing a filter.  `Name' specifies the filter that
2534  *              will be affected.  `Init' and `open' are filter functions
2535  *              that will be called when a database is opened.  `Init' is
2536  *              called for every database that is opend (just after opening;
2537  *              filters called in arbitrary order).  `Open' is called for
2538  *              each file which requests that filter.
2539  *
2540  * Return:      Success:        0
2541  *
2542  *              Failure:        -1, table is full
2543  *
2544  * Programmer:  robb@cloud
2545  *              Tue Feb 28 11:26:07 EST 1995
2546  *
2547  * Modifications:
2548  *-------------------------------------------------------------------------*/
2549 PUBLIC int
DBFilterRegistration(const char * name,int (* init)(DBfile *,char *),int (* open)(DBfile *,char *))2550 DBFilterRegistration(const char *name, int(*init)(DBfile*, char*),
2551                      int(*open)(DBfile*, char*))
2552 {
2553     int            i, j = -1;
2554 
2555     API_BEGIN("DBFilterRegistration", int, -1) {
2556 
2557         /*
2558          * Look for entry already in the table.  If found, simply change
2559          * the callbacks.
2560          */
2561         for (i = 0; i < DB_NFILTERS; i++) {
2562             if (_db_filter[i].name && !strcmp(_db_filter[i].name, name)) {
2563                 break;
2564             }
2565             if (j < 0 && !_db_filter[i].name)
2566                 j = i;
2567         }
2568         if (i < DB_NFILTERS) {
2569             if (!init && !open) {
2570                 FREE(_db_filter[i].name);
2571                 _db_filter[i].name = NULL;
2572             }
2573             else {
2574                 _db_filter[i].init = init;
2575                 _db_filter[i].open = open;
2576             }
2577             API_RETURN(0);
2578         }
2579 
2580         /*
2581          * This is a new filter definition.  Add it to the first free
2582          * slot.
2583          */
2584         if (init || open) {
2585             if (j < 0)
2586                 API_ERROR((char *)name, E_MAXFILTERS);
2587             _db_filter[j].name = STRDUP(name);
2588             _db_filter[j].init = init;
2589             _db_filter[j].open = open;
2590         }
2591         API_RETURN(0);
2592     }
2593     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
2594 }
2595 
2596 /*-------------------------------------------------------------------------
2597  * Function:    DBUninstall
2598  *
2599  * Purpose:     Uninstalls the top-most filter if any.  This is similar
2600  *              to closing the file except the uninstall is not propogated
2601  *              down the filter stack.
2602  *
2603  *              If the `uninstall' callback is null, this routine
2604  *              doesn't do anything and then returns success.  This
2605  *              allows device drivers to omit the uninstall function.
2606  *
2607  * Return:      Success:        0
2608  *
2609  *              Failure:        -1
2610  *
2611  * Programmer:  robb@cloud
2612  *              Thu Mar 16 10:29:36 EST 1995
2613  *
2614  * Modifications:
2615  *-------------------------------------------------------------------------*/
2616 int
DBUninstall(DBfile * dbfile)2617 DBUninstall(DBfile *dbfile)
2618 {
2619     int retval;
2620 
2621     API_BEGIN("DBUninstall", int, -1) {
2622         if (!dbfile)
2623             API_ERROR(NULL, E_NOFILE);
2624         if (!dbfile->pub.uninstall)
2625         {
2626             API_RETURN(0);
2627         }
2628 
2629         retval = (dbfile->pub.uninstall) (dbfile);
2630         API_RETURN(retval);
2631     }
2632     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
2633 }
2634 
2635 /*----------------------------------------------------------------------
2636  * Routine:  DBSetDataReadMask2
2637  *
2638  * Purpose:  Set and return the data read mask
2639  *
2640  * Programmer:  Sean Ahern, Fri Jan 26 17:28:06 PST 2001
2641  *
2642  * Description:  This routine sets the data read mask.  It returns the
2643  *               previous data read mask.  The data read mask is used to
2644  *               tailor how the various driver functions read their data.
2645  *               All of them are required to populate the metadata in the
2646  *               returned structures.  Ordinarily, they also read all of
2647  *               the "real" data.  If they honor the data read flag (see
2648  *               DBDataReadFlagHonored()), the user can set, by way of this
2649  *               function, the mask of "real" data to read.  This allows
2650  *               the user to decide not to read in the zonelist array of a
2651  *               UCD mesh, for instance, if he knows that it will not be
2652  *               useful to him (i.e. constant connectivity over a
2653  *               time-varying dataset.)
2654  *
2655  * Note: Many of these DBSet/Get routines DO NOT include the standard
2656  * API_BEGIN/API_END macros. This is primarily due to the fact that
2657  * these calls CANNOT fail. For others, that can fail, we do indeed
2658  * use the API_BEGIN/API_END macros as per instructions in
2659  * silo_private.h
2660  *
2661  * Modifications:
2662  *--------------------------------------------------------------------*/
2663 PUBLIC unsigned long long
DBSetDataReadMask2(unsigned long long mask)2664 DBSetDataReadMask2(unsigned long long mask)
2665 {
2666     unsigned long long oldmask = SILO_Globals.dataReadMask;
2667     SILO_Globals.dataReadMask = mask;
2668     return oldmask;
2669 }
2670 
2671 /*----------------------------------------------------------------------
2672  * Routine:  DBGetDataReadMask2
2673  *
2674  * Purpose:  Return the current data read mask
2675  *
2676  * Programmer:  Sean Ahern, Thu Mar  1 12:02:48 PST 2001
2677  *
2678  * Description:  This routine returns the current data read mask.
2679  *               The data read mask is used to tailor how the various
2680  *               driver functions read their data.
2681  *
2682  * Modifications:
2683  *--------------------------------------------------------------------*/
2684 PUBLIC unsigned long long
DBGetDataReadMask2(void)2685 DBGetDataReadMask2(void)
2686 {
2687     return SILO_Globals.dataReadMask;
2688 }
2689 
2690 /*----------------------------------------------------------------------
2691  * Routine:  DBSetAllowOverwrites
2692  *
2693  * Purpose:  Set and return the allow overwrites flags
2694  *
2695  * Programmer:  Mark C. Miller, August 23, 3005
2696  *
2697  * Description:  This routine sets the flag that controls whether
2698  *               overwrites are allowed.
2699  *--------------------------------------------------------------------*/
2700 PUBLIC int
DBSetAllowOverwrites(int allow)2701 DBSetAllowOverwrites(int allow)
2702 {
2703     int oldAllow = SILO_Globals.allowOverwrites;
2704     SILO_Globals.allowOverwrites = allow;
2705     return oldAllow;
2706 }
2707 
2708 PUBLIC int
DBGetAllowOverwrites()2709 DBGetAllowOverwrites()
2710 {
2711     return SILO_Globals.allowOverwrites;
2712 }
2713 
2714 /*----------------------------------------------------------------------
2715  * Routine:  DBSetAllowEmptyObjects
2716  *
2717  * Purpose:  Set and return the allow empty objects flags
2718  *
2719  * Programmer:  Mark C. Miller, January 9, 2013
2720  *
2721  * Description:  This routine sets the flag that controls whether
2722  *               empty objects are allowed. By default, they are not.
2723  *--------------------------------------------------------------------*/
2724 PUBLIC int
DBSetAllowEmptyObjects(int allow)2725 DBSetAllowEmptyObjects(int allow)
2726 {
2727     int oldAllow = SILO_Globals.allowEmptyObjects;
2728     SILO_Globals.allowEmptyObjects = allow;
2729     return oldAllow;
2730 }
2731 
2732 PUBLIC int
DBGetAllowEmptyObjects()2733 DBGetAllowEmptyObjects()
2734 {
2735     return SILO_Globals.allowEmptyObjects;
2736 }
2737 
2738 /*----------------------------------------------------------------------
2739  * Routine:  DBSetEnableChecksums
2740  *
2741  * Purpose:  Set and return the enable checksums flags
2742  *
2743  * Programmer:  Mark C. Miller, May 1, 2006
2744  *
2745  * Description:  This routine sets the flag that controls whether
2746  *               checksums are computed on client data.
2747  *--------------------------------------------------------------------*/
2748 PUBLIC int
DBSetEnableChecksums(int enable)2749 DBSetEnableChecksums(int enable)
2750 {
2751     int oldEnable = SILO_Globals.enableChecksums;
2752     SILO_Globals.enableChecksums = enable;
2753     return oldEnable;
2754 }
2755 
2756 PUBLIC int
DBGetEnableChecksums()2757 DBGetEnableChecksums()
2758 {
2759     return SILO_Globals.enableChecksums;
2760 }
2761 
2762 /*----------------------------------------------------------------------
2763  * Routine:  DBSetCompression
2764  *
2765  * Purpose:  Set and return the enable Compression flags
2766  *
2767  * Programmer:  Thomas R. Treadway, Wed Feb 28 11:36:34 PST 2007
2768  *
2769  * Description:  This routine enters the compression method information.
2770  *--------------------------------------------------------------------*/
2771 PUBLIC void
DBSetCompression(const char * s)2772 DBSetCompression(const char *s)
2773 {
2774     if (s && *s == '\0') {
2775         if (SILO_Globals.compressionParams)
2776             FREE(SILO_Globals.compressionParams);
2777         SILO_Globals.compressionParams = ALLOC_N(char, 12);
2778         strcpy(SILO_Globals.compressionParams, "METHOD=GZIP");
2779     }
2780     else if (s) {
2781         if (SILO_Globals.compressionParams)
2782             FREE(SILO_Globals.compressionParams);
2783         SILO_Globals.compressionParams=ALLOC_N(char,strlen(s)+1);
2784         strcpy(SILO_Globals.compressionParams, s);
2785     }
2786     else {
2787         if (SILO_Globals.compressionParams)
2788             FREE(SILO_Globals.compressionParams);
2789         SILO_Globals.compressionParams=0;
2790     }
2791 }
2792 
2793 PUBLIC char const *
DBGetCompression()2794 DBGetCompression()
2795 {
2796     return SILO_Globals.compressionParams;
2797 }
2798 
2799 PUBLIC int
DBFreeCompressionResources(DBfile * dbfile,const char * meshname)2800 DBFreeCompressionResources(DBfile *dbfile, const char *meshname)
2801 {
2802     int retval = 0;
2803 
2804     API_BEGIN2("DBFreeCompressionResources", int, -1, api_dummy) {
2805 
2806         if (!dbfile->pub.free_z)
2807             API_ERROR(dbfile->pub.name, E_NOTIMP);
2808         retval = ((dbfile->pub.free_z) (dbfile, meshname));
2809 
2810         API_RETURN(retval);
2811     }
2812     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
2813 }
2814 
2815 
2816 /*----------------------------------------------------------------------
2817  * Routine:  DBSetFriendlyHDF5Names
2818  *
2819  * Purpose:  Set flag to create friendly HDF5 dataset names
2820  *
2821  * Programmer:  Mark C. Miller, Thu Apr 19 15:17:05 PDT 2007
2822  *
2823  * Description:  Sets flag for HDF5 driver to control production of
2824  * friendly dataset names. Returns value of old setting.
2825  *--------------------------------------------------------------------*/
2826 PUBLIC int
DBSetFriendlyHDF5Names(int enable)2827 DBSetFriendlyHDF5Names(int enable)
2828 {
2829     int oldEnable = SILO_Globals.enableFriendlyHDF5Names;
2830     SILO_Globals.enableFriendlyHDF5Names = enable;
2831     return oldEnable;
2832 }
2833 
2834 PUBLIC int
DBGetFriendlyHDF5Names()2835 DBGetFriendlyHDF5Names()
2836 {
2837     return SILO_Globals.enableFriendlyHDF5Names;
2838 }
2839 
2840 #define CHECK_FOR_FRIENDLY(ON,SU)					\
2841     ntotal += toc->n ## ON;						\
2842     for (i = 0; i < toc->n ## ON; i++)					\
2843     {									\
2844         char tmp[1024];							\
2845         snprintf(tmp, sizeof(tmp), "%s_%s", toc->ON ## _names[i], SU);	\
2846         if (DBInqVarExists(f, tmp))					\
2847             nfriendly++;						\
2848     }
2849 
2850 /*----------------------------------------------------------------------
2851  * Routine:  db_guess_has_friendly_HDF5_names_r
2852  *
2853  * Purpose:  Recursive helper func for DBGuessHasFriendlyHDF5Names
2854  *           names.
2855  *
2856  * Programmer: Mark C. Miller, Wed Sep  2 15:27:06 PDT 2009
2857  *
2858  *--------------------------------------------------------------------*/
2859 PRIVATE int
db_guess_has_friendly_HDF5_names_r(DBfile * f)2860 db_guess_has_friendly_HDF5_names_r(DBfile *f)
2861 {
2862     int i, ntotal = 0, nfriendly = 0;
2863     int retval;
2864     DBtoc *toc;
2865 
2866     toc = DBGetToc(f);
2867 
2868     if (!toc) return 0;
2869 
2870     CHECK_FOR_FRIENDLY(multimesh, "meshnames");
2871     CHECK_FOR_FRIENDLY(multivar, "varnames");
2872     CHECK_FOR_FRIENDLY(multimat, "matnames");
2873     CHECK_FOR_FRIENDLY(qmesh, "coord0");
2874     CHECK_FOR_FRIENDLY(qvar, "data");
2875     CHECK_FOR_FRIENDLY(ucdmesh, "coord0");
2876     CHECK_FOR_FRIENDLY(ucdvar, "data");
2877     CHECK_FOR_FRIENDLY(ptmesh, "coord0");
2878     CHECK_FOR_FRIENDLY(ptvar, "data");
2879     CHECK_FOR_FRIENDLY(csgmesh, "_coeffs");
2880     CHECK_FOR_FRIENDLY(csgvar, "data");
2881     CHECK_FOR_FRIENDLY(mat, "_matlist");
2882     CHECK_FOR_FRIENDLY(matspecies, "_speclist");
2883     CHECK_FOR_FRIENDLY(curve, "_yvals");
2884     CHECK_FOR_FRIENDLY(obj, "_nodelist");
2885 
2886     if (ntotal >= 3) /* arb. min of 3 objects */
2887     {
2888         if (nfriendly >= ntotal/2)
2889             return 1;
2890         else
2891             return 0;
2892     }
2893 
2894     retval = -1;
2895     for (i = 0; i < toc->ndir && retval == -1; i++)
2896     {
2897         DBSetDir(f, toc->dir_names[i]);
2898         retval = db_guess_has_friendly_HDF5_names_r(f);
2899         DBSetDir(f, "..");
2900     }
2901 
2902     return retval;
2903 }
2904 
2905 /*----------------------------------------------------------------------
2906  * Routine:  DBGuessHasFriendlyHDF5Names
2907  *
2908  * Purpose:  Determine if it looks like a given file has HDF5 friendly
2909  *           names.
2910  *
2911  * Programmer: Mark C. Miller, Wed Sep  2 15:27:06 PDT 2009
2912  *
2913  *--------------------------------------------------------------------*/
2914 PUBLIC int
DBGuessHasFriendlyHDF5Names(DBfile * f)2915 DBGuessHasFriendlyHDF5Names(DBfile *f)
2916 {
2917     char cwd[1024];
2918     int retval;
2919 
2920     if (DBGetDriverType(f) != 7 /* DB_HDF5X */)
2921         return 0;
2922 
2923     DBGetDir(f, cwd);
2924     retval = db_guess_has_friendly_HDF5_names_r(f);
2925     DBSetDir(f, cwd);
2926 
2927     return retval;
2928 }
2929 
2930 /*----------------------------------------------------------------------
2931  * Routine:  DBSetDeprecateWarnings
2932  *
2933  * Purpose:  Set number of deprecate warnings Silo should print.
2934  *           Default is 3. Setting to zero effectively disables.
2935  *
2936  * Programmer:  Mark C. Miller, Thu Oct 11 16:50:12 PDT 2007
2937  *
2938  *--------------------------------------------------------------------*/
2939 PUBLIC int
DBSetDeprecateWarnings(int count)2940 DBSetDeprecateWarnings(int count)
2941 {
2942     int oldCount = SILO_Globals.maxDeprecateWarnings;
2943     SILO_Globals.maxDeprecateWarnings = count;
2944     return oldCount;
2945 }
2946 
2947 PUBLIC int
DBGetDeprecateWarnings()2948 DBGetDeprecateWarnings()
2949 {
2950     return SILO_Globals.maxDeprecateWarnings;
2951 }
2952 
2953 /*----------------------------------------------------------------------
2954  * Routine:  DBSetUnknownDriverPriority
2955  *
2956  * Purpose:  Set priority order of drivers used by unknown driver.
2957  *
2958  * Programmer:  Mark C. Miller, May 1, 2006
2959  *
2960  * Description:  This routine sets the flag that controls whether
2961  *               checksums are computed on client data.
2962  *--------------------------------------------------------------------*/
2963 PUBLIC int const *
DBSetUnknownDriverPriorities(const int * priorities)2964 DBSetUnknownDriverPriorities(const int *priorities)
2965 {
2966     int i = 0;
2967     static int oldPriorities[MAX_FILE_OPTIONS_SETS+DB_NFORMATS+1];
2968     memcpy(oldPriorities, SILO_Globals.unknownDriverPriorities, sizeof(oldPriorities));
2969     while (i < (MAX_FILE_OPTIONS_SETS+DB_NFORMATS+1) && priorities[i] >= 0)
2970     {
2971         SILO_Globals.unknownDriverPriorities[i] = priorities[i];
2972         i++;
2973     }
2974     if (i < (MAX_FILE_OPTIONS_SETS+DB_NFORMATS+1))
2975         SILO_Globals.unknownDriverPriorities[i] = -1;
2976     return oldPriorities;
2977 }
2978 
2979 PUBLIC int const *
DBGetUnknownDriverPriorities()2980 DBGetUnknownDriverPriorities()
2981 {
2982     static int priorities[MAX_FILE_OPTIONS_SETS+DB_NFORMATS+1];
2983     memcpy(priorities, SILO_Globals.unknownDriverPriorities, sizeof(priorities));
2984     return priorities;
2985 }
2986 
2987 PUBLIC int
DBRegisterFileOptionsSet(const DBoptlist * opts)2988 DBRegisterFileOptionsSet(const DBoptlist *opts)
2989 {
2990     int i;
2991 
2992     API_BEGIN("DBRegisterFileOptionsSet", int, -1) {
2993         for (i = 0; i < MAX_FILE_OPTIONS_SETS; i++)
2994         {
2995             if (SILO_Globals.fileOptionsSets[i] == 0)
2996             {
2997                 SILO_Globals.fileOptionsSets[i] = opts;
2998                 API_RETURN(i+NUM_DEFAULT_FILE_OPTIONS_SETS);
2999             }
3000         }
3001         API_ERROR("Silo library", E_MAXFILEOPTSETS);
3002     }
3003     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
3004 }
3005 
3006 PUBLIC int
DBUnregisterFileOptionsSet(int opts_set_id)3007 DBUnregisterFileOptionsSet(int opts_set_id)
3008 {
3009     int _opts_set_id = opts_set_id-NUM_DEFAULT_FILE_OPTIONS_SETS;
3010 
3011     API_BEGIN("DBUnregisterFileOptionsSet", int, -1) {
3012         if (SILO_Globals.fileOptionsSets[_opts_set_id] == 0)
3013             API_ERROR("opts_set_id", E_BADARGS);
3014         SILO_Globals.fileOptionsSets[_opts_set_id] = 0;
3015         API_RETURN(0);
3016     }
3017     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
3018 }
3019 
3020 PUBLIC void
DBUnregisterAllFileOptionsSets()3021 DBUnregisterAllFileOptionsSets()
3022 {
3023     int i;
3024 
3025     for (i = 0; i < MAX_FILE_OPTIONS_SETS; i++)
3026         SILO_Globals.fileOptionsSets[i] = 0;
3027 }
3028 
db_get_used_file_options_sets_ids()3029 const int* db_get_used_file_options_sets_ids()
3030 {
3031     int i,n;
3032     static int used_slots[MAX_FILE_OPTIONS_SETS+NUM_DEFAULT_FILE_OPTIONS_SETS+1];
3033 
3034 
3035     /* For the default cases, only return those that 'matter' in that
3036        they could possibly have an impact on Silo's ability to actually
3037        open the file. In addtion, put them in some kind of priority order */
3038     n = 0;
3039     used_slots[n++] = DB_FILE_OPTS_H5_DEFAULT_SILO;
3040     used_slots[n++] = DB_FILE_OPTS_H5_DEFAULT_SPLIT;
3041     used_slots[n++] = DB_FILE_OPTS_H5_DEFAULT_DIRECT;
3042     used_slots[n++] = DB_FILE_OPTS_H5_DEFAULT_FAMILY;
3043     used_slots[n++] = DB_FILE_OPTS_H5_DEFAULT_MPIO;
3044     used_slots[n++] = DB_FILE_OPTS_H5_DEFAULT_MPIP;
3045     for (i = n; i < MAX_FILE_OPTIONS_SETS+NUM_DEFAULT_FILE_OPTIONS_SETS+1; i++)
3046         used_slots[i] = -1;
3047 
3048     /* fill in with used options set slots */
3049     for (i = 0; i < MAX_FILE_OPTIONS_SETS; i++)
3050     {
3051         if (SILO_Globals.fileOptionsSets[i]==0)
3052             continue;
3053         used_slots[n++] = i+NUM_DEFAULT_FILE_OPTIONS_SETS;
3054     }
3055 
3056     return used_slots;
3057 }
3058 
3059 /*----------------------------------------------------------------------
3060  * Routine:  DBGrabDriver
3061  *
3062  * Purpose:  Set and return the low level driver file handle
3063  *
3064  * Programmer:  Thomas R. Treadway, Tue May 29 15:52:19 PDT 2007
3065  *
3066  * Description:  This routine returns a ponter to the driver-native
3067  * file handle.
3068  *
3069  * Modifications
3070  *   Mark C. Miller, Thu Oct 11 15:36:10 PDT 2007
3071  *   Record fact file was grabbed by adding var at top-level
3072  *--------------------------------------------------------------------*/
3073 PUBLIC void *
DBGrabDriver(DBfile * file)3074 DBGrabDriver(DBfile *file)
3075 {
3076     void *rtn = 0;
3077     if (file) {
3078        if (file->pub.GrabId > (void *) 0) {
3079           int grab_val = 1;
3080           DBWrite(file, "/_was_grabbed", &grab_val, &grab_val, 1, DB_INT);
3081           SILO_Globals.enableGrabDriver = TRUE;
3082           rtn = (void *) file->pub.GrabId;
3083        }
3084     }
3085     return rtn;
3086 }
3087 /*----------------------------------------------------------------------
3088  * Routine:  DBGetDriverType
3089  *
3090  * Purpose:  Return the drive type
3091  *
3092  * Programmer:  Thomas R. Treadway, Thu Jun  7 13:19:48 PDT 2007
3093  *
3094  * Description:  This routine returns a the driver type
3095  *--------------------------------------------------------------------*/
3096 PUBLIC int
DBGetDriverType(const DBfile * file)3097 DBGetDriverType(const DBfile *file)
3098 {
3099     if (file) {
3100        return file->pub.type;
3101     }
3102     return DB_UNKNOWN;
3103 }
3104 
3105 /*----------------------------------------------------------------------
3106  * Routine:  DBGetDriverTypeFromPath
3107  *
3108  * Purpose:  Return the drive type
3109  *
3110  * Programmer:  Thomas R. Treadway, Tue Jul  3 15:24:58 PDT 2007
3111  *
3112  * Description:  This routine returns a the driver type
3113  *
3114  * Modifications:
3115  *
3116  * Thomas R. Treadway, Thu Jul  5 11:57:03 PDT 2007
3117  * DB_HDR5 is conditional
3118  *
3119  * Mark C. Miller, Mon Nov 19 10:45:05 PST 2007
3120  * Removed conditional compilation on HDF5 driver
3121  *
3122  * Mark C. Miller, Mon Oct 25 16:12:49 PDT 2010
3123  * Initialize buf to ensure it will be null terminated no matter
3124  * what happens during open/read.
3125  *--------------------------------------------------------------------*/
3126 PUBLIC int
DBGetDriverTypeFromPath(const char * path)3127 DBGetDriverTypeFromPath(const char *path)
3128 {
3129    char buf[9] = {'\0','\0','\0','\0','\0','\0','\0','\0','\0'};
3130    int fd;
3131    int nbytes;
3132    int flags = O_RDONLY;
3133    if ((fd = open(path, flags)) < 0) {
3134       printf("cannot open `%s'\n", path);
3135       return -1;
3136    }
3137    if ((nbytes = read(fd, (char *)buf, 8)) == -1) {
3138       printf("cannot read `%s'\n", path);
3139       close(fd);
3140       return -1;
3141    }
3142    if (nbytes <= 5) {
3143       printf("cannot read `%s' buffer too small\n", path);
3144       close(fd);
3145       return -1;
3146    }
3147    (void) close(fd);
3148    if (strstr(buf, "PDB"))
3149       return 2; /* can't use DB_PDB here */
3150    if (strstr(buf, "HDF"))
3151       return 7; /* can't use DB_HDF5X here. */
3152    return DB_UNKNOWN;
3153 }
3154 
3155 /*----------------------------------------------------------------------
3156  * Routine:  DBJoinPath
3157  *
3158  * Purpose:  Given paths with possible relative naming, combine them
3159  *           into a single absolute path.
3160  *
3161  * Programmer:  Mark C. Miller, July 20, 2008
3162  *--------------------------------------------------------------------*/
3163 PUBLIC char *
DBJoinPath(const char * first,const char * second)3164 DBJoinPath(const char *first, const char *second)
3165 {
3166     API_BEGIN("DBJoinPath", char *, NULL) {
3167         API_RETURN(db_join_path(first, second));
3168     }
3169     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
3170 }
3171 
3172 /*----------------------------------------------------------------------
3173  * Routine:  DBUngrabDriver
3174  *
3175  * Purpose:  Return control of the low level driver
3176  *
3177  * Programmer:  Thomas R. Treadway, Thu Jun  7 13:19:48 PDT 2007
3178  *
3179  * Description:  This routine returns a the driver-native type
3180  *--------------------------------------------------------------------*/
3181 PUBLIC int
DBUngrabDriver(DBfile * file,const void * driver_handle)3182 DBUngrabDriver(DBfile *file, const void *driver_handle)
3183 {
3184     if (file) {
3185        SILO_Globals.enableGrabDriver = FALSE;
3186        return file->pub.type;
3187     }
3188     return DB_UNKNOWN;
3189 }
3190 
3191 static int
db_IncObjectComponentCount(DBobject * obj)3192 db_IncObjectComponentCount(DBobject *obj)
3193 {
3194     int new_maxcomps = 0;
3195     char **new_comp_names = 0;
3196     char **new_pdb_names = 0;
3197 
3198     obj->ncomponents++;
3199     if (obj->ncomponents < obj->maxcomponents)
3200         return 1;
3201 
3202     new_maxcomps = obj->maxcomponents * 1.5 + 1; /* golden rule + 1 */
3203     new_comp_names = REALLOC_N(obj->comp_names, char *, new_maxcomps);
3204     if (!new_comp_names)
3205     {
3206         db_perror(0, E_NOMEM, "db_IncObjectComponentCount");
3207         return 0;
3208     }
3209     new_pdb_names = REALLOC_N(obj->pdb_names, char *, new_maxcomps);
3210     if (!new_pdb_names)
3211     {
3212         FREE(new_comp_names);
3213         db_perror(0, E_NOMEM, "db_IncObjectComponentCount");
3214         return 0;
3215     }
3216 
3217     obj->maxcomponents = new_maxcomps;
3218     obj->comp_names = new_comp_names;
3219     obj->pdb_names = new_pdb_names;
3220 
3221     return 1;
3222 }
3223 
3224 /*----------------------------------------------------------------------
3225  *  Routine                                                 DBMakeObject
3226  *
3227  *  Purpose
3228  *
3229  *      Allocate an object of the requested length and initialize it.
3230  *
3231  *  Programmer
3232  *
3233  *      Jeffery W. Long, NSSD-B
3234  *
3235  *  Modified
3236  *    Robb Matzke, Tue Nov 8 11:41:23 PST 1994
3237  *    Added error mechanism
3238  *
3239  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
3240  *    Added a check for variable name validity.
3241  *--------------------------------------------------------------------*/
3242 PUBLIC DBobject *
DBMakeObject(const char * name,int type,int maxcomps)3243 DBMakeObject(const char *name, int type, int maxcomps)
3244 {
3245     DBobject      *object = NULL;
3246 
3247     API_BEGIN("DBMakeObject", DBobject *, NULL) {
3248 
3249         if (!name || !*name)
3250             API_ERROR("object name", E_BADARGS);
3251         if (db_VariableNameValid(name) == 0)
3252             API_ERROR("object name", E_INVALIDNAME);
3253         if (NULL == (object = ALLOC(DBobject)))
3254             API_ERROR(NULL, E_NOMEM);
3255 
3256         if (maxcomps <= 0) maxcomps = 30;
3257         object->name = STRDUP(name);
3258         object->type = STRDUP(DBGetObjtypeName(type));
3259         object->comp_names = ALLOC_N(char *, maxcomps);
3260         object->pdb_names = ALLOC_N(char *, maxcomps);
3261 
3262         if (!object->name || !object->type ||
3263             !object->comp_names || !object->pdb_names)
3264         {
3265             FREE(object->name);
3266             FREE(object->type);
3267             FREE(object->comp_names);
3268             FREE(object->pdb_names);
3269             API_ERROR(NULL, E_NOMEM);
3270         }
3271 
3272         object->ncomponents = 0;
3273         object->maxcomponents = maxcomps;
3274 
3275         API_RETURN(object);
3276     }
3277     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
3278 }
3279 
3280 /*----------------------------------------------------------------------
3281  *  Routine                                                DBFreeObject
3282  *
3283  *  Purpose
3284  *
3285  *      Release the storage associated with the given object list.
3286  *
3287  *  Programmer
3288  *
3289  *      Jeffery W. Long, NSSD-B
3290  *
3291  *  Returns
3292  *
3293  *      Returns OKAY on success, OOPS on failure.
3294  *
3295  *  Modified
3296  *    Robb Matzke, Thu Nov 10 17:28:39 EST 1994
3297  *    Added error mechanism.
3298  *
3299  *    Robb Matzke, Fri Dec 2 13:14:18 PST 1994
3300  *    Removed all references to SCORE memory management.
3301  *
3302  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
3303  *    Made the error messages a little better.
3304  *--------------------------------------------------------------------*/
3305 PUBLIC int
DBFreeObject(DBobject * object)3306 DBFreeObject(DBobject *object)
3307 {
3308     int            i;
3309 
3310     API_BEGIN("DBFreeObject", int, -1) {
3311 
3312         if (!object)
3313             API_ERROR("object pointer", E_BADARGS);
3314         if (object->ncomponents < 0) {
3315             API_ERROR("object ncomponents", E_BADARGS);
3316         }
3317 
3318         for (i = 0; i < object->ncomponents; i++) {
3319             FREE(object->comp_names[i]);
3320             FREE(object->pdb_names[i]);
3321         }
3322         for (i = 0; i < DB_MAX_H5_OBJ_VALS; i++) {
3323             FREE(object->h5_names[i]);
3324         }
3325 
3326         FREE(object->comp_names);
3327         FREE(object->pdb_names);
3328         FREE(object->name);
3329         FREE(object->type);
3330         FREE(object);
3331     }
3332     API_END;
3333 
3334     return(0);  /* Always succeeds by the time we get here */
3335 }
3336 
3337 /*----------------------------------------------------------------------
3338  *  Routine                                                DBClearObject
3339  *
3340  *  Purpose
3341  *
3342  *      Remove all components from the given object and reset counters.
3343  *
3344  *  Programmer
3345  *
3346  *      Jeffery W. Long, NSSD-B
3347  *
3348  *  Returns
3349  *
3350  *      Returns OKAY on success, OOPS on failure.
3351  *
3352  *  Modified
3353  *    Robb Matzke, Tue Nov 8 07:46:29 PST 1994
3354  *    Added error mechanism
3355  *
3356  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
3357  *    Made the error messages a little better.
3358  *--------------------------------------------------------------------*/
3359 PUBLIC int
DBClearObject(DBobject * object)3360 DBClearObject(DBobject *object)
3361 {
3362     int            i;
3363 
3364     API_BEGIN("DBClearObject", int, -1) {
3365         if (!object)
3366             API_ERROR("object pointer", E_BADARGS);
3367         if (object->ncomponents < 0) {
3368             API_ERROR("object ncomponents", E_BADARGS);
3369         }
3370 
3371         /* Reset values, but do not free */
3372         for (i = 0; i < object->maxcomponents; i++) {
3373             object->comp_names[i] = NULL;
3374             object->pdb_names[i] = NULL;
3375         }
3376 
3377         object->name = NULL;
3378         object->type = NULL;
3379         object->ncomponents = 0;
3380     }
3381     API_END;
3382 
3383     return(0);
3384 }
3385 
3386 /*----------------------------------------------------------------------
3387  *  Routine                                            DBAddVarComponent
3388  *
3389  *  Purpose
3390  *
3391  *      Add a variable component to the given object structure.
3392  *
3393  *  Programmer
3394  *
3395  *      Jeffery W. Long, NSSD-B
3396  *
3397  *  Returns
3398  *
3399  *      Returns OKAY on success, OOPS on failure.
3400  *
3401  *  Modified
3402  *    Robb Matzke, Tue Nov 8 07:43:38 PST 1994
3403  *    Added error mechanism
3404  *
3405  *    Robb Matzke, Fri Dec 2 13:14:46 PST 1994
3406  *    Removed all references to SCORE memory management.
3407  *
3408  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
3409  *    Added a check for variable name validity.
3410  *
3411  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
3412  *    Made the error messages a little better.  Correct spelling.
3413  *--------------------------------------------------------------------*/
3414 PUBLIC int
DBAddVarComponent(DBobject * object,const char * compname,const char * pdbname)3415 DBAddVarComponent(DBobject *object, const char *compname, const char *pdbname)
3416 {
3417     API_BEGIN("DBAddVarComponent", int, -1) {
3418         if (!object)
3419             API_ERROR("object pointer", E_BADARGS);
3420         if (!compname || !*compname)
3421             API_ERROR("component name", E_BADARGS);
3422         if (db_VariableNameValid(compname) == 0)
3423             API_ERROR("component name", E_INVALIDNAME);
3424         if (!pdbname || !*pdbname)
3425             API_ERROR("pdb name", E_BADARGS);
3426         if (object->ncomponents >= object->maxcomponents) {
3427             API_ERROR("object ncomponents", E_BADARGS);
3428         }
3429 
3430         if (NULL == (object->comp_names[object->ncomponents] =
3431                      STRDUP(compname)) ||
3432             NULL == (object->pdb_names[object->ncomponents] =
3433                      STRDUP(pdbname))) {
3434             FREE(object->comp_names[object->ncomponents]);
3435             API_ERROR(NULL, E_NOMEM);
3436         }
3437 
3438         if (!db_IncObjectComponentCount(object))
3439             API_ERROR(NULL, E_NOMEM);
3440 
3441     }
3442     API_END;
3443 
3444     return(0);
3445 }
3446 
3447 /*----------------------------------------------------------------------
3448  *  Routine                                            DBAddIntComponent
3449  *
3450  *  Purpose
3451  *
3452  *      Add an integer literal component to the given object structure.
3453  *
3454  *  Programmer
3455  *
3456  *      Jeffery W. Long, NSSD-B
3457  *
3458  *  Returns
3459  *
3460  *      Returns OKAY on success, OOPS on failure.
3461  *
3462  *  Modifications
3463  *    Robb Matzke, Tue Nov 8 07:06:11 PST 1994
3464  *    Added error mechanism. Returns 0 on success, -1 on failure.
3465  *
3466  *    Robb Matzke, Fri Dec 2 13:15:06 PST 1994
3467  *    Removed all references to SCORE memory management.
3468  *
3469  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
3470  *    Added a check for variable name validity.
3471  *
3472  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
3473  *    Made the error messages a little better.
3474  *--------------------------------------------------------------------*/
3475 PUBLIC int
DBAddIntComponent(DBobject * object,const char * compname,int ii)3476 DBAddIntComponent(DBobject *object, const char *compname, int ii)
3477 {
3478     char           tmp[256];
3479 
3480     API_BEGIN("DBAddIntComponent", int, -1) {
3481         if (!object)
3482             API_ERROR("object pointer", E_BADARGS);
3483         if (!compname || !*compname)
3484             API_ERROR("component name", E_BADARGS);
3485         if (db_VariableNameValid(compname) == 0)
3486             API_ERROR("component name", E_INVALIDNAME);
3487         if (object->ncomponents >= object->maxcomponents) {
3488             API_ERROR("object ncomponents", E_BADARGS);
3489         }
3490 
3491         sprintf(tmp, "'<i>%d'", ii);
3492 
3493         if (NULL == (object->comp_names[object->ncomponents] =
3494                      STRDUP(compname)) ||
3495             NULL == (object->pdb_names[object->ncomponents] =
3496                      STRDUP(tmp))) {
3497             FREE(object->comp_names[object->ncomponents]);
3498             API_ERROR(NULL, E_NOMEM);
3499         }
3500 
3501         if (!db_IncObjectComponentCount(object))
3502             API_ERROR(NULL, E_NOMEM);
3503 
3504     }
3505     API_END;
3506 
3507     return(0);
3508 }
3509 
3510 /*----------------------------------------------------------------------
3511  *  Routine                                            DBAddFltComponent
3512  *
3513  *  Purpose
3514  *
3515  *      Add a floating point literal component to the given object
3516  *      structure.
3517  *
3518  *  Programmer
3519  *
3520  *      Jeffery W. Long, NSSD-B
3521  *
3522  *  Returns
3523  *
3524  *      Returns OKAY on success, OOPS on failure.
3525  *
3526  *  Modified:
3527  *    Robb Matzke, Tue Nov 8 07:04:15 PST 1994
3528  *    Added error mechanism.  Return -1 on failure, 0 on success.
3529  *
3530  *    Robb Matzke, Fri Dec 2 13:15:28 PST 1994
3531  *    Removed all references to SCORE memory management.
3532  *
3533  *    Eric Brugger, Tue Feb  7 09:06:58 PST 1995
3534  *    I modified the argument declarations to reflect argument promotions.
3535  *
3536  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
3537  *    Added a check for variable name validity.
3538  *
3539  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
3540  *    Made the error messages a little better.
3541  *--------------------------------------------------------------------*/
3542 PUBLIC int
DBAddFltComponent(DBobject * object,const char * compname,double ff)3543 DBAddFltComponent(DBobject *object, const char *compname, double ff)
3544 {
3545     char           tmp[256];
3546 
3547     API_BEGIN("DBAddFltComponent", int, -1) {
3548         if (!object)
3549             API_ERROR("object pointer", E_BADARGS);
3550         if (!compname || !*compname)
3551             API_ERROR("component name", E_BADARGS);
3552         if (db_VariableNameValid(compname) == 0)
3553             API_ERROR("component name", E_INVALIDNAME);
3554         if (object->ncomponents >= object->maxcomponents) {
3555             API_ERROR("object ncomponents", E_BADARGS);
3556         }
3557 
3558         sprintf(tmp, "'<f>%g'", ff);
3559 
3560         if (NULL == (object->comp_names[object->ncomponents] =
3561                      STRDUP(compname)) ||
3562             NULL == (object->pdb_names[object->ncomponents] =
3563                      STRDUP(tmp))) {
3564             FREE(object->comp_names[object->ncomponents]);
3565             API_ERROR(NULL, E_NOMEM);
3566         }
3567         if (!db_IncObjectComponentCount(object))
3568             API_ERROR(NULL, E_NOMEM);
3569     }
3570     API_END;
3571 
3572     return(0);
3573 }
3574 
3575 /*----------------------------------------------------------------------
3576  *  Routine                                            DBAddDblComponent
3577  *
3578  *  Purpose
3579  *
3580  *      Add a double precision floating point literal component to
3581  *      the given object structure.
3582  *
3583  *  Programmer
3584  *
3585  *      Brad Whitlock, Thu Jan 20 09:43:13 PDT 2000
3586  *
3587  *  Returns
3588  *
3589  *      Returns OKAY on success, OOPS on failure.
3590  *
3591  *  Modified:
3592  *
3593  *--------------------------------------------------------------------*/
3594 PUBLIC int
DBAddDblComponent(DBobject * object,const char * compname,double ff)3595 DBAddDblComponent(DBobject *object, const char *compname, double ff)
3596 {
3597     char           tmp[256];
3598 
3599     API_BEGIN("DBAddDblComponent", int, -1) {
3600         if (!object)
3601             API_ERROR("object pointer", E_BADARGS);
3602         if (!compname || !*compname)
3603             API_ERROR("component name", E_BADARGS);
3604         if (db_VariableNameValid(compname) == 0)
3605             API_ERROR("component name", E_INVALIDNAME);
3606         if (object->ncomponents >= object->maxcomponents) {
3607             API_ERROR("object ncomponents", E_BADARGS);
3608         }
3609 
3610         sprintf(tmp, "'<d>%.30g'", ff);
3611 
3612         if (NULL == (object->comp_names[object->ncomponents] =
3613                      STRDUP(compname)) ||
3614             NULL == (object->pdb_names[object->ncomponents] =
3615                      STRDUP(tmp))) {
3616             FREE(object->comp_names[object->ncomponents]);
3617             API_ERROR(NULL, E_NOMEM);
3618         }
3619         if (!db_IncObjectComponentCount(object))
3620             API_ERROR(NULL, E_NOMEM);
3621     }
3622     API_END;
3623 
3624     return(0);
3625 }
3626 
3627 /*----------------------------------------------------------------------
3628  *  Routine                                            DBAddStrComponent
3629  *
3630  *  Purpose
3631  *
3632  *      Add a string literal component to the given object structure.
3633  *
3634  *  Programmer
3635  *
3636  *      Jeffery W. Long, NSSD-B
3637  *
3638  *  Returns
3639  *
3640  *      Returns OKAY on success, OOPS on failure.
3641  *
3642  *  Modified
3643  *    Robb Matzke, Tue Nov 8 07:08:33 PST 1994
3644  *    Added error mechanism.  Return 0 on success, -1 on failure.
3645  *
3646  *    Robb Matzke, Fri Dec 2 13:15:49 PST 1994
3647  *    Removed all references to SCORE memory management.
3648  *
3649  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
3650  *    Added a check for variable name validity.
3651  *
3652  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
3653  *    Made the error messages a little better.
3654  *--------------------------------------------------------------------*/
3655 PUBLIC int
DBAddStrComponent(DBobject * object,const char * compname,const char * ss)3656 DBAddStrComponent(DBobject *object, const char *compname, const char *ss)
3657 {
3658     char           tmp[256];
3659 
3660     API_BEGIN("DBAddStrComponent", int, -1) {
3661         if (!object)
3662             API_ERROR("object pointer", E_BADARGS);
3663         if (!compname || !*compname)
3664             API_ERROR("component name", E_BADARGS);
3665         if (db_VariableNameValid(compname) == 0)
3666             API_ERROR("component name", E_INVALIDNAME);
3667         if (object->ncomponents >= object->maxcomponents) {
3668             API_ERROR("object ncomponents", E_BADARGS);
3669         }
3670         if (!ss)
3671         {
3672             if (!SILO_Globals.allowEmptyObjects)
3673                 API_ERROR("string literal component", E_BADARGS);
3674             sprintf(tmp, "'<s>null'");
3675         }
3676         else
3677             sprintf(tmp, "'<s>%s'", ss);
3678 
3679         if (NULL == (object->comp_names[object->ncomponents] =
3680                      STRDUP(compname)) ||
3681             NULL == (object->pdb_names[object->ncomponents] =
3682                      STRDUP(tmp))) {
3683             FREE(object->comp_names[object->ncomponents]);
3684             API_ERROR(NULL, E_NOMEM);
3685         }
3686         if (!db_IncObjectComponentCount(object))
3687             API_ERROR(NULL, E_NOMEM);
3688     }
3689     API_END;
3690 
3691     return(0);
3692 }
3693 
3694 /*-------------------------------------------------------------------------
3695  * Function:    DBShowErrors
3696  *
3697  * Purpose:     Set the method by which errors are displayed.  The
3698  *              `level' parameter is one of the following:
3699  *
3700  *                 DB_ALL       -- Show all errors, beginning with the
3701  *                                 routine that first detected the error
3702  *                                 and continuing up the call stack to
3703  *                                 the application.
3704  *
3705  *                 DB_ABORT     -- Same as DB_ALL except abort() is called
3706  *                                 after the error message is printed.
3707  *
3708  *                 DB_TOP       -- (default) Only the top-level API functions
3709  *                                 issue error messages.
3710  *
3711  *                 DB_NONE      -- The library does not handle error messages.
3712  *                                 The application is responsible for
3713  *                                 checking the API return values and
3714  *                                 handling the error.
3715  *
3716  *                 DB_SUSPEND   -- This is used internally to temporarily
3717  *                                 suspend the issuance of error messages
3718  *                                 by changing the error level to DB_NONE.
3719  *
3720  *                 DB_RESTORE   -- This is used internally to restore the
3721  *                                 previous error level after a DB_SUSPEND.
3722  *
3723  *              The `func' parameter can point to an application-level
3724  *              error handling function that will be passed a string that
3725  *              is part of the error message (similar to the argument for
3726  *              perror()).  If the function pointer is null, then
3727  *              the library will issue error messages to the standard
3728  *              error stream.
3729  *
3730  *              The error text and erring function name can
3731  *              be obtained by calling DBErrString() or DBErrFunc().
3732  *
3733  * Return:      void
3734  *
3735  * Programmer:  matzke@viper
3736  *              Mon Nov  7 09:58:43 PST 1994
3737  *
3738  * Modifications:
3739  *    Robb Matzke, Mon Dec 12 14:25:04 EST 1994
3740  *    Added DB_SUSPEND and DB_RESUME in order to get
3741  *    db_unk_Open to work properly [the Open callback for
3742  *    the SILO-Unknown driver].
3743  *
3744  *    Eric Brugger, Tue Feb  7 09:06:58 PST 1995
3745  *    I modified the function declaration and changed the default error
3746  *    reporting level to DB_NONE.
3747  *
3748  *    Eric Brugger, Wed Mar  1 17:07:39 PST 1995
3749  *    I shrouded the prototypes for non-ansi compilers.
3750  *
3751  *    Hank Childs, Thu Mar  2 13:34:35 PST 2000
3752  *    Add check to ensure that nested DBShowErrors to suspend error
3753  *    messages would work correctly.
3754  *
3755  *-------------------------------------------------------------------------*/
3756 PUBLIC void
DBShowErrors(int level,void (* func)(char *))3757 DBShowErrors(int level, void(*func)(char*))
3758 {
3759     static int     old_level = DB_NONE;
3760     static int     old_level_drvr = DB_NONE;
3761     static int     nested_suspend = 0;
3762 
3763     SILO_Globals._db_err_level_drvr = DB_NONE;
3764     if (level == DB_ALL_AND_DRVR)
3765     {
3766         level = DB_ALL;
3767 	SILO_Globals._db_err_level_drvr = DB_ALL;
3768     }
3769 
3770     switch (level) {
3771         case DB_SUSPEND:
3772             if (nested_suspend++ == 0)
3773             {
3774                 old_level = SILO_Globals._db_err_level;
3775                 old_level_drvr = SILO_Globals._db_err_level_drvr;
3776             }
3777             SILO_Globals._db_err_level = DB_NONE;
3778 	    SILO_Globals._db_err_level_drvr = DB_NONE;
3779             break;
3780         case DB_RESUME:
3781             if (--nested_suspend == 0)
3782             {
3783                 SILO_Globals._db_err_level = old_level;
3784 	        SILO_Globals._db_err_level_drvr = old_level_drvr;
3785             }
3786             break;
3787         default:
3788             SILO_Globals._db_err_level = level;
3789             SILO_Globals._db_err_func = func;
3790             break;
3791     }
3792 }
3793 
3794 /*-------------------------------------------------------------------------
3795  * Function:    DBErrString
3796  *
3797  * Purpose:     Return the error message of the last error.
3798  *
3799  * Return:      Success:        ptr to static error message
3800  *
3801  *              Failure:        ptr to static message for db_errno=0
3802  *
3803  * Programmer:  robb@cloud
3804  *              Tue Feb 21 08:23:48 EST 1995
3805  *
3806  * Modifications:
3807  *-------------------------------------------------------------------------*/
3808 PUBLIC char const *
DBErrString(void)3809 DBErrString(void)
3810 {
3811     static char    s[128];
3812 
3813     if (db_errno < 0 || db_errno >= NELMTS(_db_err_list)) {
3814         sprintf(s, "Error %d", db_errno);
3815         return s;
3816     }
3817 
3818     return _db_err_list[db_errno];
3819 }
3820 
3821 PUBLIC int
DBErrno(void)3822 DBErrno(void)
3823 {
3824     return db_errno;
3825 }
3826 
3827 PUBLIC char const *
DBErrFuncname(void)3828 DBErrFuncname(void)
3829 {
3830     return db_errfunc;
3831 }
3832 
3833 PUBLIC DBErrFunc_t
DBErrfunc(void)3834 DBErrfunc(void)
3835 {
3836     return SILO_Globals._db_err_func;
3837 }
3838 
3839 PUBLIC int
DBErrlvl(void)3840 DBErrlvl(void)
3841 {
3842     return SILO_Globals._db_err_level;
3843 }
3844 
3845 /*-------------------------------------------------------------------------
3846  * Function: db_parse_version_digits_from_string
3847  *
3848  * str: version string
3849  * sep: separator character (typically '.')
3850  * digits: array of digits to return
3851  * ndigits: size of digits array
3852  *
3853  * returns 0 on successful conversion, non-zero on failure
3854  *-----------------------------------------------------------------------*/
3855 static int
db_parse_version_digits_from_string(char const * str,char sep,int * digits,int ndigits)3856 db_parse_version_digits_from_string(char const *str, char sep, int *digits, int ndigits)
3857 {
3858     int i, nseps, non_digits, retval = 0;
3859     char *p, *ostr;
3860 
3861     if (!str || !*str)
3862         return 1;
3863 
3864     ostr = strdup(str);
3865     p = ostr;
3866 
3867     /* Examine string for seperator chars and non-digits */
3868     nseps = 0;
3869     non_digits = 0;
3870     while (*p)
3871     {
3872         if (*p == sep)
3873         {
3874             *p = '\0';
3875             nseps++;
3876         }
3877         else if (!strncmp(p, "-pre", 4))
3878         {
3879             *(p+0) = '\0';
3880             *(p+1) = '0';
3881             *(p+2) = '0';
3882             *(p+3) = '0';
3883             nseps++;
3884             p += 3;
3885         }
3886         else if (*p < '0' || *p > '9')
3887         {
3888             non_digits = 1;
3889         }
3890         p++;
3891     }
3892     nseps++;
3893 
3894     /* Make a second pass over string converting all the digits */
3895     if (!non_digits)
3896     {
3897         p = ostr;
3898         errno = 0;
3899         for (i = 0; i < ndigits; i++)
3900             digits[i] = 0;
3901         for (i = 0; i < nseps && ndigits && errno == 0; i++, ndigits--)
3902         {
3903             digits[i] = strtol(p, 0, 10);
3904             while (*p != '\0') p++;
3905             p++;
3906         }
3907         if (errno)
3908             retval = 1;
3909     }
3910     else
3911     {
3912         retval = 1;
3913     }
3914 
3915     free(ostr);
3916 
3917     return retval;
3918 }
3919 
3920 static int
db_compare_version_digits(int const * a_digits,int const * b_digits,int ndigits)3921 db_compare_version_digits(int const *a_digits, int const *b_digits, int ndigits)
3922 {
3923     int i;
3924     for (i = 0; i < ndigits; i++)
3925     {
3926         if (a_digits[i] < b_digits[i])
3927             return -1;
3928         else if (a_digits[i] > b_digits[i])
3929             return 1;
3930     }
3931     return 0;
3932 }
3933 
3934 /*-------------------------------------------------------------------------
3935  * Function:    DBVersion
3936  *
3937  * Purpose:     Return the version number of the library as a string.
3938  *
3939  * Returns:     ptr to version number
3940  *
3941  * Programmer:  Hank Childs
3942  *              Tue Oct 17 14:08:45 PDT 2000
3943  *
3944  * Modifications:
3945  *
3946  *   Mark C. Miller, Tue Oct 24 12:39:31 PDT 2006
3947  *   Changed to use SILO_VSTRING
3948  *-------------------------------------------------------------------------*/
3949 PUBLIC char const *
DBVersion(void)3950 DBVersion(void)
3951 {
3952     static char version[256];
3953     strcpy(version, SILO_VSTRING);
3954 
3955     return version;
3956 }
3957 
3958 PUBLIC int
DBVersionDigits(int * maj,int * min,int * pat,int * pre)3959 DBVersionDigits(int *maj, int *min, int *pat, int *pre)
3960 {
3961     int digits[4] = {0,0,0,0};
3962 
3963     if (!db_parse_version_digits_from_string(DBVersion(), '.',
3964              digits, sizeof(digits)/sizeof(digits[0])))
3965     {
3966         if (maj) *maj = digits[0];
3967         if (min) *min = digits[1];
3968         if (pat) *pat = digits[2];
3969         if (pre) *pre = digits[3];
3970         return 0;
3971     }
3972     return -1;
3973 }
3974 
3975 /*-------------------------------------------------------------------------
3976  * Function:    DBVersionGE
3977  *
3978  * Purpose:     Return whether or not the version of the library is greater
3979  *              than or equal to the version specified by Maj, Min, Pat.
3980  *              This is a run-time equiv. of the SILO_VERSION_GE macro.
3981  *
3982  * Returns:     integer indicating if true (1) or false (0)
3983  *
3984  * Programmer:  Mark C. Miller, Mon Jan 12 20:59:30 PST 2009
3985  *-------------------------------------------------------------------------*/
3986 PUBLIC int
DBVersionGE(int Maj,int Min,int Pat)3987 DBVersionGE(int Maj, int Min, int Pat)
3988 {
3989     int a_digits[3] = {SILO_VERS_MAJ, SILO_VERS_MIN, SILO_VERS_PAT};
3990     int b_digits[3] = {Maj<0?0:Maj, Min<0?0:Min, Pat<0?0:Pat};
3991     return db_compare_version_digits(a_digits, b_digits, 3) >= 0;
3992 }
3993 
3994 PUBLIC int
DBVersionGEFileVersion(const DBfile * dbfile)3995 DBVersionGEFileVersion(const DBfile *dbfile)
3996 {
3997     int a_digits[3];
3998     int b_digits[3] = {4, 5, 0}; /* earliest version we have version info in file */
3999     DBVersionDigits(&a_digits[0], &a_digits[1], &a_digits[2], 0);
4000     DBFileVersionDigits(dbfile, &b_digits[0], &b_digits[1], &b_digits[2], 0);
4001     return db_compare_version_digits(a_digits, b_digits, 3) >= 0;
4002 }
4003 
4004 /*-------------------------------------------------------------------------
4005  * Function:    DBFileVersion
4006  *
4007  * Purpose:     Return the version number of the library that created the
4008  *              given file as a string.
4009  *
4010  * Returns:     ptr to version number
4011  *
4012  * Programmer:  Mark C. Miller, Mon Jan 12 20:59:30 PST 2009
4013  *-------------------------------------------------------------------------*/
4014 PUBLIC char const *
DBFileVersion(const DBfile * dbfile)4015 DBFileVersion(const DBfile *dbfile)
4016 {
4017     static char version[256];
4018     if (dbfile->pub.file_lib_version)
4019         strcpy(version, dbfile->pub.file_lib_version);
4020     else
4021         strcpy(version, "unknown; 4.5 or older");
4022     return version;
4023 }
4024 
4025 PUBLIC int
DBFileVersionDigits(const DBfile * dbfile,int * maj,int * min,int * pat,int * pre)4026 DBFileVersionDigits(const DBfile *dbfile, int *maj, int *min, int *pat, int *pre)
4027 {
4028     int digits[4] = {0,0,0,0};
4029     if (!db_parse_version_digits_from_string(DBFileVersion(dbfile), '.',
4030              digits, sizeof(digits)/sizeof(digits[0])))
4031     {
4032         if (maj) *maj = digits[0];
4033         if (min) *min = digits[1];
4034         if (pat) *pat = digits[2];
4035         if (pre) *pre = digits[3];
4036         return 0;
4037     }
4038     return -1;
4039 }
4040 
4041 /*-------------------------------------------------------------------------
4042  * Function:    DBFileVersionGE
4043  *
4044  * Purpose:     Return whether or not the given file was created with a
4045  *              version of the library greater than or equal to the
4046  *              version specified by Maj, Min, Pat
4047  *
4048  * Returns:     1 if file version is greather than or equal to Maj/Min/Pat
4049  *              0 if file version is less than Maj/Min/Pat
4050  *             -1 if unable to determine.
4051  *
4052  * Programmer:  Mark C. Miller, Mon Jan 12 20:59:30 PST 2009
4053  *-------------------------------------------------------------------------*/
4054 PUBLIC int
DBFileVersionGE(const DBfile * dbfile,int Maj,int Min,int Pat)4055 DBFileVersionGE(const DBfile *dbfile, int Maj, int Min, int Pat)
4056 {
4057     int retval = -1;
4058     int unknown = 0;
4059     int a_digits[3];
4060     int b_digits[3] = {Maj<0?0:Maj, Min<0?0:Min, Pat<0?0:Pat};
4061     char *version = STRDUP(DBFileVersion(dbfile));
4062 
4063     if (strncmp(version, "unknown", 7) == 0)
4064     {
4065         /* We started maintaining library version information in the file
4066            in version 4.5.1. So, if it is 'unknown', we can return something
4067            useful ONLY if the version we're comparing against is 4.5.1 or
4068            greater. */
4069         a_digits[0] = 4;
4070         a_digits[1] = 5;
4071         a_digits[2] = 0;
4072         unknown = 1;
4073     }
4074     else
4075     {
4076         if (db_parse_version_digits_from_string(version, '.',
4077                  a_digits, sizeof(a_digits)/sizeof(a_digits[0])))
4078         {
4079             free(version);
4080             return -1;
4081         }
4082     }
4083 
4084     free(version);
4085 
4086     retval = db_compare_version_digits(a_digits, b_digits, 3) >= 0;
4087 
4088     if (unknown)
4089     {
4090         if (retval)
4091             retval = -1;
4092     }
4093 
4094     return retval;
4095 }
4096 
4097 /*-------------------------------------------------------------------------
4098  * Function:    DBOpen
4099  *
4100  * Purpose:     Open a data file.
4101  *
4102  * Return:      Success:        pointer to new file descriptor
4103  *
4104  *              Failure:        NULL
4105  *
4106  * Programmer:  matzke@viper
4107  *              Mon Nov  7 10:25:08 PST 1994
4108  *
4109  * Modifications:
4110  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
4111  *    I replaced API_END with API_END_NOPOP.
4112  *
4113  *    Robb Matzke, Tue Feb 28 10:51:19 EST 1995
4114  *    When a file is opened, it is given a unique ID number wrt all other
4115  *    open files.  The ID is a small integer [0..DB_NFILES-1].
4116  *
4117  *    Robb Matzke, Tue Feb 28 11:38:08 EST 1995
4118  *    For each registered filter, call the non-null `init' functions for
4119  *    every file that is opened.
4120  *
4121  *    Sean Ahern, Mon Jan  8 17:38:18 PST 1996
4122  *    Added the mode parameter.
4123  *
4124  *    Lisa J. Nafziger, Wed Mar  6 10:20:48 PST 1996
4125  *    Added code to check for file existence, to check if it is a
4126  *    directory and to check for read permission.  This allows more
4127  *    specific error messages to be returned.
4128  *
4129  *    Lisa J. Nafziger, Tue Mar 12 14:15:06 PST 1996
4130  *    Modified code to check file attributes so that stat() rather
4131  *    than access() is used.  The former is POSIX compliant.
4132  *
4133  *    Eric Brugger, Tue Jun 17 10:25:57 PDT 1997
4134  *    I modified the routine to only check file validity if the type
4135  *    is not an SDX connection.
4136  *
4137  *    Jeremy Meredith, Fri Jul 23 09:31:14 PDT 1999
4138  *    I added error reporting to the result of stat().
4139  *
4140  *    Jeremy Meredith, Mon Jul 26 10:39:49 PDT 1999
4141  *    Made stat() error reporting POSIX.1 compliant.
4142  *
4143  *    Sean Ahern, Wed Jul  5 15:35:48 PDT 2000
4144  *    Renamed the function to DBOpenReal.  Client code now calls a macro
4145  *    called DBOpen.
4146  *
4147  *    Mark C. Miller, Wed Feb  2 07:59:53 PST 2005
4148  *    Added printing of error message from stat() with strerror
4149  *
4150  *    Mark C. Miller, Wed Feb 23 08:51:35 PST 2005
4151  *    Added code to reset _db_fstatus slot to 0 if open fails
4152  *
4153  *    Thomas R. Treadway, Tue Jun 27 13:59:21 PDT 2006
4154  *    Added HAVE_STRERROR wrappers
4155  *
4156  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
4157  *    Added code to register the returned file pointer
4158  *
4159  *    Mark C. Miller, Mon Jan 12 20:50:41 PST 2009
4160  *    Removed DB_SDX conditionally compiled code blocks.
4161  *
4162  *    Mark C. Miller, Wed Feb 25 23:50:06 PST 2009
4163  *    Moved call to db_isregistered_file to AFTER calls to stat the file
4164  *    add changed db_isregistered_file to accept stat struct instead of name.
4165  *    Changed call to db_register_file to accpet stat struct.
4166  *
4167  *    Mark C. Miller, Fri Feb 12 08:22:41 PST 2010
4168  *    Replaced stat/stat64 calls with db_silo_stat. Replaced conditional
4169  *    compilation logic for SIZEOF_OFF64_T with db_silo_stat_struct.
4170  *------------------------------------------------------------------------- */
4171 PUBLIC DBfile *
DBOpenReal(const char * name,int type,int mode)4172 DBOpenReal(const char *name, int type, int mode)
4173 {
4174     char           ascii[16];
4175     DBfile        *dbfile;
4176     int            fileid, i;
4177     int            origtype = type;
4178     int            opts_set_id;
4179     db_silo_stat_t filestate;
4180 
4181     API_BEGIN("DBOpen", DBfile *, NULL) {
4182         if (!name)
4183             API_ERROR(NULL, E_NOFILE);
4184 
4185         /* deal with extended driver type specifications */
4186         db_DriverTypeAndFileOptionsSetId(origtype, &type, &opts_set_id);
4187 
4188         if (type < 0 || type >= DB_NFORMATS) {
4189             sprintf(ascii, "%d", type);
4190             API_ERROR(ascii, E_BADFTYPE);
4191         }
4192         if ((mode != DB_READ) && (mode != DB_APPEND))
4193         {
4194             sprintf(ascii, "%d", mode);
4195             API_ERROR(ascii, E_BADARGS);
4196         }
4197         if (!DBOpenCB[type]) {
4198             sprintf(ascii, "%d", type);
4199             API_ERROR(ascii, E_NOTIMP);
4200         }
4201 
4202         /****************************************************/
4203         /* Check to make sure the file exists and has the   */
4204         /* correct permissions.                             */
4205         /****************************************************/
4206         if (db_silo_stat(name, &filestate, type==DB_UNKNOWN?-1:opts_set_id) != 0)
4207         {
4208             if( errno == ENOENT )
4209             {
4210                 /********************************/
4211                 /* File doesn't exist.          */
4212                 /********************************/
4213                 API_ERROR((char *)name, E_NOFILE);
4214             }
4215             else
4216             {
4217                 /********************************/
4218                 /* System level error occured.  */
4219                 /********************************/
4220                 printf("stat() failed with error: ");
4221                 switch (errno)
4222                 {
4223                   case EACCES:       printf("EACCES\n");       break;
4224                   case EBADF:        printf("EBADF\n");        break;
4225                   case ENAMETOOLONG: printf("ENAMETOOLONG\n"); break;
4226                   case ENOTDIR:      printf("ENOTDIR\n");      break;
4227 #ifdef EOVERFLOW
4228                   case EOVERFLOW:
4229 #ifdef HAVE_STRERROR
4230                                      printf("EOVERFLOW: \"%s\"\n",
4231                                         strerror(errno));
4232 #else
4233                                      printf("EOVERFLOW: errno=%d\n", errno);
4234 #endif
4235                                      printf("Silo may need to be re-compiled with "
4236                                             "Large File Support (LFS)\n");
4237                                      break;
4238 #endif
4239                   default:
4240 #ifdef HAVE_STRERROR
4241                                      printf("\"%s\"\n",
4242                                         strerror(errno));
4243 #else
4244                                      printf("errno=%d\n", errno);
4245 #endif
4246                                      break;
4247                 }
4248                 API_ERROR((char *)name, E_SYSTEMERR);
4249             }
4250         }
4251 
4252         /* Check if file is already opened. If so, none can
4253            have it opened for write, including this new one */
4254         i = db_isregistered_file(0, &filestate);
4255         if (i != -1)
4256         {
4257             if (_db_regstatus[i].w != 0 || mode != DB_READ)
4258                 API_ERROR(name, E_CONCURRENT);
4259         }
4260 
4261         if( ( filestate.s.st_mode & S_IFDIR ) != 0 )
4262         {
4263             /************************************/
4264             /* File is actually a directory.    */
4265             /************************************/
4266             API_ERROR((char *)name, E_FILEISDIR);
4267         }
4268         if( ( filestate.s.st_mode & S_IREAD ) == 0 )
4269         {
4270             /****************************************/
4271             /* File is missing read permissions.    */
4272             /****************************************/
4273             API_ERROR((char *)name, E_FILENOREAD);
4274         }
4275         if (DB_READ!=mode && (filestate.s.st_mode & S_IWUSR) == 0)
4276         {
4277             /****************************************/
4278             /* File is open for write and missing write permission. */
4279             /****************************************/
4280             API_ERROR((char *)name, E_FILENOWRITE);
4281         }
4282 
4283         if ((fileid = db_get_fileid(DB_ISOPEN)) < 0)
4284             API_ERROR((char *)name, E_MAXOPEN);
4285         if (NULL == (dbfile = (DBOpenCB[type]) (name, mode, opts_set_id)))
4286         {
4287             _db_fstatus[fileid] = 0;
4288             API_RETURN(NULL);
4289         }
4290         dbfile->pub.fileid = fileid;
4291         db_register_file(dbfile, &filestate, mode!=DB_READ);
4292 
4293         /*
4294          * Install filters.  First, all `init' filters, then the
4295          * specified filters.
4296          */
4297         for (i = 0; i < DB_NFILTERS; i++) {
4298             if (_db_filter[i].name && _db_filter[i].init) {
4299                 (void)(_db_filter[i].init) (dbfile, _db_filter[i].name);
4300             }
4301         }
4302         db_filter_install(dbfile);
4303         if (DBInqVarExists(dbfile, SILO_VSTRING_NAME))
4304             dbfile->pub.file_lib_version = (char*)DBGetVar(dbfile, SILO_VSTRING_NAME);
4305 
4306         API_RETURN(dbfile);
4307     }
4308     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
4309 }
4310 
4311 /*-------------------------------------------------------------------------
4312  * Function:    DBCreateReal
4313  *
4314  * Purpose:     Create a data file
4315  *
4316  * Return:      Success:        pointer to file descriptor
4317  *
4318  *              Failure:        NULL
4319  *
4320  * Programmer:  matzke@viper
4321  *              Mon Nov  7 10:29:23 PST 1994
4322  *
4323  * Modifications:
4324  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
4325  *    I replaced API_END with API_END_NOPOP.
4326  *
4327  *    Robb Matzke, Tue Feb 28 10:57:06 EST 1995
4328  *    A file ID is assigned to the new file.
4329  *
4330  *    Robb Matzke, 15 May 1996
4331  *    Removed the unused `statue' auto variable.
4332  *
4333  *    Sean Ahern, Wed Jul  5 15:35:48 PDT 2000
4334  *    Renamed the function to DBCreateReal.  Client code now calls a macro
4335  *    called DBCreate.
4336  *
4337  *    Mark C. Miller, Wed Feb 23 08:51:35 PST 2005
4338  *    Added code to reset _db_fstatus slot to 0 if create fails
4339  *
4340  *    Mark C. Miller, Wed Apr  5 10:17:31 PDT 2006
4341  *    Added code to output silo library version string to the file
4342  *
4343  *    Mark C. Miller, Mon Nov 19 10:45:05 PST 2007
4344  *    Added hdf5 driver warning.
4345  *
4346  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
4347  *    Added code to register the returned file pointer
4348  *
4349  *    Mark C. Miller, Mon Nov 17 19:04:39 PST 2008
4350  *    Added code to check to see if name is a directory.
4351  *
4352  *    Mark C. Miller, Wed Feb 25 23:52:05 PST 2009
4353  *    Moved call to db_isregistered_file to after stat calls. Stat the
4354  *    file after its created so we can get information to register it.
4355  *
4356  *    Mark C. Miller, Fri Feb 12 08:22:41 PST 2010
4357  *    Replaced stat/stat64 calls with db_silo_stat. Replaced conditional
4358  *    compilation logic for SIZEOF_OFF64_T with db_silo_stat_struct.
4359  *
4360  *    Mark C. Miller, Thu Aug 30 17:41:24 PDT 2012
4361  *    Added logic to temporarily disable any compression settings prior
4362  *    to writing silo library info and then re-enabling it.
4363  *-------------------------------------------------------------------------*/
4364 PUBLIC DBfile *
DBCreateReal(const char * name,int mode,int target,const char * info,int type)4365 DBCreateReal(const char *name, int mode, int target, const char *info, int type)
4366 {
4367     char           ascii[16];
4368     char           *tmpcs = 0;
4369     DBfile        *dbfile;
4370     int            fileid, i, n;
4371     int            origtype = type;
4372     int            opts_set_id;
4373     db_silo_stat_t filestate;
4374 
4375     API_BEGIN("DBCreate", DBfile *, NULL) {
4376         if (!name)
4377             API_ERROR(NULL, E_NOFILE);
4378 
4379         /* deal with extended driver type specifications */
4380         db_DriverTypeAndFileOptionsSetId(origtype, &type, &opts_set_id);
4381 
4382         if (type < 0 || type >= DB_NFORMATS) {
4383             sprintf(ascii, "%d", type);
4384             API_ERROR(ascii, E_BADFTYPE);
4385         }
4386 
4387         if (db_silo_stat(name, &filestate, opts_set_id) == 0)  /* Success - File exists */
4388         {
4389             if (mode == DB_NOCLOBBER)
4390             {
4391                 API_ERROR((char *)name, E_FEXIST);
4392             }
4393             if ((filestate.s.st_mode & S_IFDIR) != 0)
4394             {
4395                 API_ERROR((char *)name, E_FILEISDIR);
4396             }
4397 
4398             /* Check if file is already opened. If so, none can
4399                have it opened for write, including this new one */
4400             i = db_isregistered_file(0, &filestate);
4401             if (i != -1)
4402             {
4403                 API_ERROR(name, E_CONCURRENT);
4404             }
4405         }
4406 
4407         if (!DBCreateCB[type]) {
4408             sprintf(ascii, "%d", type);
4409             if (type == 7)
4410             {
4411                 API_ERROR(ascii, E_NOHDF5);
4412             }
4413             else
4414             {
4415                 API_ERROR(ascii, E_NOTIMP);
4416             }
4417         }
4418 
4419         if ((fileid = db_get_fileid(DB_ISOPEN)) < 0)
4420             API_ERROR((char *)name, E_MAXOPEN);
4421         dbfile = ((DBCreateCB[type]) (name, mode, target, opts_set_id,
4422                                       info));
4423         if (!dbfile)
4424         {
4425             _db_fstatus[fileid] = 0;
4426             API_RETURN(NULL);
4427         }
4428         dbfile->pub.fileid = fileid;
4429         db_silo_stat(name, &filestate, opts_set_id);
4430         db_register_file(dbfile, &filestate, 1);
4431 
4432         /*
4433          * Install filters.  First all `init' routines, then the specified
4434          * `open' routines.
4435          */
4436         for (i = 0; i < DB_NFILTERS; i++) {
4437             if (_db_filter[i].name && _db_filter[i].init) {
4438                 (void)(_db_filter[i].init) (dbfile, _db_filter[i].name);
4439             }
4440         }
4441         db_filter_install(dbfile);
4442 
4443         /* write silo library version information to the file */
4444         /* Temporarily turn off any compression settings and then re-enable */
4445         if (DBGetCompression())
4446         {
4447 
4448             n = strlen(DBGetCompression());
4449             tmpcs = ALLOC_N(char,n+1);
4450             strncpy(tmpcs, DBGetCompression(), n);
4451             tmpcs[n] = '\0';
4452             DBSetCompression(0);
4453         }
4454         n = strlen(SILO_VSTRING)+1;
4455         DBWrite(dbfile, SILO_VSTRING_NAME, SILO_VSTRING, &n, 1, DB_CHAR);
4456         dbfile->pub.file_lib_version = STRDUP(SILO_VSTRING);
4457         if (tmpcs)
4458         {
4459             DBSetCompression(tmpcs);
4460             FREE(tmpcs);
4461         }
4462 
4463         API_RETURN(dbfile);
4464     }
4465     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
4466 }
4467 
4468 /*-------------------------------------------------------------------------
4469  * Function:    DBClose
4470  *
4471  * Purpose:     Close the specified data file and return NULL.
4472  *
4473  * Return:      Success:        NULL
4474  *
4475  *              Failure:        NULL
4476  *
4477  * Programmer:  matzke@viper
4478  *              Mon Nov  7 10:31:41 PST 1994
4479  *
4480  * Modifications:
4481  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
4482  *    I replaced API_END with API_END_NOPOP.
4483  *
4484  *    Eric Brugger, Mon Feb 27 15:03:01 PST 1995
4485  *    I changed the return value to be an integer instead of a pointer
4486  *    to a DBfile.
4487  *
4488  *    Robb Matzke, Tue Feb 28 10:57:57 EST 1995
4489  *    The file status slot is cleared so it can be reused.
4490  *
4491  *    Eric Brugger, Mon Jul 10 07:42:24 PDT 1995
4492  *    I moved the reseting of _db_fstatus to before the return statement,
4493  *    so that the instruction would get executed.
4494  *
4495  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
4496  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
4497  *    Added code to UNregister the given file pointer.
4498  *-------------------------------------------------------------------------*/
4499 PUBLIC int
DBClose(DBfile * dbfile)4500 DBClose(DBfile *dbfile)
4501 {
4502     int            id;
4503     int            retval;
4504 
4505     API_BEGIN2("DBClose", int, -1, api_dummy) {
4506         if (!dbfile)
4507             API_ERROR(NULL, E_NOFILE);
4508         if (NULL == dbfile->pub.close)
4509             API_ERROR(dbfile->pub.name, E_NOTIMP);
4510         id = dbfile->pub.fileid;
4511         if (id >= 0 && id < DB_NFILES)
4512             _db_fstatus[id] = 0;
4513 
4514         if (dbfile->pub.file_lib_version)
4515             free(dbfile->pub.file_lib_version);
4516         db_unregister_file(dbfile);
4517         retval = (dbfile->pub.close) (dbfile);
4518         API_RETURN(retval);
4519     }
4520     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
4521 }
4522 
4523 /*----------------------------------------------------------------------
4524  * Routine:  db_inq_file_has_silo_objects_r
4525  *
4526  * Purpose:  Recursive helper func for DBInqFileHasObjects
4527  *
4528  * Programmer: Mark C. Miller, Wed Sep 23 11:34:01 PDT 2009
4529  *
4530  * Modifications:
4531  *   Mark C. Miller, Mon Nov 16 10:28:41 PST 2009
4532  *   Fixed dir recursion by copying dir-related toc entries. Removed
4533  *   misc. vars from count of silo objects.
4534  *--------------------------------------------------------------------*/
4535 
4536 PRIVATE int
db_inq_file_has_silo_objects_r(DBfile * f)4537 db_inq_file_has_silo_objects_r(DBfile *f)
4538 {
4539     int i, ndir, retval = 0;
4540     char **dirnames;
4541     DBtoc *toc = DBGetToc(f);
4542 
4543     if (!toc)
4544         return -1;
4545 
4546     /* save dirnames so we don't loose 'em as we get new tocs */
4547     ndir = toc->ndir;
4548     dirnames = (char **) malloc(ndir * sizeof(char*));
4549     for (i = 0; i < ndir; i++)
4550         dirnames[i] = STRDUP(toc->dir_names[i]);
4551 
4552     /* We exclude dirs and misc. vars because a non-Silo file may
4553      * contain them. */
4554     retval = toc->ncurve + toc->ncsgmesh + toc->ncsgvar + toc->ndefvars +
4555         toc->nmultimesh + toc->nmultimeshadj + toc->nmultivar +
4556         toc->nmultimat + toc->nmultimatspecies + toc->nqmesh +
4557         toc->nqvar + toc->nucdmesh + toc->nucdvar + toc->nptmesh +
4558         toc->nptvar + toc->nmat + toc->nmatspecies +
4559         toc->nobj + toc->nmrgtree + toc->ngroupelmap +
4560         toc->nmrgvar + toc->narray;
4561 
4562     /* Recurse on directories. */
4563     for (i = 0; i < ndir && retval == 0; i++)
4564     {
4565         DBSetDir(f, dirnames[i]);
4566         retval += db_inq_file_has_silo_objects_r(f);
4567         DBSetDir(f, "..");
4568     }
4569 
4570     /* free the dirnames */
4571     for (i = 0; i < ndir; i++)
4572         free(dirnames[i]);
4573     free(dirnames);
4574 
4575     return retval;
4576 }
4577 
4578 /*-------------------------------------------------------------------------
4579  * Function:    DBInqFileHasObjects
4580  *
4581  * Purpose:     See if the file contains any silo objects, excluding
4582  *              directories in the search.
4583  *
4584  * Return:      Success:         >0 ==> yes, the file has silo objects.
4585  *                              ==0 ==> no, the file has no silo objects.
4586  *
4587  *              Failure:        -1
4588  *
4589  * Programmer:  Mark C. Miller, Wed Sep 23 09:42:27 PDT 2009
4590  *
4591  * Modifications:
4592  *   Mark C. Miller, Mon Nov 16 10:29:36 PST 2009
4593  *   Added logic to test from some well known, tell-tale silo variables.
4594  *-------------------------------------------------------------------------*/
4595 
4596 PUBLIC int
DBInqFileHasObjects(DBfile * f)4597 DBInqFileHasObjects(DBfile *f)
4598 {
4599     char cwd[4096];
4600     int retval;
4601 
4602     if (f == 0)
4603         return -1;
4604 
4605     if (DBInqVarExists(f, "_silolibinfo"))
4606         return 1;
4607     if (DBInqVarExists(f, "_hdf5libinfo"))
4608         return 1;
4609 
4610     DBGetDir(f, cwd);
4611     retval = db_inq_file_has_silo_objects_r(f);
4612     DBSetDir(f, cwd);
4613 
4614     return retval;
4615 }
4616 
4617 /*-------------------------------------------------------------------------
4618  * Function:    DBInqFileReal
4619  *
4620  * Purpose:     Determines if the filename is a Silo file.
4621  *
4622  * Return:      0  if filename is not a Silo file,
4623  *              >0 if filename is a Silo file,
4624  *              <0 if an error occurred.
4625  *
4626  * Programmer:  Hank Childs
4627  *              Tue Feb 29 16:24:01 PST 2000
4628  *
4629  * Modifications:
4630  *    Sean Ahern, Wed Jul  5 15:35:48 PDT 2000
4631  *    Renamed the function to DBInqFileReal.  Client code now calls a macro
4632  *    called DBInqFile.
4633  *
4634  *    Mark C. Miller, Wed Sep 23 11:48:19 PDT 2009
4635  *    Added logic to confirm that indeed the successfully opened file has
4636  *    some silo objects in it.
4637  *-------------------------------------------------------------------------*/
4638 PUBLIC int
DBInqFileReal(const char * filename)4639 DBInqFileReal(const char *filename)
4640 {
4641     DBfile *dbfile = NULL;
4642     int hasobjects = -1;
4643 
4644     API_BEGIN("DBInqFile", int, -1) {
4645         if (!filename || ! *filename)
4646             API_ERROR("filename", E_BADARGS);
4647 
4648         /*
4649          * Turn the error handling off so user won't see errors,
4650          * won't abort, etc.
4651          */
4652         DBShowErrors(DB_SUSPEND, NULL);
4653 
4654         /*
4655          * Must protect this code so that the error handling can be
4656          * restored afterwards.
4657          */
4658         PROTECT {
4659             dbfile = DBOpen(filename, DB_UNKNOWN, DB_READ);
4660             if (dbfile)
4661                 hasobjects = DBInqFileHasObjects(dbfile);
4662         } CLEANUP {
4663             CANCEL_UNWIND;
4664         } END_PROTECT;
4665 
4666         /*
4667          * Turn the error handling back on.
4668          */
4669         DBShowErrors(DB_RESUME, NULL);
4670 
4671         if (dbfile != NULL)
4672         {
4673             DBClose(dbfile);
4674             API_RETURN(hasobjects);
4675         }
4676 
4677         API_RETURN(0);
4678     }
4679     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
4680 }
4681 
4682 /*----------------------------------------------------------------------
4683  *  Routine                                               DBInqVarExists
4684  *
4685  *  Purpose
4686  *
4687  *      Determine if the given variable object exists in the SILO file.
4688  *      Return non-zero if it does and 0 if it doesn't.
4689  *
4690  *  Programmer
4691  *
4692  *      Sean Ahern, Thu Jul 20 11:53:40 PDT 1995
4693  *
4694  *  Modifications
4695  *    Mon Aug 28 11:15:21 PDT 1995
4696  *    (ahern) Changed the API_BEGIN to API_BEGIN2.
4697  *
4698  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
4699  *    Added a check for variable name validity.
4700  *--------------------------------------------------------------------*/
4701 PUBLIC int
DBInqVarExists(DBfile * dbfile,const char * varname)4702 DBInqVarExists(DBfile *dbfile, const char *varname)
4703 {
4704     int retval;
4705 
4706     API_BEGIN2("DBInqVarExists", int, 0, varname) {
4707         if (!dbfile)
4708             API_ERROR(NULL, E_NOFILE);
4709         if (!varname || !*varname)
4710             API_ERROR("variable name", E_BADARGS);
4711         if (dbfile->pub.exist == NULL)
4712             API_ERROR(dbfile->pub.name, E_NOTIMP);
4713         retval = (dbfile->pub.exist) (dbfile, varname);
4714         API_RETURN(retval);
4715     }
4716     API_END_NOPOP; /* BEWARE: If API_RETURN above is removed use API_END */
4717 }
4718 
4719 /*-------------------------------------------------------------------------
4720  * Function:    DBForceSingle
4721  *
4722  * Purpose:     If 'status' is non-zero, then any 'datatype'd arrays are
4723  *              converted on read from whatever their native datatype is to
4724  *              float. A 'datatype'd array is an array that is part of some
4725  *              Silo object containing a 'datatype' member which indicates
4726  *              the type of data in the array. So, for example, a DBucdvar
4727  *              has a 'datatype' member to indicate the type of data in the
4728  *              var and mixvar arrays. Such arrays will be converted on read
4729  *              if 'status' here is non-zero. However, a DBmaterial object
4730  *              is ALWAYS integer data. There is no 'datatype' member for
4731  *              such an object and so its data will NEVER be converted to
4732  *              float on read regardless of force single status set here.
4733  *
4734  *              I believe this function's original intention was to convert
4735  *              only double precision arrays to single precision. However,
4736  *              the PDB driver was apparently never designed that way and
4737  *              the PDB driver's behavior sort of established the defacto
4738  *              meaning of force single. So, now, as of Silo version 4.8
4739  *              the HDF5 driver obeys it as well. Though, in fact the HDF5
4740  *              driver was originally written to support the original
4741  *              intention of force single status and it worked in this
4742  *              ('buggy') fashion for many years before we started
4743  *              encountering real problems with it in VisIt.
4744  *
4745  * Return:      Success:        0 if all drivers succeeded or did not
4746  *                              implement this function.
4747  *
4748  *              Failure:        -1 if any driver returned failure.
4749  *
4750  * Programmer:  matzke@viper
4751  *              Tue Jan 10 11:01:24 PST 1995
4752  *
4753  * Modifications:
4754  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
4755  *    I replaced API_END with API_END_NOPOP.
4756  *
4757  *    Mark C. Miller, Fri Jul 16 19:28:23 PDT 2010
4758  *    Updated 'Purpose' above to reflect current understanding of the
4759  *    meaning of force single.
4760  *-------------------------------------------------------------------------*/
4761 PUBLIC int
DBForceSingle(int status)4762 DBForceSingle(int status)
4763 {
4764     int            i;
4765 
4766     API_BEGIN("DBForceSingle", int, -1) {
4767         for (i = 0; i < DB_NFORMATS; i++) {
4768             if (DBFSingleCB[i]) {
4769                 if (((DBFSingleCB[i]) (status)) < 0) {
4770                     char           dname[32];
4771 
4772                     sprintf(dname, "driver-%d", i);
4773                     API_ERROR(dname, E_CALLFAIL);
4774                 }
4775             }
4776         }
4777     }
4778     API_END;
4779 
4780     return(0);
4781 }
4782 
4783 /*----------------------------------------------------------------------
4784  *  Routine                                                DBMakeOptlist
4785  *
4786  *  Purpose
4787  *
4788  *      Allocate an option list of the requested length and initialize it.
4789  *
4790  *  Programmer
4791  *
4792  *      Jeffery W. Long, NSSD-B
4793  *
4794  *  Modified
4795  *    Robb Matzke, Tue Nov 8 06:58:04 PST 1994
4796  *    Added error mechanism
4797  *--------------------------------------------------------------------*/
4798 PUBLIC DBoptlist *
DBMakeOptlist(int maxopts)4799 DBMakeOptlist(int maxopts)
4800 {
4801     DBoptlist     *optlist = NULL;
4802 
4803     API_BEGIN("DBMakeOptlist", DBoptlist *, NULL) {
4804         if (maxopts <= 0)
4805             API_ERROR("maxopts", E_BADARGS);
4806         optlist = ALLOC(DBoptlist);
4807         if (!optlist) API_ERROR(NULL, E_NOMEM);
4808         optlist->options = ALLOC_N(int, maxopts);
4809         optlist->values = ALLOC_N(void *, maxopts);
4810 
4811         if (!optlist->options || !optlist->values)
4812         {
4813             FREE(optlist->values);
4814             FREE(optlist->options);
4815             FREE(optlist);
4816             API_ERROR(NULL, E_NOMEM);
4817         }
4818 
4819         optlist->numopts = 0;
4820         optlist->maxopts = maxopts;
4821 
4822         API_RETURN(optlist);
4823     }
4824     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
4825 }
4826 
4827 /*----------------------------------------------------------------------
4828  *  Routine                                                DBFreeOptlist
4829  *
4830  *  Purpose
4831  *
4832  *      Release the storage associated with the given optlist list.
4833  *
4834  *  Programmer
4835  *
4836  *      Jeffery W. Long, NSSD-B
4837  *
4838  *  Returns
4839  *
4840  *      Returns 0 on success, -1 on failure.
4841  *
4842  *  Modified
4843  *    Robb Matzke, Tue Nov 8 07:56:34 PST 1994
4844  *    Added error mechanism.
4845  *
4846  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
4847  *    Made the error messages a little better.
4848  *--------------------------------------------------------------------*/
4849 PUBLIC int
DBFreeOptlist(DBoptlist * optlist)4850 DBFreeOptlist(DBoptlist *optlist)
4851 {
4852     API_BEGIN("DBFreeOptlist", int, -1) {
4853         if (!optlist || optlist->numopts < 0) {
4854             API_ERROR("optlist pointer", E_BADARGS);
4855         }
4856         FREE(optlist->options);
4857         FREE(optlist->values);
4858         FREE(optlist);
4859     }
4860     API_END;
4861 
4862     return(0);
4863 }
4864 
4865 /*----------------------------------------------------------------------
4866  *  Routine                                                DBClearOptlist
4867  *
4868  *  Purpose
4869  *
4870  *      Remove all options from the given optlist and reset counters.
4871  *
4872  *  Programmer
4873  *
4874  *      Jeffery W. Long, NSSD-B
4875  *
4876  *  Returns
4877  *
4878  *      Returns OKAY on success, OOPS on failure.
4879  *
4880  *  Modified
4881  *    Robb Matzke, Tue Nov 8 07:48:52 PST 1994
4882  *    Added error mechanism.
4883  *
4884  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
4885  *    Made the error messages a little better.
4886  *--------------------------------------------------------------------*/
4887 PUBLIC int
DBClearOptlist(DBoptlist * optlist)4888 DBClearOptlist(DBoptlist *optlist)
4889 {
4890     int            i;
4891 
4892     API_BEGIN("DBClearOptlist", int, -1) {
4893         if (!optlist || optlist->numopts < 0) {
4894             API_ERROR("optlist pointer", E_BADARGS);
4895         }
4896 
4897         /* Reset values, but do not free */
4898         for (i = 0; i < optlist->maxopts; i++) {
4899             optlist->options[i] = 0;
4900             optlist->values[i] = (void *)NULL;
4901         }
4902 
4903         optlist->numopts = 0;
4904     }
4905     API_END;
4906 
4907     return(0);
4908 }
4909 
4910 /*----------------------------------------------------------------------
4911  *  Routine                                                  DBAddOption
4912  *
4913  *  Purpose
4914  *
4915  *      Add an option to the given option list structure.
4916  *
4917  *  Programmer
4918  *
4919  *      Jeffery W. Long, NSSD-B
4920  *
4921  *  Returns
4922  *
4923  *      Returns OKAY on success, OOPS on failure.
4924  *
4925  *  Modified:
4926  *    Robb Matzke, Tue Nov 8 07:00:55 PST 1994
4927  *    Added error mechanism.  Returns -1 on failure, 0 on success.
4928  *
4929  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
4930  *    Made the error messages a little better.
4931  *--------------------------------------------------------------------*/
4932 PUBLIC int
DBAddOption(DBoptlist * optlist,int option,void * value)4933 DBAddOption(DBoptlist *optlist, int option, void *value)
4934 {
4935     API_BEGIN("DBAddOption", int, -1) {
4936         if (!optlist)
4937             API_ERROR("optlist pointer", E_BADARGS);
4938         if (optlist->numopts >= optlist->maxopts)
4939             API_ERROR("optlist nopts", E_BADARGS);
4940 
4941         optlist->options[optlist->numopts] = option;
4942         optlist->values[optlist->numopts] = value;
4943         optlist->numopts++;
4944 
4945         if (optlist->numopts >= optlist->maxopts)
4946         {
4947             int new_maxopts = optlist->maxopts * 1.5 + 1; /* golden rule + 1 */
4948             int *new_options = REALLOC_N(optlist->options, int, new_maxopts);
4949             void **new_values = REALLOC_N(optlist->values, void*, new_maxopts);
4950 
4951             if (!new_options || !new_values)
4952             {
4953                 FREE(new_options);
4954                 FREE(new_values);
4955                 API_ERROR(0, E_NOMEM);
4956             }
4957 
4958             optlist->maxopts = new_maxopts;
4959             optlist->options = new_options;
4960             optlist->values  = new_values;
4961         }
4962 
4963     }
4964     API_END;
4965 
4966     return(0);
4967 }
4968 
4969 /*----------------------------------------------------------------------
4970  *  Routine                                                DBClearOption
4971  *
4972  *  Purpose
4973  *
4974  *      Remove a given option from the given optlist and re-order
4975  *      the remaining options.
4976  *
4977  *  Programmer
4978  *
4979  *      Mark C. Miller, August 18, 2005
4980  *
4981  *--------------------------------------------------------------------*/
4982 PUBLIC int
DBClearOption(DBoptlist * optlist,int option)4983 DBClearOption(DBoptlist *optlist, int option)
4984 {
4985     int            i, j, foundit=0;
4986 
4987     API_BEGIN("DBClearOption", int, -1) {
4988         if (!optlist || optlist->numopts < 0) {
4989             API_ERROR("optlist pointer", E_BADARGS);
4990         }
4991 
4992         /* Shift values down in list by one entry */
4993         for (i = 0; i < optlist->numopts; i++) {
4994             if (optlist->options[i] == option) {
4995                 foundit = 1;
4996                 for (j = i; j < optlist->numopts-1; j++) {
4997                     optlist->options[j] = optlist->options[j+1];
4998                     optlist->values[j]  = optlist->values[j+1];
4999                 }
5000                 break;
5001             }
5002         }
5003 
5004         if (foundit) {
5005             optlist->numopts--;
5006             optlist->options[optlist->numopts] = 0;
5007             optlist->values[optlist->numopts]  = 0;
5008         }
5009     }
5010     API_END;
5011 
5012     return(0);
5013 }
5014 
5015 /*----------------------------------------------------------------------
5016  *  Routine                                                DBGetOption
5017  *
5018  *  Purpose
5019  *
5020  *      Return value set for a given option from the given optlist.
5021  *
5022  *  Programmer
5023  *
5024  *      Mark C. Miller, August 18, 2005
5025  *
5026  *  Modifications:
5027  *
5028  *      Mark C. Miller, Wed Jul 14 20:35:50 PDT 2010
5029  *      Replaced 'return' with 'API_RETURN'
5030  *
5031  *      Mark C. Miller, Tue Aug 10 23:49:51 PDT 2010
5032  *      Removed API_BEGIN/END stuff so that function can be handed
5033  *      a null optlist and it will behave well.
5034  *--------------------------------------------------------------------*/
5035 PUBLIC void *
DBGetOption(const DBoptlist * optlist,int option)5036 DBGetOption(const DBoptlist *optlist, int option)
5037 {
5038     int            i;
5039 
5040     if (!optlist) return 0;
5041 
5042     /* find the given option in the optlist and return its value */
5043     for (i = 0; i < optlist->numopts; i++)
5044         if (optlist->options[i] == option)
5045             return optlist->values[i];
5046 
5047     return 0;
5048 }
5049 
5050 /*-------------------------------------------------------------------------
5051  * Function:    DBGetToc
5052  *
5053  * Purpose:     Return a pointer to table of contents of the file.  Note
5054  *              that the pointer is the same as the one in the DBfile
5055  *              so it should not be modified and may become invalid after
5056  *              calling the next silo routine.
5057  *
5058  * Return:      Success:        Pointer to the table of contents structure.
5059  *
5060  *              Failure:        NULL
5061  *
5062  * Programmer:  matzke@viper
5063  *              Mon Nov  7 10:35:47 PST 1994
5064  *
5065  * Modifications:
5066  *    Eric Brugger, Fri Jan 27 08:23:43 PST 1995
5067  *    I changed the interface and function of the routine.
5068  *
5069  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5070  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5071  *-------------------------------------------------------------------------*/
5072 PUBLIC DBtoc  *
DBGetToc(DBfile * dbfile)5073 DBGetToc(DBfile *dbfile)
5074 {
5075     API_BEGIN2("DBGetToc", DBtoc *, NULL, api_dummy) {
5076         if (SILO_Globals.enableGrabDriver == TRUE)
5077             API_ERROR("", E_GRABBED) ;
5078         if (!dbfile)
5079             API_ERROR(NULL, E_NOFILE);
5080 
5081         DBNewToc(dbfile);
5082         API_RETURN(dbfile->pub.toc);
5083     }
5084     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5085 }
5086 
5087 /*-------------------------------------------------------------------------
5088  * Function:    DBInqVarType
5089  *
5090  * Purpose:     Return the DBObjectType for a given object name
5091  *
5092  * Return:      Success:        the ObjectType for the given object
5093  *
5094  *              Failure:        DB_INVALID_OBJECT
5095  *
5096  * Programmer:  Sean Ahern,
5097  *              Wed Oct 28 14:46:53 PST 1998
5098  *
5099  * Modifications:
5100  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
5101  *    Added a check for variable name validity.
5102  *
5103  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5104  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5105  *-------------------------------------------------------------------------*/
5106 PUBLIC DBObjectType
DBInqVarType(DBfile * dbfile,char const * varname)5107 DBInqVarType(DBfile *dbfile, char const *varname)
5108 {
5109     DBObjectType retval;
5110 
5111     API_BEGIN2("DBInqVarType", DBObjectType, DB_INVALID_OBJECT, api_dummy) {
5112         if (SILO_Globals.enableGrabDriver == TRUE)
5113             API_ERROR("", E_GRABBED) ;
5114         if (!dbfile)
5115             API_ERROR(NULL, E_NOFILE);
5116         if (!varname || !*varname)
5117             API_ERROR("variable name", E_BADARGS);
5118         if (!dbfile->pub.inqvartype)
5119             API_ERROR(dbfile->pub.name, E_NOTIMP);
5120 
5121         retval = (dbfile->pub.inqvartype) (dbfile, varname);
5122         API_RETURN(retval);
5123     }
5124     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5125 }
5126 
5127 /*-------------------------------------------------------------------------
5128  * Function:    DBNewToc
5129  *
5130  * Purpose:     Used to be called `DBGetToc', this function installs a
5131  *              new table of contents in the specified file from that
5132  *              file's current working directory.  The old table of contents
5133  *              is destroyed.
5134  *
5135  * Return:      Success:        0
5136  *
5137  *              Failure:        -1
5138  *
5139  * Programmer:  robb@cloud
5140  *              Tue Mar  7 10:26:23 EST 1995
5141  *
5142  * Modifications:
5143  *              Robb Matzke, 2000-05-23
5144  *              If nothing has changed then this function just returns
5145  *              success, leaving the original table of contents in place.
5146  *              Any function that potentially changes the table of
5147  *              contents should call db_FreeToc() on the file handle.
5148  *-------------------------------------------------------------------------*/
5149 PUBLIC int
DBNewToc(DBfile * dbfile)5150 DBNewToc(DBfile *dbfile)
5151 {
5152     int retval;
5153 
5154     API_BEGIN("DBNewToc", int, -1) {
5155         if (!dbfile)
5156             API_ERROR(NULL, E_NOFILE);
5157         if (SILO_Globals.enableGrabDriver == TRUE)
5158             API_ERROR("", E_GRABBED) ;
5159         if (!dbfile->pub.newtoc)
5160             API_ERROR(dbfile->pub.name, E_NOTIMP);
5161         if (dbfile->pub.toc)
5162             API_RETURN(0);
5163         retval = (dbfile->pub.newtoc) (dbfile);
5164         API_RETURN(retval);
5165     }
5166     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5167 }
5168 
5169 /*
5170 This logic is necessary to support callers accessing standard (e.g. non-DB_USERDEF)
5171 objects via the generic interface to ensure logic for specially handled component
5172 values is consistent with the standard object's DBGetXXX methods.
5173 To ensure a zero for the component in the file means either not-present or
5174 not-set, certain components, especially those for which a zero value is a valid
5175 value for the data producer to use, special handling is required and that logic
5176 is sprinkled about in the DBPutXXX and DBGetXXX methods of the drivers and so
5177 to is it required here. Its a nasty maintenance issue.
5178 */
5179 
5180 static int
db_IsComponentNameStandardWithSpecialHandling(char const * compname)5181 db_IsComponentNameStandardWithSpecialHandling(char const *compname)
5182 {
5183     if (!strcmp(compname, "missing_value")) return 1;
5184     if (!strcmp(compname, "topo_dim")) return 1;
5185     if (!strcmp(compname, "repr_block_idx")) return 1;
5186     return 0;
5187 }
5188 
5189 /* For use in the DBGetComponent call */
5190 static void
db_AdjustSpeciallyHandledStandardObjectComponentValue(void * val_ptr,int obj_type,char const * comp_name)5191 db_AdjustSpeciallyHandledStandardObjectComponentValue(
5192     void *val_ptr, int obj_type, char const *comp_name)
5193 {
5194     if (!val_ptr || !comp_name) return;
5195 
5196     if (!strcmp(comp_name, "missing_value") &&
5197         (obj_type == DB_UCDVAR || obj_type == DB_QUADVAR || obj_type == DB_CURVE ||
5198          obj_type == DB_POINTVAR || obj_type == DB_MULTIVAR))
5199     {
5200         double val_for_mem, val_from_file = *((double*)val_ptr);
5201         db_SetMissingValueForGet(val_for_mem, val_from_file);
5202         *((double*)val_ptr) = val_for_mem;
5203     }
5204     else if (!strcmp(comp_name, "repr_block_idx") &&
5205         (obj_type == DB_MULTIMESH || obj_type == DB_MULTIVAR ||
5206          obj_type == DB_MULTIMAT || obj_type == DB_MULTIMATSPECIES))
5207     {
5208         int val_for_mem, val_from_file = *((int*)val_ptr);
5209         val_for_mem = val_from_file - 1;
5210         *((int*)val_ptr) = val_for_mem;
5211     }
5212     else if (!strcmp(comp_name, "topo_dim") &&
5213         (obj_type == DB_MULTIMESH || obj_type == DB_UCDMESH))
5214     {
5215         int val_for_mem, val_from_file = *((int*)val_ptr);
5216         val_for_mem = val_from_file - 1;
5217         *((int*)val_ptr) = val_for_mem;
5218     }
5219 }
5220 
5221 /* For use in the DBGetObject call */
5222 static void
db_AdjustSpeciallyHandledStandardObjectComponentValues(DBobject * obj)5223 db_AdjustSpeciallyHandledStandardObjectComponentValues(DBobject *obj)
5224 {
5225     int i, obj_type;
5226 
5227     if (!obj) return;
5228 
5229     obj_type = DBGetObjtypeTag(obj->type);
5230     if (obj_type == DB_USERDEF) return;
5231 
5232     for (i = 0; i < obj->ncomponents; i++)
5233     {
5234         char tmp[256];
5235 
5236         if (!strcmp(obj->comp_names[i], "missing_value") &&
5237             (obj_type == DB_UCDVAR || obj_type == DB_QUADVAR || obj_type == DB_CURVE ||
5238              obj_type == DB_POINTVAR || obj_type == DB_MULTIVAR))
5239         {
5240             double val_for_mem, val_from_file = strtod(obj->pdb_names[i]+4,0);
5241             db_SetMissingValueForGet(val_for_mem, val_from_file);
5242             sprintf(tmp, "'<d>%.30g'", val_for_mem);
5243         }
5244         else if (!strcmp(obj->comp_names[i], "repr_block_idx") &&
5245             (obj_type == DB_MULTIMESH || obj_type == DB_MULTIVAR ||
5246              obj_type == DB_MULTIMAT || obj_type == DB_MULTIMATSPECIES))
5247         {
5248             int val_for_mem, val_from_file = (int) strtol(obj->pdb_names[i]+4,0,10);
5249             val_for_mem = val_from_file - 1;
5250             sprintf(tmp, "'<i>%d'", val_for_mem);
5251         }
5252         else if (!strcmp(obj->comp_names[i], "topo_dim") &&
5253             (obj_type == DB_MULTIMESH || obj_type == DB_UCDMESH))
5254         {
5255             int val_for_mem, val_from_file = (int) strtol(obj->pdb_names[i]+4,0,10);
5256             val_for_mem = val_from_file - 1;
5257             sprintf(tmp, "'<i>%d'", val_for_mem);
5258         }
5259         else
5260         {
5261             continue;
5262         }
5263 
5264         FREE(obj->pdb_names[i]);
5265         obj->pdb_names[i] = STRDUP(tmp);
5266     }
5267 }
5268 
5269 /*----------------------------------------------------------------------
5270  *  Routine                                                DBGetComponent
5271  *
5272  *  Purpose
5273  *
5274  *      Return the requested component value for the given object.
5275  *
5276  *  Programmer
5277  *
5278  *      Jeffery W. Long, NSSD-B
5279  *
5280  *  Parameters
5281  *
5282  *      dbfile           {In}    {Pointer to current file}
5283  *      objname          {In}    {Name of object to inquire about}
5284  *      compname         {In}    {Name of component to return}
5285  *
5286  *  Notes
5287  *
5288  *  Modified
5289  *    Robb Matzke, Tue Nov 8 08:22:42 PST 1994
5290  *    Added error mechanism
5291  *
5292  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
5293  *    I replaced API_END with API_END_NOPOP.
5294  *
5295  *    Eric Brugger, Wed Mar 10 16:59:34 PST 1999
5296  *    Changed API_BEGIN2 to API_BEGIN so that Silo directory information
5297  *    would be processed at the driver level, since the pdb driver
5298  *    version of this routine handles silo directory paths as well as
5299  *    file system directory paths, which API_BEGIN2 does not.
5300  *
5301  *    Eric Brugger, Thu Mar 11 12:33:15 PST 1999
5302  *    I forgot to remove the fourth argument when I changed API_BEGIN2
5303  *    to API_BEGIN.  I did so now.
5304  *
5305  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
5306  *    Added a check for variable name validity.
5307  *
5308  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
5309  *    Made the error messages a little better.
5310  *
5311  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5312  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5313  *--------------------------------------------------------------------*/
5314 PUBLIC void   *
DBGetComponent(DBfile * dbfile,char const * objname,char const * compname)5315 DBGetComponent(DBfile *dbfile, char const *objname, char const *compname)
5316 {
5317     void *retval = NULL;
5318 
5319     API_BEGIN2("DBGetComponent", void *, NULL, api_dummy) {
5320         if (!dbfile)
5321             API_ERROR(NULL, E_NOFILE);
5322         if (SILO_Globals.enableGrabDriver == TRUE)
5323             API_ERROR("DBGetComponent", E_GRABBED) ;
5324         if (!objname || !*objname)
5325             API_ERROR("object name", E_BADARGS);
5326         if (!compname || !*compname)
5327             API_ERROR("component name", E_BADARGS);
5328         if (!dbfile->pub.g_comp)
5329             API_ERROR(dbfile->pub.name, E_NOTIMP);
5330 
5331         retval = (dbfile->pub.g_comp) (dbfile, objname, compname);
5332 
5333         if (db_IsComponentNameStandardWithSpecialHandling(compname))
5334             db_AdjustSpeciallyHandledStandardObjectComponentValue(retval,
5335                 DBInqVarType(dbfile, objname), compname);
5336 
5337         API_RETURN(retval);
5338     }
5339     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5340 }
5341 
5342 /*----------------------------------------------------------------------
5343  *  Routine                                           DBGetComponentType
5344  *
5345  *  Purpose
5346  *
5347  *      Return the type of a component for the given object.
5348  *
5349  *  Programmer
5350  *
5351  *      Brad Whitlock, Thu Jan 20 11:54:54 PDT 2000
5352  *
5353  *  Parameters
5354  *
5355  *      dbfile           {In}    {Pointer to current file}
5356  *      objname          {In}    {Name of object to inquire about}
5357  *      compname         {In}    {Name of component to return}
5358  *
5359  *  Modified
5360  *
5361  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5362  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5363  *--------------------------------------------------------------------*/
5364 
5365 PUBLIC int
DBGetComponentType(DBfile * dbfile,char const * objname,char const * compname)5366 DBGetComponentType(DBfile *dbfile, char const *objname, char const *compname)
5367 {
5368     int retval = DB_NOTYPE;
5369 
5370     API_BEGIN2("DBGetComponentType", int, DB_NOTYPE, api_dummy) {
5371         if (!dbfile)
5372             API_ERROR(NULL, E_NOFILE);
5373         if (SILO_Globals.enableGrabDriver == TRUE)
5374             API_ERROR("", E_GRABBED) ;
5375         if (!objname || !*objname)
5376             API_ERROR("object name", E_BADARGS);
5377         if (!compname || !*compname)
5378             API_ERROR("component name", E_BADARGS);
5379         if (!dbfile->pub.g_comptyp)
5380             API_ERROR(dbfile->pub.name, E_NOTIMP);
5381 
5382         retval = (dbfile->pub.g_comptyp) (dbfile, objname, compname);
5383         API_RETURN(retval);
5384     }
5385     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5386 }
5387 
5388 /*----------------------------------------------------------------------
5389  *  Routine                                                     DBGetDir
5390  *
5391  *  Purpose
5392  *
5393  *      Get the name of the current directory, return in space provided.
5394  *
5395  *  Modified
5396  *    Robb Matzke, Tue Nov 8 08:48:12 PST 1994
5397  *    Added error mechanism
5398  *
5399  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
5400  *    I replaced API_END with API_END_NOPOP.
5401  *
5402  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5403  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5404  *--------------------------------------------------------------------*/
5405 PUBLIC int
DBGetDir(DBfile * dbfile,char * path)5406 DBGetDir(DBfile *dbfile, char *path)
5407 {
5408     int retval;
5409 
5410     API_BEGIN2("DBGetDir", int, -1, api_dummy) {
5411         if (!dbfile)
5412             API_ERROR(NULL, E_NOFILE);
5413         if (SILO_Globals.enableGrabDriver == TRUE)
5414             API_ERROR("DBGetDir", E_GRABBED) ;
5415         if (!path)
5416             API_ERROR("path", E_BADARGS);
5417         if (!dbfile->pub.g_dir)
5418             API_ERROR(dbfile->pub.name, E_NOTIMP);
5419 
5420         retval = (dbfile->pub.g_dir) (dbfile, path);
5421         API_RETURN(retval);
5422     }
5423     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5424 }
5425 
5426 /*-------------------------------------------------------------------------
5427  * Function:    DBSetDir
5428  *
5429  * Purpose:     Sets the current directory within the database.
5430  *
5431  * Return:      Success:        0
5432  *
5433  *              Failure:        -1
5434  *
5435  * Programmer:  robb@cloud
5436  *              Wed Nov  9 13:09:23 EST 1994
5437  *
5438  * Modifications:
5439  *    Robb Matzke, Mon Nov 21 21:31:17 EST 1994
5440  *    Added error mechanism.
5441  *
5442  *    Robb Matzke, Fri Jan 6 07:34:29 PST 1995
5443  *    Checkes for changing to `.' since that is a no-op.
5444  *
5445  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
5446  *    I replaced API_END with API_END_NOPOP.
5447  *
5448  *    Robb Matzke, 2000-05-23
5449  *    The old table of contents is discarded if the directory changes.
5450  *
5451  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5452  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5453  *-------------------------------------------------------------------------*/
5454 PUBLIC int
DBSetDir(DBfile * dbfile,const char * path)5455 DBSetDir(DBfile *dbfile, const char *path)
5456 {
5457     char           tmp[256];
5458     int retval;
5459 
5460     API_BEGIN2("DBSetDir", int, -1, api_dummy) {
5461         if (!dbfile)
5462             API_ERROR(NULL, E_NOFILE);
5463         if (SILO_Globals.enableGrabDriver == TRUE)
5464             API_ERROR("DBSetDir", E_GRABBED) ;
5465         if (!path || !*path)
5466             API_ERROR("path", E_BADARGS);
5467         if (STR_EQUAL(path, "."))
5468         {
5469             API_RETURN(0);
5470         }
5471         if (DBGetDir(dbfile, tmp) < 0)
5472             API_ERROR("DBGetDir", E_CALLFAIL);
5473         if (STR_EQUAL(tmp, path))
5474         {
5475             API_RETURN(0);
5476         }
5477         if (!dbfile->pub.cd)
5478             API_ERROR(dbfile->pub.name, E_NOTIMP);
5479 
5480         retval = (dbfile->pub.cd) (dbfile, path);
5481         db_FreeToc(dbfile);
5482         API_RETURN(retval);
5483     }
5484     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5485 }
5486 
5487 /*-------------------------------------------------------------------------
5488  * Function:    DBFilters
5489  *
5490  * Purpose:     List the names of filters installed for the specified
5491  *              file.  The list is sent to the specified stream.
5492  *
5493  * Return:      Success:        0
5494  *
5495  *              Failure:        -1
5496  *
5497  * Programmer:  robb@cloud
5498  *              Tue Mar  7 10:51:58 EST 1995
5499  *
5500  * Modifications:
5501  *
5502  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5503  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5504  *-------------------------------------------------------------------------*/
5505 PUBLIC int
DBFilters(DBfile * dbfile,FILE * stream)5506 DBFilters(DBfile *dbfile, FILE *stream)
5507 {
5508     int retval;
5509 
5510     API_BEGIN2("DBFilters", int, -1, api_dummy) {
5511         if (!dbfile)
5512             API_ERROR(NULL, E_NOFILE);
5513         if (SILO_Globals.enableGrabDriver == TRUE)
5514             API_ERROR("DBFilters", E_GRABBED) ;
5515         if (!stream)
5516             stream = stdout;
5517         if (!dbfile->pub.module)
5518             API_ERROR(dbfile->pub.name, E_NOTIMP);
5519 
5520         retval = (dbfile->pub.module) (dbfile, stream);
5521         API_RETURN(retval);
5522     }
5523     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5524 }
5525 
5526 /*-------------------------------------------------------------------------
5527  * Function:    DBMkDir
5528  *
5529  * Purpose:     Creates a new directory in the database.
5530  *
5531  * Return:      Success:        directory ID
5532  *
5533  *              Failure:        -1
5534  *
5535  * Programmer:  matzke@viper
5536  *              Tue Nov  8 11:46:21 PST 1994
5537  *
5538  * Modifications:
5539  *    Robb Matzke, Mon Nov 21 21:36:44 EST 1994
5540  *    Added error mechanism.
5541  *
5542  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
5543  *    I replaced API_END with API_END_NOPOP.
5544  *
5545  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
5546  *    Added a check for variable name validity.
5547  *
5548  *    Robb Matzke, 2000-05-23
5549  *    The old table of contents is discarded if the directory changes.
5550  *
5551  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5552  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5553  *-------------------------------------------------------------------------*/
5554 PUBLIC int
DBMkDir(DBfile * dbfile,const char * name)5555 DBMkDir(DBfile *dbfile, const char *name)
5556 {
5557     int retval;
5558 
5559     API_BEGIN2("DBMkDir", int, -1, api_dummy) {
5560         if (!dbfile)
5561             API_ERROR(NULL, E_NOFILE);
5562         if (SILO_Globals.enableGrabDriver == TRUE)
5563             API_ERROR("DBMkDir", E_GRABBED) ;
5564         if (!name || !*name)
5565             API_ERROR("directory name", E_BADARGS);
5566         if (db_VariableNameValid(name) == 0)
5567             API_ERROR("directory name", E_INVALIDNAME);
5568         if (!dbfile->pub.mkdir)
5569             API_ERROR(dbfile->pub.name, E_NOTIMP);
5570 
5571         retval = (dbfile->pub.mkdir) (dbfile, name);
5572         db_FreeToc(dbfile);
5573         API_RETURN(retval);
5574     }
5575     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5576 }
5577 
5578 
5579 /*-------------------------------------------------------------------------
5580  * Function:    DBCpDir
5581  *
5582  * Purpose:     Copies a directory tree from one file to another
5583  *
5584  * Return:      Success:        directory ID
5585  *
5586  *              Failure:        -1
5587  *
5588  * Programmer:  Mark C. Miller, Wed Aug  6 15:14:33 PDT 2008
5589  *
5590  *-------------------------------------------------------------------------*/
5591 PUBLIC int
DBCpDir(DBfile * dbfile,const char * srcDir,DBfile * dstFile,const char * dstDir)5592 DBCpDir(DBfile *dbfile, const char *srcDir,
5593         DBfile *dstFile, const char *dstDir)
5594 {
5595     int retval;
5596 
5597     API_BEGIN2("DBCpDir", int, -1, api_dummy) {
5598         if (!dbfile)
5599             API_ERROR(NULL, E_NOFILE);
5600         if (!dstFile)
5601             API_ERROR(NULL, E_NOFILE);
5602         if (db_isregistered_file(dstFile,0)==-1)
5603             API_ERROR(NULL, E_NOTREG);
5604         if (SILO_Globals.enableGrabDriver == TRUE)
5605             API_ERROR(NULL, E_GRABBED) ;
5606         if (!srcDir || !*srcDir)
5607             API_ERROR("source directory name", E_BADARGS);
5608         if (!dstDir || !*dstDir)
5609             API_ERROR("destination directory name", E_BADARGS);
5610         if (db_VariableNameValid(dstDir) == 0)
5611             API_ERROR("destination directory name", E_INVALIDNAME);
5612         if (!dbfile->pub.cpdir)
5613             API_ERROR(dbfile->pub.name, E_NOTIMP);
5614 
5615         retval = (dbfile->pub.cpdir) (dbfile, srcDir, dstFile, dstDir);
5616         db_FreeToc(dbfile);
5617         API_RETURN(retval);
5618     }
5619     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5620 }
5621 
5622 /*-------------------------------------------------------------------------
5623  * Function:    DBChangeObject
5624  *
5625  * Purpose:     Overwrites an object with a new object.  This is usually
5626  *              the same function as called by DBWriteObject but with
5627  *              OVER_WRITE as the flag.  However, we keep it as a separate
5628  *              callback so existing drivers that don't support overwriting
5629  *              don't need to be changed and so that the silo API doesn't
5630  *              change by changing the meaning of the `freemem' argument
5631  *              to DBWriteObject.
5632  *
5633  * Return:      Success:        0
5634  *
5635  *              Failure:        -1
5636  *
5637  * Programmer:  Robb Matzke
5638  *              robb@maya.nuance.mdn.com
5639  *              Mar  7 1997
5640  *
5641  * Modifications:
5642  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
5643  *    Completely reformatted the code so a human can read it.  Made the error
5644  *    messages a little better.
5645  *
5646  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5647  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5648  *-------------------------------------------------------------------------*/
5649 PUBLIC int
DBChangeObject(DBfile * dbfile,DBobject const * obj)5650 DBChangeObject (DBfile *dbfile, DBobject const *obj)
5651 {
5652     int             retval;
5653 
5654     API_BEGIN2("DBChangeObject", int, -1, api_dummy)
5655     {
5656         if (!dbfile)
5657             API_ERROR(NULL, E_NOFILE);
5658         if (SILO_Globals.enableGrabDriver == TRUE)
5659             API_ERROR("DBChangeObject", E_GRABBED) ;
5660         if (!obj)
5661             API_ERROR("object pointer", E_BADARGS);
5662         if (!dbfile->pub.c_obj)
5663             API_ERROR(dbfile->pub.name, E_NOTIMP);
5664         retval = (dbfile->pub.c_obj) (dbfile, obj, OVER_WRITE);
5665         API_RETURN(retval);
5666     }
5667     API_END_NOPOP;                     /* BEWARE: If API_RETURN is removed
5668                                         * use API_END */
5669 }
5670 
5671 /*-------------------------------------------------------------------------
5672  * Function:    DBWriteObject
5673  *
5674  * Purpose:     Write an object into the data file.
5675  *
5676  * Return:      Success:        0
5677  *
5678  *              Failure:        -1
5679  *
5680  * Programmer:  matzke@viper
5681  *              Mon Nov  7 10:45:14 PST 1994
5682  *
5683  * Modifications:
5684  *    Robb Matzke, Mon Nov 21 21:37:54 EST 1994
5685  *    Added error mechanism.
5686  *
5687  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
5688  *    I replaced API_END with API_END_NOPOP.
5689  *
5690  *    Robb Matzke, 7 Mar 1997
5691  *    The freemem value passed to the driver is either FREE_MEM or zero
5692  *    so that drivers that overload this function with DBChangeObject
5693  *    are guaranteed to be able to tell the difference.
5694  *
5695  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
5696  *    Made the error messages a little better.
5697  *
5698  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5699  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5700  *-------------------------------------------------------------------------*/
5701 PUBLIC int
DBWriteObject(DBfile * dbfile,DBobject const * obj,int freemem)5702 DBWriteObject(DBfile *dbfile, DBobject const *obj, int freemem)
5703 {
5704     int retval;
5705 
5706     API_BEGIN2("DBWriteObject", int, -1, api_dummy)
5707     {
5708         if (!dbfile)
5709             API_ERROR(NULL, E_NOFILE);
5710         if (SILO_Globals.enableGrabDriver == TRUE)
5711             API_ERROR("DBWriteObject", E_GRABBED) ;
5712         if (!obj)
5713             API_ERROR("object pointer", E_BADARGS);
5714         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, obj->name))
5715             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
5716         if (!dbfile->pub.w_obj)
5717             API_ERROR(dbfile->pub.name, E_NOTIMP);
5718 
5719         retval = (dbfile->pub.w_obj) (dbfile, obj, freemem?FREE_MEM:0);
5720         API_RETURN(retval);
5721     }
5722     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5723 }
5724 
5725 /*-------------------------------------------------------------------------
5726  * Function:    DBGetObject
5727  *
5728  * Purpose:     Reads an object from a file.
5729  *
5730  * Return:      Success:        Ptr to the new object.
5731  *
5732  *              Failure:        NULL
5733  *
5734  * Programmer:  Robb Matzke
5735  *              matzke@viper.llnl.gov
5736  *              Dec  2 1996
5737  *
5738  * Modifications:
5739  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
5740  *    Added a check for variable name validity.
5741  *
5742  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
5743  *    Made the error messages a little better.
5744  *
5745  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5746  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5747  *-------------------------------------------------------------------------*/
5748 PUBLIC DBobject *
DBGetObject(DBfile * dbfile,char const * objname)5749 DBGetObject (DBfile *dbfile, char const *objname)
5750 {
5751     DBobject       *retval = NULL;
5752 
5753     API_BEGIN2("DBGetObject", DBobject *, NULL, api_dummy)
5754     {
5755         if (!dbfile)
5756             API_ERROR(NULL, E_NOFILE);
5757         if (SILO_Globals.enableGrabDriver == TRUE)
5758             API_ERROR("DBGetObject", E_GRABBED) ;
5759         if (!objname)
5760             API_ERROR("object name", E_BADARGS);
5761         if (!dbfile->pub.g_obj)
5762             API_ERROR(dbfile->pub.name, E_NOTIMP);
5763         retval = (dbfile->pub.g_obj) (dbfile, (char const *)objname);
5764         db_AdjustSpeciallyHandledStandardObjectComponentValues(retval);
5765         API_RETURN(retval);
5766     }
5767     API_END_NOPOP;                     /* BEWARE:  If API_RETURN above is
5768                                         * removed use API_END */
5769 }
5770 
5771 /*-------------------------------------------------------------------------
5772  * Function:    DBWriteComponent
5773  *
5774  * Purpose:     Add a variable component to the given object structure, AND
5775  *              write out the associated data.
5776  *
5777  * Return:      Success:        0
5778  *
5779  *              Failure:        -1
5780  *
5781  * Programmer:  matzke@viper
5782  *              Mon Nov  7 10:47:29 PST 1994
5783  *
5784  * Modifications:
5785  *    Robb Matzke, Mon Nov 21 21:39:06 EST 1994
5786  *    Added error mechanism.
5787  *
5788  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
5789  *    I replaced API_END with API_END_NOPOP.
5790  *
5791  *    Sean Ahern, Tue Mar 31 17:16:24 PST 1998
5792  *    I added a check for zero-length data arrays.
5793  *
5794  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
5795  *    Added a check for variable name validity.
5796  *
5797  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
5798  *    Made the error messages a little better.
5799  *
5800  *    Robb Matzke, 2000-05-23
5801  *    The old table of contents is discarded if the directory changes.
5802  *
5803  *    Mark C. Miller, Wed Jul 23 00:15:15 PDT 2008
5804  *    Changed to API_BEGIN2 to help detect attempted ops on closed files.
5805  *-------------------------------------------------------------------------*/
5806 PUBLIC int
DBWriteComponent(DBfile * dbfile,DBobject * obj,char const * comp_name,char const * prefix,char const * datatype,void const * var,int nd,long const * count)5807 DBWriteComponent(DBfile *dbfile, DBobject *obj, char const *comp_name,
5808                  char const *prefix, char const *datatype, void const *var, int nd,
5809                  long const *count)
5810 {
5811     int retval;
5812     int nvals, i;
5813 
5814     API_BEGIN2("DBWriteComponent", int, -1, api_dummy) {
5815         if (!dbfile)
5816             API_ERROR(NULL, E_NOFILE);
5817         if (SILO_Globals.enableGrabDriver == TRUE)
5818             API_ERROR("DBWriteComponent", E_GRABBED) ;
5819         if (!obj)
5820             API_ERROR("object pointer", E_BADARGS);
5821         if (SILO_Globals.allowEmptyObjects)
5822         {
5823             if (nd<=0) API_RETURN(0);
5824             if (!count) API_RETURN(0);
5825             if (!var) API_RETURN(0);
5826             for(nvals=1,i=0;i<nd;i++)
5827                 nvals *= count[i];
5828             if (nvals<=0) API_RETURN(0);
5829         }
5830         if (!comp_name || !*comp_name)
5831             API_ERROR("component name", E_BADARGS);
5832         if (db_VariableNameValid((char *)comp_name) == 0)
5833             API_ERROR("component name", E_INVALIDNAME);
5834 #if 0
5835         /* We don't know what name to pass to DBInqVarExists here because it
5836            is the driver that knows how to construct component names */
5837         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, obj->name))
5838             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
5839 #endif
5840         if (!prefix || !*prefix)
5841             API_ERROR("prefix", E_BADARGS);
5842         if (db_VariableNameValid((char *)prefix) == 0)
5843             API_ERROR("prefix", E_INVALIDNAME);
5844         if (!datatype || !*datatype)
5845             API_ERROR("data type", E_BADARGS);
5846         if (!var)
5847             API_ERROR("var pointer", E_BADARGS);
5848         if (nd <= 0)
5849             API_ERROR("nd", E_BADARGS);
5850         if (!count && nd)
5851             API_ERROR("count", E_BADARGS);
5852         for(nvals=1,i=0;i<nd;i++)
5853         {
5854             nvals *= count[i];
5855         }
5856         if (nvals == 0) {
5857             API_ERROR("Zero-length write attempted", E_BADARGS);
5858         }
5859         if (!dbfile->pub.w_comp)
5860             API_ERROR(dbfile->pub.name, E_NOTIMP);
5861 
5862         /* Note that the work to add the variable component to the object is
5863            handled down in the drivers due to the fact that the drivers may
5864            use different rules to construct the object component names */
5865 
5866         retval = (dbfile->pub.w_comp) (dbfile, obj, comp_name, prefix,
5867                                        datatype, var, nd, count);
5868         db_FreeToc(dbfile);
5869         API_RETURN(retval);
5870     }
5871     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5872 }
5873 
5874 /*-------------------------------------------------------------------------
5875  * Function:    DBWrite
5876  *
5877  * Purpose:     Writes a single variable into the database.
5878  *
5879  * Return:      Success:        0
5880  *
5881  *              Failure:        -1
5882  *
5883  * Programmer:  robb@cloud
5884  *              Wed Nov  9 13:19:49 EST 1994
5885  *
5886  * Modifications:
5887  *    Robb Matzke, Mon Nov 21 21:42:27 EST 1994
5888  *    Added error mecanism.
5889  *
5890  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
5891  *    I replaced API_END with API_END_NOPOP.
5892  *
5893  *    Sean Ahern, Tue Mar 31 17:17:44 PST 1998
5894  *    I added a check for zero-length arrays.
5895  *
5896  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
5897  *    Added a check for variable name validity.
5898  *
5899  *    Robb Matzke, 2000-05-23
5900  *    The old table of contents is discarded if the directory changes.
5901  *
5902  *    Mark C. Miller, Mon Jan 11 17:42:51 PST 2010
5903  *    Allow special variable names in the magic /.silo dir for HDF5 files.
5904  *-------------------------------------------------------------------------*/
5905 PUBLIC int
DBWrite(DBfile * dbfile,char const * vname,void const * var,int const * dims,int ndims,int datatype)5906 DBWrite(DBfile *dbfile, char const *vname, void const *var, int const *dims,
5907     int ndims, int datatype)
5908 {
5909     int retval;
5910     int nvals, i;
5911 
5912     API_BEGIN2("DBWrite", int, -1, vname) {
5913         if (!dbfile)
5914             API_ERROR(NULL, E_NOFILE);
5915         if (SILO_Globals.enableGrabDriver == TRUE)
5916             API_ERROR("DBWrite", E_GRABBED) ;
5917         if (!vname || !*vname)
5918             API_ERROR("variable name", E_BADARGS);
5919         if (strncmp("/.silo/#", vname, 8) != 0 &&
5920             db_VariableNameValid(vname) == 0)
5921             API_ERROR("variable name", E_INVALIDNAME);
5922         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, vname))
5923             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
5924         if (ndims <= 0)
5925             API_ERROR("ndims", E_BADARGS);
5926         if (!dims && ndims)
5927             API_ERROR("dims", E_BADARGS);
5928         for(nvals=1,i=0;i<ndims;i++)
5929         {
5930             nvals *= dims[i];
5931         }
5932         if (nvals == 0)
5933             API_ERROR("Zero length write attempted", E_BADARGS);
5934         if (db_FullyDeprecatedConvention(vname))
5935             API_ERROR(dbfile->pub.name, E_NOTIMP);
5936         if (!dbfile->pub.write)
5937             API_ERROR(dbfile->pub.name, E_NOTIMP);
5938 
5939         retval = (dbfile->pub.write) (dbfile, vname, var, dims,
5940                                       ndims, datatype);
5941         db_FreeToc(dbfile);
5942         API_RETURN(retval);
5943     }
5944     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
5945 }
5946 
5947 /*-------------------------------------------------------------------------
5948  * Function:    DBWriteSlice
5949  *
5950  * Purpose:     Similar to DBWrite except only part of the data is
5951  *              written.  If VNAME doesn't exist, space is reserved for
5952  *              the entire variable based on DIMS; otherwise we check
5953  *              that DIMS has the same value as originally.  Then we
5954  *              write the specified slice to the file.
5955  *
5956  * Return:      Success:        0
5957  *
5958  *              Failure:        -1
5959  *
5960  * Programmer:  Robb Matzke
5961  *              robb@callisto.nuance.com
5962  *              May  9, 1996
5963  *
5964  * Modifications:
5965  *    Sean Ahern, Tue Mar 31 17:19:38 PST 1998
5966  *    I added a check for zero-length writes.
5967  *
5968  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
5969  *    Added a check for variable name validity.
5970  *
5971  *    Robb Matzke, 2000-05-23
5972  *    The old table of contents is discarded if the directory changes.
5973  *-------------------------------------------------------------------------*/
5974 PUBLIC int
DBWriteSlice(DBfile * dbfile,const char * vname,void const * values,int dtype,int const * offset,int const * length,int const * stride,int const * dims,int ndims)5975 DBWriteSlice (DBfile *dbfile, const char *vname, void const *values, int dtype,
5976               int const *offset, int const *length, int const *stride, int const *dims,
5977               int ndims)
5978 {
5979     int retval;
5980     int nvals,i;
5981 
5982     API_BEGIN2("DBWriteSlice", int, -1, vname)
5983     {
5984         if (!dbfile)
5985             API_ERROR(NULL, E_NOFILE);
5986         if (SILO_Globals.enableGrabDriver == TRUE)
5987             API_ERROR("DBWriteSlice", E_GRABBED) ;
5988         if (!vname || !*vname)
5989             API_ERROR("variable name", E_BADARGS);
5990         if (db_VariableNameValid(vname) == 0)
5991             API_ERROR("variable name", E_INVALIDNAME);
5992         if (!values)
5993             API_ERROR("values", E_BADARGS);
5994         if (!offset)
5995             API_ERROR("offset", E_BADARGS);
5996         if (!length)
5997             API_ERROR("length", E_BADARGS);
5998         if (!stride)
5999             API_ERROR("stride", E_BADARGS);
6000         if (!dims)
6001             API_ERROR("dims", E_BADARGS);
6002         if (ndims <= 0 || ndims > 3)
6003             API_ERROR("ndims", E_BADARGS);
6004         for(nvals=1,i=0;i<ndims;i++)
6005         {
6006             nvals *= length[i];
6007         }
6008         if (nvals == 0)
6009             API_ERROR("Zero-length write attempted", E_BADARGS);
6010         if (!dbfile->pub.writeslice)
6011             API_ERROR(dbfile->pub.name, E_NOTIMP);
6012 
6013         retval = (dbfile->pub.writeslice) (dbfile, vname, values,
6014                                            dtype, offset, length, stride,
6015                                            dims, ndims);
6016         db_FreeToc(dbfile);
6017         API_RETURN(retval);
6018     }
6019     API_END_NOPOP;     /* BEWARE: If API_RETURN above is removed use API_END */
6020 }
6021 
6022 /*-------------------------------------------------------------------------
6023  * Function:    DBGetCompoundarray
6024  *
6025  * Purpose:     Read a compound array object from the file.
6026  *
6027  * Return:      Success:        pointer to fresh compound array obj.
6028  *
6029  *              Failure:        NULL
6030  *
6031  * Programmer:  matzke@viper
6032  *              Mon Nov  7 10:50:29 PST 1994
6033  *
6034  * Modifications:
6035  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6036  *    I replaced API_END with API_END_NOPOP.
6037  *
6038  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6039  *    Added a check for variable name validity.
6040  *-------------------------------------------------------------------------*/
6041 PUBLIC DBcompoundarray *
DBGetCompoundarray(DBfile * dbfile,char const * name)6042 DBGetCompoundarray(DBfile *dbfile, char const *name)
6043 {
6044     DBcompoundarray *retval = NULL;
6045 
6046     API_BEGIN2("DBGetCompoundarray", DBcompoundarray *, NULL, name) {
6047         if (!dbfile)
6048             API_ERROR(NULL, E_NOFILE);
6049         if (SILO_Globals.enableGrabDriver == TRUE)
6050             API_ERROR("DBGetCompoundarray", E_GRABBED) ;
6051         if (!name || !*name)
6052             API_ERROR("array name", E_BADARGS);
6053         if (NULL == dbfile->pub.g_ca)
6054             API_ERROR(dbfile->pub.name, E_NOTIMP);
6055 
6056         retval = (dbfile->pub.g_ca) (dbfile, name);
6057         API_RETURN(retval);
6058     }
6059     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6060 }
6061 
6062 /*-------------------------------------------------------------------------
6063  * Function:    DBGetCurve
6064  *
6065  * Purpose:     Read a curve object from the file.
6066  *
6067  * Return:      Success:        pointer to fresh curve obj
6068  *
6069  *              Failure:        NULL
6070  *
6071  * Programmer:  Robb Matzke
6072  *              robb@callisto.nuance.com
6073  *              May 16, 1996
6074  *
6075  * Modifications:
6076  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6077  *    Added a check for variable name validity.
6078  *-------------------------------------------------------------------------*/
6079 PUBLIC DBcurve *
DBGetCurve(DBfile * dbfile,char const * name)6080 DBGetCurve (DBfile *dbfile, char const *name)
6081 {
6082     DBcurve *retval = NULL;
6083 
6084     API_BEGIN2("DBGetCurve", DBcurve *, NULL, name)
6085     {
6086         if (!dbfile)
6087             API_ERROR(NULL, E_NOFILE);
6088         if (SILO_Globals.enableGrabDriver == TRUE)
6089             API_ERROR("DBGetCurve", E_GRABBED) ;
6090         if (!name || !*name)
6091             API_ERROR("curve name", E_BADARGS);
6092         if (NULL == dbfile->pub.g_cu)
6093             API_ERROR(dbfile->pub.name, E_NOTIMP);
6094 
6095         retval = (dbfile->pub.g_cu) (dbfile, name);
6096         API_RETURN(retval);
6097     }
6098     API_END_NOPOP;  /* BEWARE: If API_RETURN above is removed use API_END */
6099 }
6100 
6101 /*-------------------------------------------------------------------------
6102  * Function:    DBGetDefvars
6103  *
6104  * Purpose:     Read a defvars object from the file.
6105  *
6106  * Return:      Success:        pointer to fresh defvars obj
6107  *
6108  *              Failure:        NULL
6109  *
6110  * Programmer:  Mark C. Miller
6111  *              August 8, 2005
6112  *
6113  *-------------------------------------------------------------------------*/
6114 PUBLIC DBdefvars *
DBGetDefvars(DBfile * dbfile,const char * name)6115 DBGetDefvars (DBfile *dbfile, const char *name)
6116 {
6117     DBdefvars *retval = NULL;
6118 
6119     API_BEGIN2("DBGetDefvars", DBdefvars *, NULL, name)
6120     {
6121         if (!dbfile)
6122             API_ERROR(NULL, E_NOFILE);
6123         if (SILO_Globals.enableGrabDriver == TRUE)
6124             API_ERROR("DBGetDefvars", E_GRABBED) ;
6125         if (!name || !*name)
6126             API_ERROR("defvars name", E_BADARGS);
6127         if (NULL == dbfile->pub.g_defv)
6128             API_ERROR(dbfile->pub.name, E_NOTIMP);
6129 
6130         retval = (dbfile->pub.g_defv) (dbfile, name);
6131         API_RETURN(retval);
6132     }
6133     API_END_NOPOP;  /* BEWARE: If API_RETURN above is removed use API_END */
6134 }
6135 
6136 /*-------------------------------------------------------------------------
6137  * Function:    DBGetMaterial
6138  *
6139  * Purpose:     Allocates a DBmaterial data structure, reads material data
6140  *              from the database, and returns a pointer to that struct.
6141  *
6142  * Return:      Success:        pointer to a new DBmaterial structure
6143  *
6144  *              Failure:        NULL
6145  *
6146  * Programmer:  matzke@viper
6147  *              Tue Nov  8 09:32:17 PST 1994
6148  *
6149  * Modifications:
6150  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6151  *    I replaced API_END with API_END_NOPOP.
6152  *
6153  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6154  *    Added a check for variable name validity.
6155  *-------------------------------------------------------------------------*/
6156 PUBLIC DBmaterial *
DBGetMaterial(DBfile * dbfile,const char * name)6157 DBGetMaterial(DBfile *dbfile, const char *name)
6158 {
6159     DBmaterial *retval = NULL;
6160 
6161     API_BEGIN2("DBGetMaterial", DBmaterial *, NULL, name) {
6162         if (!dbfile)
6163             API_ERROR(NULL, E_NOFILE);
6164         if (SILO_Globals.enableGrabDriver == TRUE)
6165             API_ERROR("DBGetMaterial", E_GRABBED) ;
6166         if (!name || !*name)
6167             API_ERROR("material name", E_BADARGS);
6168         if (!dbfile->pub.g_ma)
6169             API_ERROR(dbfile->pub.name, E_NOTIMP);
6170 
6171         retval = (dbfile->pub.g_ma) (dbfile, name);
6172         API_RETURN(retval);
6173     }
6174     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6175 }
6176 
6177 /*----------------------------------------------------------------------
6178  *  Routine                                             DBGetMatspecies
6179  *
6180  *  Purpose
6181  *
6182  *      Read a matspecies-data structure from the given database.
6183  *
6184  *  Programmer
6185  *
6186  *      Jeffery W. Long, NSSD-B
6187  *
6188  *  Parameters
6189  *
6190  *      DBGetMatspecies {Out}    {Pointer to matspecies structure}
6191  *      dbfile           {In}    {Pointer to current file}
6192  *      name             {In}    {Name of matspecies-data to read}
6193  *
6194  *  Notes
6195  *
6196  *  Modifications
6197  *    Al Leibee, Tue Jul 26 08:44:01 PDT 1994
6198  *    Replaced composition by species.
6199  *
6200  *    Robb Matzke, Tue Nov 29 13:21:27 PST 1994
6201  *    Modified for device independence.  Added error mechanism.
6202  *
6203  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6204  *    I replaced API_END with API_END_NOPOP.
6205  *
6206  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6207  *    Added a check for variable name validity.
6208  *
6209  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6210  *    Made the error messages a little better.
6211  *--------------------------------------------------------------------*/
6212 PUBLIC DBmatspecies *
DBGetMatspecies(DBfile * dbfile,const char * name)6213 DBGetMatspecies(DBfile *dbfile, const char *name)
6214 {
6215     DBmatspecies *retval = NULL;
6216 
6217     API_BEGIN2("DBGetMatspecies", DBmatspecies *, NULL, name) {
6218         if (!dbfile)
6219             API_ERROR(NULL, E_NOFILE);
6220         if (SILO_Globals.enableGrabDriver == TRUE)
6221             API_ERROR("DBGetMatspecies", E_GRABBED) ;
6222         if (!name || !*name)
6223             API_ERROR("material species name", E_BADARGS);
6224         if (!dbfile->pub.g_ms)
6225             API_ERROR(dbfile->pub.name, E_NOTIMP);
6226 
6227         retval = (dbfile->pub.g_ms) (dbfile, name);
6228         API_RETURN(retval);
6229     }
6230     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6231 }
6232 
6233 /*-------------------------------------------------------------------------
6234  * Function:    DBGetMultimesh
6235  *
6236  * Purpose:     Allocates a DBmultimesh data structure, reads a multi-block
6237  *              mesh from the database, and returns a pointer to the
6238  *              new structure.
6239  *
6240  * Return:      Success:        pointer to the new DBmultimesh
6241  *
6242  *              Failure:        NULL
6243  *
6244  * Programmer:  matzke@viper
6245  *              Tue Nov  8 09:35:38 PST 1994
6246  *
6247  * Modifications:
6248  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6249  *    I replaced API_END with API_END_NOPOP.
6250  *
6251  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6252  *    Added a check for variable name validity.
6253  *
6254  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6255  *    Made the error messages a little better.
6256  *-------------------------------------------------------------------------*/
6257 PUBLIC DBmultimesh *
DBGetMultimesh(DBfile * dbfile,const char * name)6258 DBGetMultimesh(DBfile *dbfile, const char *name)
6259 {
6260     DBmultimesh * retval = NULL;
6261 
6262     API_BEGIN2("DBGetMultimesh", DBmultimesh *, NULL, name) {
6263         if (!dbfile)
6264             API_ERROR(NULL, E_NOFILE);
6265         if (SILO_Globals.enableGrabDriver == TRUE)
6266             API_ERROR("DBGetMultimesh", E_GRABBED) ;
6267         if (!name || !*name)
6268             API_ERROR("multimesh name", E_BADARGS);
6269         if (!dbfile->pub.g_mm)
6270             API_ERROR(dbfile->pub.name, E_NOTIMP);
6271 
6272         retval = (dbfile->pub.g_mm) (dbfile, name);
6273         API_RETURN(retval);
6274     }
6275     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6276 }
6277 
6278 /*-------------------------------------------------------------------------
6279  * Function:    DBGetMultimeshadj
6280  *
6281  * Purpose:     Allocates a DBmultimeshdj data structure, reads a
6282  *              multi-block mesh adjacency object from the database, and
6283  *              returns a pointer to the new structure.
6284  *
6285  * Return:      Success:        pointer to the new DBmultimeshadj
6286  *
6287  *              Failure:        NULL
6288  *
6289  * Programmer:  Mark C. Miller
6290  *              August 24, 2005
6291  *
6292  *-------------------------------------------------------------------------*/
6293 PUBLIC DBmultimeshadj *
DBGetMultimeshadj(DBfile * dbfile,const char * name,int nmesh,const int * block_map)6294 DBGetMultimeshadj(DBfile *dbfile, const char *name, int nmesh,
6295    const int *block_map)
6296 {
6297     DBmultimeshadj * retval = NULL;
6298 
6299     API_BEGIN2("DBGetMultimeshadj", DBmultimeshadj *, NULL, name) {
6300         if (!dbfile)
6301             API_ERROR(NULL, E_NOFILE);
6302         if (SILO_Globals.enableGrabDriver == TRUE)
6303             API_ERROR("DBGetMultimeshadj", E_GRABBED) ;
6304         if (!name || !*name)
6305             API_ERROR("multimesh name", E_BADARGS);
6306         if (!dbfile->pub.g_mmadj)
6307             API_ERROR(dbfile->pub.name, E_NOTIMP);
6308 
6309         retval = (dbfile->pub.g_mmadj) (dbfile, name, nmesh,
6310                                         block_map);
6311         API_RETURN(retval);
6312     }
6313     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6314 }
6315 
6316 
6317 
6318 
6319 
6320 /*-------------------------------------------------------------------------
6321  * Function:    DBGetMultivar
6322  *
6323  * Purpose:     Allocates a DBmultivar data structure, reads a multi-block
6324  *              variable from the database, and returns a pointer to the
6325  *              new structure.
6326  *
6327  * Return:      Success:        pointer to the new DBmultivar
6328  *
6329  *              Failure:        NULL
6330  *
6331  * Programmer:  matzke@cloud
6332  *              Tue Feb 21 11:27:46 EST 1995
6333  *
6334  * Modifications:
6335  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6336  *    Added a check for variable name validity.
6337  *
6338  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6339  *    Made the error messages a little better.
6340  *-------------------------------------------------------------------------*/
6341 PUBLIC DBmultivar *
DBGetMultivar(DBfile * dbfile,const char * name)6342 DBGetMultivar(DBfile *dbfile, const char *name)
6343 {
6344     DBmultivar * retval = NULL;
6345 
6346     API_BEGIN2("DBGetMultivar", DBmultivar *, NULL, name) {
6347         if (!dbfile)
6348             API_ERROR(NULL, E_NOFILE);
6349         if (SILO_Globals.enableGrabDriver == TRUE)
6350             API_ERROR("DBGetMultivar", E_GRABBED) ;
6351         if (!name || !*name)
6352             API_ERROR("multivar name", E_BADARGS);
6353         if (!dbfile->pub.g_mv)
6354             API_ERROR(dbfile->pub.name, E_NOTIMP);
6355 
6356         retval = (dbfile->pub.g_mv) (dbfile, name);
6357         API_RETURN(retval);
6358     }
6359     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6360 }
6361 
6362 /*-------------------------------------------------------------------------
6363  * Function:    DBGetMultimat
6364  *
6365  * Purpose:     Allocates a DBmultimat data structure, reads a multi-
6366  *              material from the database, and returns a pointer to the
6367  *              new structure.
6368  *
6369  * Return:      Success:        pointer to the new DBmultimat
6370  *
6371  *              Failure:        NULL
6372  *
6373  * Programmer:  matzke@cloud
6374  *              Tue Feb 21 11:27:46 EST 1995
6375  *
6376  * Modifications:
6377  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6378  *    Added a check for variable name validity.
6379  *
6380  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6381  *    Made the error messages a little better.
6382  *-------------------------------------------------------------------------*/
6383 PUBLIC DBmultimat *
DBGetMultimat(DBfile * dbfile,const char * name)6384 DBGetMultimat(DBfile *dbfile, const char *name)
6385 {
6386     DBmultimat * retval = NULL;
6387 
6388     API_BEGIN2("DBGetMultimat", DBmultimat *, NULL, name) {
6389         if (!dbfile)
6390             API_ERROR(NULL, E_NOFILE);
6391         if (SILO_Globals.enableGrabDriver == TRUE)
6392             API_ERROR("DBGetMultimat", E_GRABBED) ;
6393         if (!name || !*name)
6394             API_ERROR("multimat name", E_BADARGS);
6395         if (!dbfile->pub.g_mt)
6396             API_ERROR(dbfile->pub.name, E_NOTIMP);
6397 
6398         retval = (dbfile->pub.g_mt) (dbfile, name);
6399         API_RETURN(retval);
6400     }
6401     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6402 }
6403 
6404 /*-------------------------------------------------------------------------
6405  * Function:    DBGetMultimatspecies
6406  *
6407  * Purpose:     Allocates a DBmultimatspecies data structure, reads a
6408  *              multi-material-species from the database, and returns
6409  *              a pointer to the new structure.
6410  *
6411  * Return:      Success:        pointer to the new DBmultimatspecies
6412  *
6413  *              Failure:        NULL
6414  *
6415  * Programmer:  Jeremy S. Meredith
6416  *              Sept 17 1998
6417  *
6418  * Modifications:
6419  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6420  *    Added a check for variable name validity.
6421  *
6422  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6423  *    Made the error messages a little better.
6424  *-------------------------------------------------------------------------*/
6425 PUBLIC DBmultimatspecies *
DBGetMultimatspecies(DBfile * dbfile,const char * name)6426 DBGetMultimatspecies(DBfile *dbfile, const char *name)
6427 {
6428     DBmultimatspecies * retval = NULL;
6429 
6430     API_BEGIN2("DBGetMultimatspecies", DBmultimatspecies *, NULL, name) {
6431         if (!dbfile)
6432             API_ERROR(NULL, E_NOFILE);
6433         if (SILO_Globals.enableGrabDriver == TRUE)
6434             API_ERROR("DBGetMultimatspecies", E_GRABBED) ;
6435         if (!name || !*name)
6436             API_ERROR("multimatspecies name", E_BADARGS);
6437         if (!dbfile->pub.g_mms)
6438             API_ERROR(dbfile->pub.name, E_NOTIMP);
6439 
6440         retval = (dbfile->pub.g_mms) (dbfile, name);
6441         API_RETURN(retval);
6442     }
6443     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6444 }
6445 
6446 /*-------------------------------------------------------------------------
6447  * Function:    DBGetPointmesh
6448  *
6449  * Purpose:     Allocates a DBpointmesh data structure and reads a point
6450  *              mesh from the database.
6451  *
6452  * Return:      Success:        pointer to the new DBpointmesh struct.
6453  *
6454  *              Failure:        NULL
6455  *
6456  * Programmer:  matzke@viper
6457  *              Tue Nov  8 09:37:55 PST 1994
6458  *
6459  * Modifications:
6460  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6461  *    I replaced API_END with API_END_NOPOP.
6462  *
6463  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6464  *    Added a check for variable name validity.
6465  *
6466  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6467  *    Made the error messages a little better.
6468  *-------------------------------------------------------------------------*/
6469 PUBLIC DBpointmesh *
DBGetPointmesh(DBfile * dbfile,const char * name)6470 DBGetPointmesh(DBfile *dbfile, const char *name)
6471 {
6472     DBpointmesh * retval = NULL;
6473 
6474     API_BEGIN2("DBGetPointmesh", DBpointmesh *, NULL, name) {
6475         if (!dbfile)
6476             API_ERROR(NULL, E_NOFILE);
6477         if (SILO_Globals.enableGrabDriver == TRUE)
6478             API_ERROR("DBGetPointmesh", E_GRABBED) ;
6479         if (!name || !*name)
6480             API_ERROR("pointmesh name", E_BADARGS);
6481         if (!dbfile->pub.g_pm)
6482             API_ERROR(dbfile->pub.name, E_NOTIMP);
6483 
6484         retval = (dbfile->pub.g_pm) (dbfile, name);
6485         API_RETURN(retval);
6486     }
6487     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6488 }
6489 
6490 /*-------------------------------------------------------------------------
6491  * Function:    DBGetPointvar
6492  *
6493  * Purpose:     Allocates a DBmeshvar data structure and reads a variable
6494  *              associated with a point mesh from the database.
6495  *
6496  * Return:      Success:        pointer to the new DBmeshvar struct
6497  *
6498  *              Failure:        NULL
6499  *
6500  * Programmer:  matzke@viper
6501  *              Tue Nov  8 09:41:21 PST 1994
6502  *
6503  * Modifications:
6504  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6505  *    I replaced API_END with API_END_NOPOP.
6506  *
6507  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6508  *    Added a check for variable name validity.
6509  *
6510  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6511  *    Made the error messages a little better.
6512  *-------------------------------------------------------------------------*/
6513 PUBLIC DBmeshvar *
DBGetPointvar(DBfile * dbfile,const char * name)6514 DBGetPointvar(DBfile *dbfile, const char *name)
6515 {
6516     DBmeshvar * retval = NULL;
6517 
6518     API_BEGIN2("DBGetPointvar", DBmeshvar *, NULL, name) {
6519         if (!dbfile)
6520             API_ERROR(NULL, E_NOFILE);
6521         if (SILO_Globals.enableGrabDriver == TRUE)
6522             API_ERROR("DBGetPointvar", E_GRABBED) ;
6523         if (!name || !*name)
6524             API_ERROR("pointvar name", E_BADARGS);
6525         if (!dbfile->pub.g_pv)
6526             API_ERROR(dbfile->pub.name, E_NOTIMP);
6527 
6528         retval = (dbfile->pub.g_pv) (dbfile, name);
6529         API_RETURN(retval);
6530     }
6531     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6532 }
6533 
6534 /*-------------------------------------------------------------------------
6535  * Function:    DBGetQuadmesh
6536  *
6537  * Purpose:     Allocates a DBquadmesh data structure and reads
6538  *              a quadrilateral mesh from the databas.
6539  *
6540  * Return:      Success:        pointer to the new DBquadmesh struct.
6541  *
6542  *              Failure:        NULL
6543  *
6544  * Programmer:  matzke@viper
6545  *              Tue Nov  8 09:44:26 PST 1994
6546  *
6547  * Modifications:
6548  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6549  *    I replaced API_END with API_END_NOPOP.
6550  *
6551  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6552  *    Added a check for variable name validity.
6553  *
6554  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6555  *    Made the error messages a little better.
6556  *
6557  *    Hank Childs, Fri Feb 25 09:48:40 PST 2000
6558  *    Initialized start_index and size_index.
6559  *
6560  *-------------------------------------------------------------------------*/
6561 PUBLIC DBquadmesh *
DBGetQuadmesh(DBfile * dbfile,const char * name)6562 DBGetQuadmesh(DBfile *dbfile, const char *name)
6563 {
6564     DBquadmesh    *qm = NULL;
6565     int            i;
6566 
6567     API_BEGIN2("DBGetQuadmesh", DBquadmesh *, NULL, name) {
6568         if (!dbfile)
6569             API_ERROR(NULL, E_NOFILE);
6570         if (SILO_Globals.enableGrabDriver == TRUE)
6571             API_ERROR("DBGetQuadmesh", E_GRABBED) ;
6572         if (!name || !*name)
6573             API_ERROR("quadmesh name", E_BADARGS);
6574         if (!dbfile->pub.g_qm)
6575             API_ERROR(dbfile->pub.name, E_NOTIMP);
6576         qm = (dbfile->pub.g_qm) (dbfile, name);
6577         if (!qm)
6578         {
6579             API_RETURN(NULL);
6580         }
6581 
6582         /*
6583          * Put in default axis labels if none supplied.
6584          */
6585         switch (qm->ndims) {
6586             case 3:
6587                 if (qm->labels[2] == NULL) {
6588                     qm->labels[2] = ALLOC_N(char, 7);
6589 
6590                     strcpy(qm->labels[2], "Z Axis");
6591                 }
6592                 /* Fall through */
6593             case 2:
6594                 if (qm->labels[1] == NULL) {
6595                     qm->labels[1] = ALLOC_N(char, 7);
6596 
6597                     strcpy(qm->labels[1], "Y Axis");
6598                 }
6599                 /* Fall through */
6600             case 1:
6601                 if (qm->labels[0] == NULL) {
6602                     qm->labels[0] = ALLOC_N(char, 7);
6603 
6604                     strcpy(qm->labels[0], "X Axis");
6605                 }
6606                 break;
6607         }
6608 
6609         for (i = 0 ; i < 3 ; i++)
6610         {
6611             qm->start_index[i] = 0;
6612             qm->size_index[i]  = qm->dims[i];
6613         }
6614 
6615         API_RETURN(qm);
6616     }
6617     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6618 }
6619 
6620 /*-------------------------------------------------------------------------
6621  * Function:    DBGetQuadvar
6622  *
6623  * Purpose:     Allocates a DBquadvar data structure and reads a variable
6624  *              associated with a quadrilateral mesh from the database.
6625  *
6626  * Return:      Success:        Pointer to the new DBquadvar struct
6627  *
6628  *              Failure:        NULL
6629  *
6630  * Programmer:  matzke@viper
6631  *              Tue Nov  8 09:46:57 PST 1994
6632  *
6633  * Modifications:
6634  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6635  *    I replaced API_END with API_END_NOPOP.
6636  *
6637  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6638  *    Added a check for variable name validity.
6639  *
6640  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6641  *    Made the error messages a little better.
6642  *-------------------------------------------------------------------------*/
6643 PUBLIC DBquadvar *
DBGetQuadvar(DBfile * dbfile,const char * name)6644 DBGetQuadvar(DBfile *dbfile, const char *name)
6645 {
6646     DBquadvar * retval = NULL;
6647 
6648     API_BEGIN2("DBGetQuadvar", DBquadvar *, NULL, name) {
6649         if (!dbfile)
6650             API_ERROR(NULL, E_NOFILE);
6651         if (SILO_Globals.enableGrabDriver == TRUE)
6652             API_ERROR("DBGetQuadvar", E_GRABBED) ;
6653         if (!name || !*name)
6654             API_ERROR("quadvar name", E_BADARGS);
6655         if (!dbfile->pub.g_qv)
6656             API_ERROR(dbfile->pub.name, E_NOTIMP);
6657 
6658         retval = (dbfile->pub.g_qv) (dbfile, name);
6659         API_RETURN(retval);
6660     }
6661     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6662 }
6663 
6664 /*-------------------------------------------------------------------------
6665  * Function:    DBAnnotateUcdmesh
6666  *
6667  * Purpose:     Walks a DBucdmesh data structure and adds shapetype
6668  *              info based on ndims and shapesize (spatial dimensions
6669  *              and node count).
6670  *
6671  * Return:      1:        One or more zones/shapes were annotated.
6672  *
6673  *              0:        No annotation was performed.
6674  *
6675  *              -1:       Annotation could not be performed (an
6676  *                        error condition such as exhaustion of
6677  *                        dynamic memory occurred).
6678  *
6679  * Programmer:  reus@viper
6680  *              Tue Oct  8 09:40:36 PDT 1996
6681  *
6682  * Modifications:
6683  *-------------------------------------------------------------------------*/
6684 PUBLIC int
DBAnnotateUcdmesh(DBucdmesh * m)6685 DBAnnotateUcdmesh(DBucdmesh *m)
6686 {
6687    if (m != NULL)
6688    {
6689       DBzonelist *z;
6690 
6691       if ((z=m->zones) != NULL)
6692          if (z->shapetype == NULL)
6693          {
6694             int N, dims;
6695 
6696             if (m->topo_dim == 0 || m->topo_dim == 1 || m->topo_dim == 2)
6697                 dims = m->topo_dim;
6698             else
6699                 dims = z->ndims;
6700 
6701             N = z->nshapes;
6702             if ((z->shapetype=(int *)malloc(N*sizeof(int))) != NULL)
6703             {
6704                int *numberOfNodes;
6705 
6706                if ((numberOfNodes=z->shapesize) != NULL)
6707                {
6708                   int i;
6709 
6710                   switch (dims)
6711                   {
6712                     case 1: for (i=0; i<N; ++i)
6713                                z->shapetype[i] = DB_ZONETYPE_BEAM;
6714                             break;
6715                     case 2: for (i=0; i<N; ++i)
6716                                switch (numberOfNodes[i])
6717                                {
6718                                  case 3:  z->shapetype[i] = DB_ZONETYPE_TRIANGLE;
6719                                           break;
6720                                  case 4:  z->shapetype[i] = DB_ZONETYPE_QUAD;
6721                                           break;
6722                                  default: z->shapetype[i] = DB_ZONETYPE_POLYGON;
6723                                           break;
6724                                }
6725                             break;
6726                     case 3: for (i=0; i<N; ++i)
6727                                switch (numberOfNodes[i])
6728                                {
6729                                  case 4:  z->shapetype[i] = DB_ZONETYPE_TET;
6730                                           break;
6731                                  case 5:  z->shapetype[i] = DB_ZONETYPE_PYRAMID;
6732                                           break;
6733                                  case 6:  z->shapetype[i] = DB_ZONETYPE_PRISM;
6734                                           break;
6735                                  case 8:  z->shapetype[i] = DB_ZONETYPE_HEX;
6736                                           break;
6737                                  default: z->shapetype[i] = DB_ZONETYPE_POLYHEDRON;
6738                                           break;
6739                                }
6740                             break;
6741                   }
6742                   return 1;
6743                }
6744                else
6745                   return 0;
6746             }
6747             else
6748                return -1;
6749          }
6750          else
6751             return 0;
6752       else
6753          return 0;
6754    }
6755    else
6756       return 0;
6757 }
6758 
6759 /*-------------------------------------------------------------------------
6760  * Function:    DBGetUcdmesh
6761  *
6762  * Purpose:     Allocates a DBucdmesh data structure and reads a UCD mesh
6763  *              from the data file.
6764  *
6765  * Return:      Success:        Pointer to the new DBucdmesh struct
6766  *
6767  *              Failure:        NULL
6768  *
6769  * Programmer:  matzke@viper
6770  *              Tue Nov  8 09:57:59 PST 1994
6771  *
6772  * Modifications:
6773  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6774  *    Added a check for variable name validity.
6775  *
6776  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6777  *    Made the error messages a little better.
6778  *-------------------------------------------------------------------------*/
6779 PUBLIC DBucdmesh *
DBGetUcdmesh(DBfile * dbfile,const char * name)6780 DBGetUcdmesh(DBfile *dbfile, const char *name)
6781 {
6782     DBucdmesh     *um = NULL;
6783 
6784     API_BEGIN2("DBGetUcdmesh", DBucdmesh *, NULL, name) {
6785         if (!dbfile)
6786             API_ERROR(NULL, E_NOFILE);
6787         if (SILO_Globals.enableGrabDriver == TRUE)
6788             API_ERROR("DBGetUcdmesh", E_GRABBED) ;
6789         if (!name || !*name)
6790             API_ERROR("UCDmesh name", E_BADARGS);
6791         if (!dbfile->pub.g_um)
6792             API_ERROR(dbfile->pub.name, E_NOTIMP);
6793         um = ((dbfile->pub.g_um) (dbfile, name));
6794         if (!um)
6795         {
6796             API_RETURN(NULL);
6797         }
6798 
6799         /*
6800          * Put in default axis labels if none supplied.
6801          */
6802         switch (um->ndims) {
6803             case 3:
6804                 if (um->labels[2] == NULL) {
6805                     um->labels[2] = ALLOC_N(char, 7);
6806 
6807                     if (!um->labels[2])
6808                         API_ERROR(NULL, E_NOMEM);
6809                     strcpy(um->labels[2], "Z Axis");
6810                 }
6811                 /*fall through */
6812             case 2:
6813                 if (um->labels[1] == NULL) {
6814                     um->labels[1] = ALLOC_N(char, 7);
6815 
6816                     if (!um->labels[1])
6817                         API_ERROR(NULL, E_NOMEM);
6818                     strcpy(um->labels[1], "Y Axis");
6819                 }
6820                 /*fall through */
6821             case 1:
6822                 if (um->labels[0] == NULL) {
6823                     um->labels[0] = ALLOC_N(char, 7);
6824 
6825                     if (!um->labels[0])
6826                         API_ERROR(NULL, E_NOMEM);
6827                     strcpy(um->labels[0], "X Axis");
6828                 }
6829         }
6830         if (DBAnnotateUcdmesh(um) < 0)
6831            API_ERROR(NULL, E_NOMEM);
6832 
6833         API_RETURN(um);
6834     }
6835     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6836 }
6837 
6838 /*-------------------------------------------------------------------------
6839  * Function:    DBGetUcdvar
6840  *
6841  * Purpose:     Allocates a DBucdvar structure and reads a variable associated
6842  *              with a UCD mesh from the database.
6843  *
6844  * Return:      Success:        Pointer to the new DBucdvar struct
6845  *
6846  *              Failure:        NULL
6847  *
6848  * Programmer:  matzke@viper
6849  *              Tue Nov  8 11:04:35 PST 1994
6850  *
6851  * Modifications:
6852  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6853  *    Added a check for variable name validity.
6854  *
6855  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6856  *    Made the error messages a little better.
6857  *-------------------------------------------------------------------------*/
6858 PUBLIC DBucdvar *
DBGetUcdvar(DBfile * dbfile,const char * name)6859 DBGetUcdvar(DBfile *dbfile, const char *name)
6860 {
6861     DBucdvar * retval = NULL;
6862 
6863     API_BEGIN2("DBGetUcdvar", DBucdvar *, NULL, name) {
6864         if (!dbfile)
6865             API_ERROR(NULL, E_NOFILE);
6866         if (SILO_Globals.enableGrabDriver == TRUE)
6867             API_ERROR("DBGetUcdvar", E_GRABBED) ;
6868         if (!name || !*name)
6869             API_ERROR("UCDvar name", E_BADARGS);
6870         if (!dbfile->pub.g_uv)
6871             API_ERROR(dbfile->pub.name, E_NOTIMP);
6872 
6873         retval = (dbfile->pub.g_uv) (dbfile, name);
6874         API_RETURN(retval);
6875     }
6876     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6877 }
6878 
6879 /*-------------------------------------------------------------------------
6880  * Function:    DBGetFacelist
6881  *
6882  * Purpose:     Allocate and read a DBfacelist structure.
6883  *
6884  * Return:      Success:        ptr to new DBfacelist
6885  *
6886  *              Failure:        NULL
6887  *
6888  * Programmer:  robb@cloud
6889  *              Wed Dec 14 13:50:44 EST 1994
6890  *
6891  * Modifications:
6892  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6893  *    I replaced API_END with API_END_NOPOP.
6894  *
6895  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6896  *    Added a check for variable name validity.
6897  *
6898  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6899  *    Made the error messages a little better.
6900  *-------------------------------------------------------------------------*/
6901 PUBLIC DBfacelist *
DBGetFacelist(DBfile * dbfile,const char * name)6902 DBGetFacelist(DBfile *dbfile, const char *name)
6903 {
6904     DBfacelist * retval = NULL;
6905 
6906     API_BEGIN2("DBGetFacelist", DBfacelist *, NULL, name) {
6907         if (!dbfile)
6908             API_ERROR(NULL, E_NOFILE);
6909         if (SILO_Globals.enableGrabDriver == TRUE)
6910             API_ERROR("DBGetFacelist", E_GRABBED) ;
6911         if (!name || !*name)
6912             API_ERROR("facelist name", E_BADARGS);
6913         if (!dbfile->pub.g_fl)
6914             API_ERROR(dbfile->pub.name, E_NOTIMP);
6915 
6916         retval = (dbfile->pub.g_fl) (dbfile, name);
6917         API_RETURN(retval);
6918     }
6919     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6920 }
6921 
6922 /*-------------------------------------------------------------------------
6923  * Function:    DBGetZonelist
6924  *
6925  * Purpose:     Allocate and read a DBzonelist structure.
6926  *
6927  * Return:      Success:        ptr to new DBzonelist.
6928  *
6929  *              Failure:        NULL
6930  *
6931  * Programmer:  robb@cloud
6932  *              Wed Dec 14 13:59:51 EST 1994
6933  *
6934  * Modifications:
6935  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
6936  *    I replaced API_END with API_END_NOPOP.
6937  *
6938  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
6939  *    Added a check for variable name validity.
6940  *
6941  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
6942  *    Made the error messages a little better.
6943  *-------------------------------------------------------------------------*/
6944 PUBLIC DBzonelist *
DBGetZonelist(DBfile * dbfile,const char * name)6945 DBGetZonelist(DBfile *dbfile, const char *name)
6946 {
6947     DBzonelist * retval = NULL;
6948 
6949     API_BEGIN2("DBGetZonelist", DBzonelist *, NULL, name) {
6950         if (!dbfile)
6951             API_ERROR(NULL, E_NOFILE);
6952         if (SILO_Globals.enableGrabDriver == TRUE)
6953             API_ERROR("DBGetZonelist", E_GRABBED) ;
6954         if (!name || !*name)
6955             API_ERROR("zonelist name", E_BADARGS);
6956         if (!dbfile->pub.g_zl)
6957             API_ERROR(dbfile->pub.name, E_NOTIMP);
6958 
6959         retval = (dbfile->pub.g_zl) (dbfile, name);
6960         API_RETURN(retval);
6961     }
6962     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6963 }
6964 
6965 /*-------------------------------------------------------------------------
6966  * Function:    DBGetPHZonelist
6967  *
6968  * Purpose:     Allocate and read a DBphzonelist structure.
6969  *
6970  * Return:      Success:        ptr to new DBphzonelist.
6971  *
6972  *              Failure:        NULL
6973  *
6974  * Programmer:  Mark C. Miller
6975  *              July 28, 2004
6976  *
6977  *-------------------------------------------------------------------------*/
6978 PUBLIC DBphzonelist *
DBGetPHZonelist(DBfile * dbfile,const char * name)6979 DBGetPHZonelist(DBfile *dbfile, const char *name)
6980 {
6981     DBphzonelist * retval = NULL;
6982 
6983     API_BEGIN2("DBGetPHZonelist", DBphzonelist *, NULL, name) {
6984         if (!dbfile)
6985             API_ERROR(NULL, E_NOFILE);
6986         if (SILO_Globals.enableGrabDriver == TRUE)
6987             API_ERROR("DBGetPHZonelist", E_GRABBED) ;
6988         if (!name || !*name)
6989             API_ERROR("zonelist name", E_BADARGS);
6990         if (!dbfile->pub.g_phzl)
6991             API_ERROR(dbfile->pub.name, E_NOTIMP);
6992 
6993         retval = (dbfile->pub.g_phzl) (dbfile, name);
6994         API_RETURN(retval);
6995     }
6996     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
6997 }
6998 
6999 /*-------------------------------------------------------------------------
7000  * Function:    DBGetVar
7001  *
7002  * Purpose:     Allocate space for a variable and read the variable from the
7003  *              database.
7004  *
7005  * Return:      Success:        Pointer to the variable value.
7006  *
7007  *              Failure:        NULL
7008  *
7009  * Programmer:  matzke@viper
7010  *              Tue Nov  8 11:11:29 PST 1994
7011  *
7012  * Modifications:
7013  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7014  *    I replaced API_END with API_END_NOPOP.
7015  *
7016  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7017  *    Added a check for variable name validity.
7018  *-------------------------------------------------------------------------*/
7019 PUBLIC void   *
DBGetVar(DBfile * dbfile,const char * name)7020 DBGetVar(DBfile *dbfile, const char *name)
7021 {
7022     void   * retval = NULL;
7023 
7024     API_BEGIN2("DBGetVar", void *, NULL, name) {
7025         if (!dbfile)
7026             API_ERROR(NULL, E_NOFILE);
7027         if (SILO_Globals.enableGrabDriver == TRUE)
7028             API_ERROR("DBGetVar", E_GRABBED) ;
7029         if (!name || !*name)
7030             API_ERROR("variable name", E_BADARGS);
7031         if (!dbfile->pub.g_var)
7032             API_ERROR(dbfile->pub.name, E_NOTIMP);
7033 
7034         retval = (dbfile->pub.g_var) (dbfile, name);
7035         API_RETURN(retval);
7036     }
7037     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7038 }
7039 
7040 /*-------------------------------------------------------------------------
7041  * Function:    DBReadVar
7042  *
7043  * Purpose:     Same as DBGetVar() except the user supplies the result
7044  *              memory instead of the function allocating it on the heap.
7045  *
7046  * Return:      Success:        0
7047  *
7048  *              Failure:        -1
7049  *
7050  * Programmer:  robb@cloud
7051  *              Wed Nov  9 13:00:07 EST 1994
7052  *
7053  * Modifications:
7054  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7055  *    I replaced API_END with API_END_NOPOP.
7056  *
7057  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7058  *    Added a check for variable name validity.
7059  *
7060  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7061  *    Made the error messages a little better.
7062  *-------------------------------------------------------------------------*/
7063 PUBLIC int
DBReadVar(DBfile * dbfile,const char * name,void * result)7064 DBReadVar(DBfile *dbfile, const char *name, void *result)
7065 {
7066     int retval;
7067 
7068     API_BEGIN2("DBReadVar", int, -1, name) {
7069         if (!dbfile)
7070             API_ERROR(NULL, E_NOFILE);
7071         if (SILO_Globals.enableGrabDriver == TRUE)
7072             API_ERROR("DBReadVar", E_GRABBED) ;
7073         if (!name || !*name)
7074             API_ERROR("variable name", E_BADARGS);
7075         if (!result)
7076             API_ERROR("result pointer", E_BADARGS);
7077         if (!dbfile->pub.r_var)
7078             API_ERROR(dbfile->pub.name, E_NOTIMP);
7079 
7080         retval = (dbfile->pub.r_var) (dbfile, name, result);
7081         API_RETURN(retval);
7082     }
7083     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7084 }
7085 
7086 /*-------------------------------------------------------------------------
7087  * Function:    DBReadVarSlice
7088  *
7089  * Purpose:     Same as DBReadVarSlice() except the user can read a only
7090  *              a slice of the variable.
7091  *
7092  * Return:      Success:        0
7093  *
7094  *              Failure:        -1
7095  *
7096  * Programmer:  brugger@sgibird
7097  *              Thu Feb 16 08:25:47 PST 1995
7098  *
7099  * Modifications:
7100  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7101  *    Added a check for variable name validity.
7102  *
7103  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7104  *    Made the error messages a little better.
7105  *-------------------------------------------------------------------------*/
7106 PUBLIC int
DBReadVarSlice(DBfile * dbfile,const char * name,int const * offset,int const * length,int const * stride,int ndims,void * result)7107 DBReadVarSlice(DBfile *dbfile, const char *name, int const *offset, int const *length,
7108                int const *stride, int ndims, void *result)
7109 {
7110     int retval;
7111 
7112     API_BEGIN2("DBReadVarSlice", int, -1, name) {
7113         if (!dbfile)
7114             API_ERROR(NULL, E_NOFILE);
7115         if (SILO_Globals.enableGrabDriver == TRUE)
7116             API_ERROR("DBReadVarSlice", E_GRABBED) ;
7117         if (!name || !*name)
7118             API_ERROR("variable name", E_BADARGS);
7119         if (!offset)
7120             API_ERROR("offset", E_BADARGS);
7121         if (!length)
7122             API_ERROR("length", E_BADARGS);
7123         if (!stride)
7124             API_ERROR("stride", E_BADARGS);
7125         if (ndims <= 0)
7126             API_ERROR("ndims", E_BADARGS);
7127         if (!result)
7128             API_ERROR("result pointer", E_BADARGS);
7129         if (!dbfile->pub.r_varslice)
7130             API_ERROR(dbfile->pub.name, E_NOTIMP);
7131 
7132         retval = (dbfile->pub.r_varslice) (dbfile, name, offset,
7133                                            length, stride, ndims, result);
7134         API_RETURN(retval);
7135     }
7136     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7137 }
7138 
7139 /*-------------------------------------------------------------------------
7140  * Function:    DBGetVarByteLength
7141  *
7142  * Purpose:     Returns the length of the requested variable, in bytes.
7143  *
7144  * Return:      Success:        length of variable in bytes.
7145  *
7146  *              Failure:        -1
7147  *
7148  * Programmer:  matzke@viper
7149  *              Tue Nov  8 11:18:35 PST 1994
7150  *
7151  * Modifications:
7152  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7153  *    I replaced API_END with API_END_NOPOP.
7154  *
7155  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7156  *    Added a check for variable name validity.
7157  *-------------------------------------------------------------------------*/
7158 PUBLIC int
DBGetVarByteLength(DBfile * dbfile,const char * name)7159 DBGetVarByteLength(DBfile *dbfile, const char *name)
7160 {
7161     int retval;
7162 
7163     API_BEGIN2("DBGetVarByteLength", int, -1, name) {
7164         if (!dbfile)
7165             API_ERROR(NULL, E_NOFILE);
7166         if (SILO_Globals.enableGrabDriver == TRUE)
7167             API_ERROR("DBGetVarByteLength", E_GRABBED) ;
7168         if (!name || !*name)
7169             API_ERROR("variable name", E_BADARGS);
7170         if (!dbfile->pub.g_varbl)
7171             API_ERROR(dbfile->pub.name, E_NOTIMP);
7172 
7173         retval = (dbfile->pub.g_varbl) (dbfile, name);
7174         API_RETURN(retval);
7175     }
7176     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7177 }
7178 
7179 /*-------------------------------------------------------------------------
7180  * Function:    DBGetVarLength
7181  *
7182  * Purpose:     Returns the number of elements in the given variable.
7183  *
7184  * Return:      Success:        number of elements
7185  *
7186  *              Failure:        -1
7187  *
7188  * Programmer:  matzke@viper
7189  *              Tue Nov  8 11:23:20 PST 1994
7190  *
7191  * Modifications:
7192  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7193  *    I replaced API_END with API_END_NOPOP.
7194  *
7195  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7196  *    Added a check for variable name validity.
7197  *-------------------------------------------------------------------------*/
7198 PUBLIC int
DBGetVarLength(DBfile * dbfile,const char * name)7199 DBGetVarLength(DBfile *dbfile, const char *name)
7200 {
7201     int retval;
7202 
7203     API_BEGIN2("DBGetVarLength", int, -1, name) {
7204         if (!dbfile)
7205             API_ERROR(NULL, E_NOFILE);
7206         if (SILO_Globals.enableGrabDriver == TRUE)
7207             API_ERROR("DBGetVarLength", E_GRABBED) ;
7208         if (!name || !*name)
7209             API_ERROR("variable name", E_BADARGS);
7210         if (!dbfile->pub.g_varlen)
7211             API_ERROR(dbfile->pub.name, E_NOTIMP);
7212 
7213         retval = (dbfile->pub.g_varlen) (dbfile, name);
7214         API_RETURN(retval);
7215     }
7216     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7217 }
7218 
7219 /*-------------------------------------------------------------------------
7220  * Function:    DBGetVarDims
7221  *
7222  * Purpose:     Returns information about the dimensions of a variable.
7223  *              The user passes a buffer to hold the dimension sizes
7224  *              and indicates the size of that buffer.
7225  *
7226  * Return:      Success:        The number of dimensions not exceeding
7227  *                              MAXDIMS.  The dimension sizes are returned
7228  *                              through DIMS.
7229  *
7230  *              Failure:        -1
7231  *
7232  * Programmer:  Robb Matzke
7233  *              robb@maya.nuance.mdn.com
7234  *              Mar  6 1997
7235  *
7236  * Modifications:
7237  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7238  *    Reformatted the code so that a human can read it.
7239  *-------------------------------------------------------------------------*/
7240 PUBLIC int
DBGetVarDims(DBfile * dbfile,const char * name,int maxdims,int * dims)7241 DBGetVarDims(DBfile *dbfile, const char *name, int maxdims, int *dims)
7242 {
7243     int             retval = -1;
7244 
7245     API_BEGIN2("DBGetVarDims", int, -1, name)
7246     {
7247         if (!dbfile)
7248             API_ERROR(NULL, E_NOFILE);
7249         if (SILO_Globals.enableGrabDriver == TRUE)
7250             API_ERROR("DBGetVarDims", E_GRABBED) ;
7251         if (!name || !*name)
7252             API_ERROR("variable name", E_BADARGS);
7253         if (maxdims <= 0)
7254             API_ERROR("max dims", E_BADARGS);
7255         if (!dims)
7256             API_ERROR("dimension buffer pointer", E_BADARGS);
7257         if (!dbfile->pub.g_vardims)
7258             API_ERROR(dbfile->pub.name, E_NOTIMP);
7259 
7260         retval = (dbfile->pub.g_vardims) (dbfile, name, maxdims, dims);
7261         API_RETURN(retval);
7262     }
7263     API_END_NOPOP;                     /* BEWARE: If API_RETURN above is
7264                                         * removed use API_END */
7265 }
7266 
7267 /*-------------------------------------------------------------------------
7268  * Function:    DBGetVarType
7269  *
7270  * Purpose:     Returns the data type of a variable.
7271  *
7272  * Return:      Success:        type, such as DB_INT, DB_FLOAT, etc.
7273  *
7274  *              Failure:        -1
7275  *
7276  * Programmer:  matzke@viper
7277  *              Thu Dec 22 08:54:20 PST 1994
7278  *
7279  * Modifications:
7280  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7281  *    I replaced API_END with API_END_NOPOP.
7282  *
7283  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7284  *    Added a check for variable name validity.
7285  *-------------------------------------------------------------------------*/
7286 PUBLIC int
DBGetVarType(DBfile * dbfile,const char * name)7287 DBGetVarType(DBfile *dbfile, const char *name)
7288 {
7289     int retval;
7290 
7291     API_BEGIN2("DBGetVarType", int, -1, name) {
7292         if (!dbfile)
7293             API_ERROR(NULL, E_NOFILE);
7294         if (SILO_Globals.enableGrabDriver == TRUE)
7295             API_ERROR("DBGetVarType", E_GRABBED) ;
7296         if (!name || !*name)
7297             API_ERROR("variable name", E_BADARGS);
7298         if (!dbfile->pub.g_vartype)
7299             API_ERROR(dbfile->pub.name, E_NOTIMP);
7300 
7301         retval = (dbfile->pub.g_vartype) (dbfile, name);
7302         API_RETURN(retval);
7303     }
7304     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7305 }
7306 
7307 /*-------------------------------------------------------------------------
7308  * Function:    DBInqMeshname
7309  *
7310  * Purpose:     Returns the name of a mesh associated with a mesh
7311  *              variable.
7312  *
7313  * Return:      Success:        0, name returned via `mname'
7314  *
7315  *              Failure:        -1
7316  *
7317  * Programmer:  matzke@viper
7318  *              Tue Nov  8 11:27:15 PST 1994
7319  *
7320  * Modifications:
7321  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7322  *    I replaced API_END with API_END_NOPOP.
7323  *
7324  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7325  *    Added a check for variable name validity.
7326  *
7327  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7328  *    Made the error messages a little better.
7329  *-------------------------------------------------------------------------*/
7330 PUBLIC int
DBInqMeshname(DBfile * dbfile,const char * vname,char * mname)7331 DBInqMeshname(DBfile *dbfile, const char *vname, char *mname)
7332 {
7333     int retval;
7334 
7335     API_BEGIN2("DBInqMeshname", int, -1, vname) {
7336         if (!dbfile)
7337             API_ERROR(NULL, E_NOFILE);
7338         if (SILO_Globals.enableGrabDriver == TRUE)
7339             API_ERROR("DBInqMeshname", E_GRABBED) ;
7340         if (!vname || !*vname)
7341             API_ERROR("variable name", E_BADARGS);
7342         if (!mname)
7343             API_ERROR("mesh name pointer", E_BADARGS);
7344         if (!dbfile->pub.i_meshname)
7345             API_ERROR(dbfile->pub.name, E_NOTIMP);
7346 
7347         retval = (dbfile->pub.i_meshname) (dbfile, vname, mname);
7348         API_RETURN(retval);
7349     }
7350     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7351 }
7352 
7353 /*-------------------------------------------------------------------------
7354  * Function:    DBInqMeshtype
7355  *
7356  * Purpose:     Returns the mesh type for the specified mesh.
7357  *
7358  * Return:      Success:        mesh type constant
7359  *
7360  *              Failure:        -1
7361  *
7362  * Programmer:  matzke@viper
7363  *              Tue Nov  8 11:31:56 PST 1994
7364  *
7365  * Modifications:
7366  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7367  *    I replaced API_END with API_END_NOPOP.
7368  *
7369  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7370  *    Added a check for variable name validity.
7371  *-------------------------------------------------------------------------*/
7372 PUBLIC int
DBInqMeshtype(DBfile * dbfile,const char * name)7373 DBInqMeshtype(DBfile *dbfile, const char *name)
7374 {
7375     int retval;
7376 
7377     API_BEGIN2("DBInqMeshtype", int, -1, name) {
7378         if (!dbfile)
7379             API_ERROR(NULL, E_NOFILE);
7380         if (SILO_Globals.enableGrabDriver == TRUE)
7381             API_ERROR("DBInqMeshtype", E_GRABBED) ;
7382         if (!name || !*name)
7383             API_ERROR("mesh name", E_BADARGS);
7384         if (!dbfile->pub.i_meshtype)
7385             API_ERROR(dbfile->pub.name, E_NOTIMP);
7386 
7387         retval = (dbfile->pub.i_meshtype) (dbfile, name);
7388         API_RETURN(retval);
7389     }
7390     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7391 }
7392 
7393 /*-------------------------------------------------------------------------
7394  * Function:    DBPutCompoundarray
7395  *
7396  * Purpose:     Write compoundarray information to a file.
7397  *
7398  * Return:      Success:        0
7399  *
7400  *              Failure:        -1
7401  *
7402  * Programmer:  matzke@viper
7403  *              Mon Nov  7 10:54:46 PST 1994
7404  *
7405  * Modifications:
7406  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7407  *    I replaced API_END with API_END_NOPOP.
7408  *
7409  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7410  *    Added a check for variable name validity.
7411  *
7412  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7413  *    Made the error messages a little better.
7414  *
7415  *    Robb Matzke, 2000-05-23
7416  *    The old table of contents is discarded if the directory changes.
7417  *-------------------------------------------------------------------------*/
7418 PUBLIC int
DBPutCompoundarray(DBfile * dbfile,char const * name,char const * const * elemnames,int const * elemlengths,int nelems,void const * values,int nvalues,int datatype,DBoptlist const * opts)7419 DBPutCompoundarray(
7420     DBfile *dbfile,
7421     char const *name,
7422     char const * const *elemnames,
7423     int const *elemlengths,
7424     int nelems,
7425     void const *values,
7426     int nvalues,
7427     int datatype,
7428     DBoptlist const *opts
7429 )
7430 {
7431     int retval;
7432 
7433     API_BEGIN2("DBPutCompoundarray", int, -1, name) {
7434         if (!dbfile)
7435             API_ERROR(NULL, E_NOFILE);
7436         if (SILO_Globals.enableGrabDriver == TRUE)
7437             API_ERROR("DBPutCompoundarray", E_GRABBED) ;
7438         if (!name || !*name)
7439             API_ERROR("array name", E_BADARGS);
7440         if (db_VariableNameValid(name) == 0)
7441             API_ERROR("array name", E_INVALIDNAME);
7442         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
7443             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
7444         if (nelems < 0)
7445             API_ERROR("nelems<0", E_BADARGS);
7446         if (nelems)
7447         {
7448             if (!nelems)
7449                 API_ERROR("nelems=0", E_BADARGS);
7450             if (!elemnames)
7451                 API_ERROR("elemnames=0", E_BADARGS);
7452             if (nvalues <= 0)
7453                 API_ERROR("nvalues=0", E_BADARGS);
7454             if (!values)
7455                 API_ERROR("values=0", E_BADARGS);
7456         }
7457         else if (!SILO_Globals.allowEmptyObjects)
7458         {
7459             /* this is an empty object but we don't know if it was intentional */
7460             API_ERROR("nelems=0", E_EMPTYOBJECT);
7461         }
7462         else
7463         {
7464             nvalues = 0;
7465         }
7466 
7467         if (NULL == dbfile->pub.p_ca)
7468             API_ERROR(dbfile->pub.name, E_NOTIMP);
7469 
7470         retval = (dbfile->pub.p_ca) (dbfile, name, elemnames,
7471                                      elemlengths, nelems, values, nvalues,
7472                                      datatype, opts);
7473         db_FreeToc(dbfile);
7474         API_RETURN(retval);
7475     }
7476     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7477 }
7478 
7479 /*-------------------------------------------------------------------------
7480  * Function:    DBPutCurve
7481  *
7482  * Purpose:     Writes curve information to a file.
7483  *
7484  * Return:      Success:        0
7485  *
7486  *              Failure:        -1
7487  *
7488  * Programmer:  Robb Matzke
7489  *              robb@callisto.nuance.com
7490  *              May 15, 1996
7491  *
7492  * Modifications:
7493  *    Robb Matzke, 16 May 1996
7494  *    Don't check for existence of XVALS and YVALS since the OPTS can
7495  *    specify a PDB variable name which has already been added to the
7496  *    file and which contains the necessary x or y values.  However,
7497  *    the driver should check.
7498  *
7499  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7500  *    Added a check for variable name validity.
7501  *
7502  *    Robb Matzke, 2000-05-23
7503  *    The old table of contents is discarded if the directory changes.
7504  *-------------------------------------------------------------------------*/
7505 PUBLIC int
DBPutCurve(DBfile * dbfile,char const * name,void const * xvals,void const * yvals,int datatype,int npts,DBoptlist const * opts)7506 DBPutCurve(
7507     DBfile *dbfile,
7508     char const *name,
7509     void const *xvals,
7510     void const *yvals,
7511     int datatype,
7512     int npts,
7513     DBoptlist const *opts
7514 )
7515 {
7516     int retval;
7517 
7518     API_BEGIN2("DBPutCurve", int, -1, name)
7519     {
7520         if (!dbfile)
7521             API_ERROR(NULL, E_NOFILE);
7522         if (SILO_Globals.enableGrabDriver == TRUE)
7523             API_ERROR("DBPutCurve", E_GRABBED) ;
7524         if (!name || !*name)
7525             API_ERROR("curve name", E_BADARGS);
7526         if (db_VariableNameValid(name) == 0)
7527             API_ERROR("curve name", E_INVALIDNAME);
7528         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
7529             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
7530         if (npts < 0)
7531             API_ERROR("npts<0", E_BADARGS);
7532         if (npts)
7533         {
7534             if (DBGetOption(opts, DBOPT_REFERENCE))
7535             {
7536                 if (yvals || xvals)
7537                     API_ERROR("xvals & yvals must be null when using DBOPT_REFERENCE", E_BADARGS);
7538             }
7539             else
7540             {
7541                 if (!xvals && !DBGetOption(opts, DBOPT_XVARNAME))
7542                     API_ERROR("xvals=0 || DBOPT_XVARNAME", E_BADARGS);
7543                 if (xvals && DBGetOption(opts, DBOPT_XVARNAME))
7544                     API_ERROR("xvals!=0 && DBOPT_XVARNAME", E_BADARGS);
7545                 if (!yvals && !DBGetOption(opts, DBOPT_YVARNAME))
7546                     API_ERROR("yvals=0 || DBOPT_YVARNAME", E_BADARGS);
7547                 if (yvals && DBGetOption(opts, DBOPT_YVARNAME))
7548                     API_ERROR("yvals!=0 && DBOPT_YVARNAME", E_BADARGS);
7549             }
7550         }
7551         else if (!SILO_Globals.allowEmptyObjects &&
7552                  !DBGetOption(opts, DBOPT_REFERENCE))
7553         {
7554             /* this is an empty object but we don't know if it was intentional */
7555             API_ERROR("npts=0", E_EMPTYOBJECT);
7556         }
7557 
7558         if (NULL == dbfile->pub.p_cu)
7559             API_ERROR(dbfile->pub.name, E_NOTIMP);
7560 
7561         retval = (dbfile->pub.p_cu) (dbfile, name, (void*)xvals, (void*)yvals,
7562                                      datatype, npts, opts);
7563 
7564         db_FreeToc(dbfile);
7565         API_RETURN(retval);
7566     }
7567     API_END_NOPOP; /* BEWARE: If API_RETURN above is removed use API_END */
7568 }
7569 
7570 /*-------------------------------------------------------------------------
7571  * Function:    DBPutDefvars
7572  *
7573  * Purpose:     Writes a Defvars object to a file.
7574  *
7575  * Return:      Success:        0
7576  *
7577  *              Failure:        -1
7578  *
7579  * Programmer:  Mark C. Miller
7580  *              August 8, 2005
7581  *
7582  *-------------------------------------------------------------------------*/
7583 PUBLIC int
DBPutDefvars(DBfile * dbfile,const char * name,int ndefs,char const * const * names,int const * types,char const * const * defns,DBoptlist const * const * opts)7584 DBPutDefvars(
7585     DBfile *dbfile,
7586     const char *name,
7587     int ndefs,
7588     char const * const *names,
7589     int const *types,
7590     char const * const *defns,
7591     DBoptlist const * const *opts
7592 )
7593 {
7594     int retval;
7595 
7596     API_BEGIN2("DBPutDefvars", int, -1, name)
7597     {
7598         if (!dbfile)
7599             API_ERROR(NULL, E_NOFILE);
7600         if (SILO_Globals.enableGrabDriver == TRUE)
7601             API_ERROR("DBPutDefvars", E_GRABBED) ;
7602         if (!name || !*name)
7603             API_ERROR("defvars name", E_BADARGS);
7604         if (db_VariableNameValid(name) == 0)
7605             API_ERROR("defvars name", E_INVALIDNAME);
7606         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
7607             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
7608         if (ndefs < 0)
7609             API_ERROR("ndefs", E_BADARGS);
7610         if (ndefs)
7611         {
7612             if (!names)
7613                 API_ERROR("names=0", E_BADARGS);
7614             if (!types)
7615                 API_ERROR("types=0", E_BADARGS);
7616             if (!defns)
7617                 API_ERROR("defns=0", E_BADARGS);
7618         }
7619         else if (!SILO_Globals.allowEmptyObjects)
7620         {
7621             /* this is an empty object but we don't know if it was intentional */
7622             API_ERROR("ndefs=0", E_EMPTYOBJECT);
7623         }
7624 
7625         if (NULL == dbfile->pub.p_defv)
7626             API_ERROR(dbfile->pub.name, E_NOTIMP);
7627 
7628         retval = (dbfile->pub.p_defv) (dbfile, name, ndefs, names,
7629                                        types, defns, opts);
7630         db_FreeToc(dbfile);
7631         API_RETURN(retval);
7632     }
7633     API_END_NOPOP; /* BEWARE: If API_RETURN above is removed use API_END */
7634 }
7635 
7636 /*-------------------------------------------------------------------------
7637  * Function:    DBPutFacelist
7638  *
7639  * Purpose:     Writes a facelist object into the open database file.
7640  *
7641  * Return:      Success:        0
7642  *
7643  *              Failure:        -1
7644  *
7645  * Programmer:  matzke@viper
7646  *              Tue Nov  8 11:52:25 PST 1994
7647  *
7648  * Modifications:
7649  *    Robb Matzke, Thu Dec 1 10:34:09 PST 1994
7650  *    The `zoneno' parameter is optional even if
7651  *    the number of faces is zero.
7652  *
7653  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7654  *    I replaced API_END with API_END_NOPOP.
7655  *
7656  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7657  *    Added a check for variable name validity.
7658  *
7659  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7660  *    Made the error messages a little better.
7661  *
7662  *    Robb Matzke, 2000-05-23
7663  *    The old table of contents is discarded if the directory changes.
7664  *-------------------------------------------------------------------------*/
7665 PUBLIC int
DBPutFacelist(DBfile * dbfile,const char * name,int nfaces,int ndims,int const * nodelist,int lnodelist,int origin,int const * zoneno,int const * shapesize,int const * shapecnt,int nshapes,int const * types,int const * typelist,int ntypes)7666 DBPutFacelist(DBfile *dbfile, const char *name, int nfaces, int ndims,
7667               int const *nodelist, int lnodelist, int origin, int const *zoneno,
7668               int const *shapesize, int const *shapecnt, int nshapes, int const *types,
7669               int const *typelist, int ntypes)
7670 {
7671     int retval;
7672 
7673     API_BEGIN2("DBPutFacelist", int, -1, name) {
7674         if (!dbfile)
7675             API_ERROR(NULL, E_NOFILE);
7676         if (SILO_Globals.enableGrabDriver == TRUE)
7677             API_ERROR("DBPutFacelist", E_GRABBED) ;
7678         if (!name || !*name)
7679             API_ERROR("facelist name", E_BADARGS);
7680         if (db_VariableNameValid(name) == 0)
7681             API_ERROR("facelist name", E_INVALIDNAME);
7682         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
7683             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
7684         if (nfaces < 0)
7685             API_ERROR("nfaces<0", E_BADARGS);
7686         if (nfaces)
7687         {
7688             if (nfaces <= 0)
7689                 API_ERROR("nfaces<=0", E_BADARGS);
7690             if (ndims <= 0)
7691                 API_ERROR("ndims<=0", E_BADARGS);
7692             if (lnodelist <= 0)
7693                 API_ERROR("lnodelist<0", E_BADARGS);
7694             if (nshapes <= 0)
7695                 API_ERROR("nshapes<0", E_BADARGS);
7696             if (!nodelist)
7697                 API_ERROR("nodelist==0", E_BADARGS);
7698             if (!shapesize)
7699                 API_ERROR("shapesize==0", E_BADARGS);
7700             if (!shapecnt)
7701                 API_ERROR("shapecnt==0", E_BADARGS);
7702             if (ntypes < 0)
7703                 API_ERROR("ntypes<0", E_BADARGS);
7704             if (origin != 0 && origin != 1)
7705                 API_ERROR("origin", E_BADARGS);
7706         }
7707         else if (!SILO_Globals.allowEmptyObjects)
7708         {
7709             /* this is an empty object but we don't know if it was intentional */
7710             API_ERROR("nfaces=0", E_EMPTYOBJECT);
7711         }
7712         else
7713         {
7714             nfaces = 0;
7715             lnodelist = 0;
7716             nshapes = 0;
7717             ntypes = 0;
7718         }
7719 
7720         if (!dbfile->pub.p_fl)
7721             API_ERROR(dbfile->pub.name, E_NOTIMP);
7722 
7723         retval = (dbfile->pub.p_fl) (dbfile, name, nfaces, ndims,
7724                                      nodelist, lnodelist, origin, zoneno,
7725                                      shapesize, shapecnt, nshapes, types,
7726                                      typelist, ntypes);
7727         db_FreeToc(dbfile);
7728         API_RETURN(retval);
7729     }
7730     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7731 }
7732 
7733 /*-------------------------------------------------------------------------
7734  * Function:    DBPutMaterial
7735  *
7736  * Purpose:     Writes a material data object into the current open
7737  *              database.  The minimum required information for a material
7738  *              data object is supplied via the standard arguments to the
7739  *              function.  The `optlist' argument must be used for
7740  *              supplying any information not requested through the
7741  *              standard arguments.
7742  *
7743  * Return:      Success:        object ID
7744  *
7745  *              Failure:        -1
7746  *
7747  * Programmer:  matzke@viper
7748  *              Tue Nov  8 12:05:23 PST 1994
7749  *
7750  * Modifications:
7751  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7752  *    I replaced API_END with API_END_NOPOP.
7753  *
7754  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7755  *    Added a check for variable name validity.
7756  *
7757  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7758  *    Made the error messages a little better.
7759  *
7760  *    Robb Matzke, 2000-05-23
7761  *    The old table of contents is discarded if the directory changes.
7762  *
7763  *    Sean Ahern, Thu Jun  8 12:08:05 PDT 2000
7764  *    Removed an unnecessary check on mix_zone.
7765  *-------------------------------------------------------------------------*/
7766 PUBLIC int
DBPutMaterial(DBfile * dbfile,char const * name,char const * meshname,int nmat,int const * matnos,int const * matlist,int const * dims,int ndims,int const * mix_next,int const * mix_mat,int const * mix_zone,DBVCP1_t mix_vf,int mixlen,int datatype,DBoptlist const * optlist)7767 DBPutMaterial(
7768     DBfile *dbfile,
7769     char const *name,
7770     char const *meshname,
7771     int nmat,
7772     int const *matnos,
7773     int const *matlist,
7774     int const *dims,
7775     int ndims,
7776     int const *mix_next,
7777     int const *mix_mat,
7778     int const *mix_zone,
7779     DBVCP1_t mix_vf,
7780     int mixlen,
7781     int datatype,
7782     DBoptlist const *optlist
7783 )
7784 {
7785     int i, retval, is_empty = 1;
7786 
7787     API_BEGIN2("DBPutMaterial", int, -1, name) {
7788         if (!dbfile)
7789             API_ERROR(NULL, E_NOFILE);
7790         if (SILO_Globals.enableGrabDriver == TRUE)
7791             API_ERROR("DBPutMaterial", E_GRABBED) ;
7792         if (!name || !*name)
7793             API_ERROR("material name", E_BADARGS);
7794         if (db_VariableNameValid(name) == 0)
7795             API_ERROR("material name", E_INVALIDNAME);
7796         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
7797             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
7798         if (nmat < 0)
7799             API_ERROR("nmat<0", E_BADARGS);
7800         if (ndims < 0)
7801             API_ERROR("ndims<0", E_BADARGS);
7802         if (!dims)
7803             API_ERROR("dims=0", E_BADARGS);
7804         for (i = 0; i < ndims; i++)
7805         {
7806             if (dims[i] != 0)
7807             {
7808                 is_empty = 0;
7809                 break;
7810             }
7811         }
7812         if (!is_empty)
7813         {
7814             for (i = 0; i < ndims && dims; i++)
7815                 if (dims[i] == 0) dims = 0;
7816             if (!matnos) API_ERROR("matnos=0", E_BADARGS);
7817             if (!matlist) API_ERROR("matlist=0", E_BADARGS);
7818             if (!meshname || !*meshname) API_ERROR("mesh name", E_BADARGS);
7819             if (!db_VariableNameValid(meshname)) API_ERROR("meshname", E_INVALIDNAME);
7820             if (mixlen < 0)
7821                 API_ERROR("mixlen<0", E_BADARGS);
7822             if (mixlen)
7823             {
7824                 if (!mix_next)
7825                     API_ERROR("mix_next=0", E_BADARGS);
7826                 if (!mix_mat)
7827                     API_ERROR("mix_mat=0", E_BADARGS);
7828                 if (!mix_vf)
7829                     API_ERROR("mix_vf=0", E_BADARGS);
7830             }
7831         }
7832         else if (!SILO_Globals.allowEmptyObjects)
7833         {
7834             API_ERROR("nmat=0", E_EMPTYOBJECT);
7835         }
7836         if (!dbfile->pub.p_ma)
7837             API_ERROR(dbfile->pub.name, E_NOTIMP);
7838 
7839         retval = (dbfile->pub.p_ma) (dbfile, name, meshname,
7840                                      nmat, matnos, matlist, dims, ndims,
7841                                      mix_next, mix_mat, mix_zone, mix_vf,
7842                                      mixlen, datatype, optlist);
7843 
7844         /* Zero out the _ma._matnames pointer so we can't accidentially use it
7845          * again. Likewise for matcolors. */
7846         _ma._matnames = NULL;
7847         _ma._matcolors = NULL;
7848 
7849         db_FreeToc(dbfile);
7850         API_RETURN(retval);
7851     }
7852     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7853 }
7854 
7855 /*----------------------------------------------------------------------
7856  *  Routine                                                DBPutMatspecies
7857  *
7858  *  Purpose
7859  *
7860  *      Write a material species object into the open file.
7861  *
7862  *  Programmer
7863  *
7864  *      Al Leibee, B-DSAD
7865  *
7866  *  Notes
7867  *
7868  *      One zonal array ('speclist') is used which contains either:
7869  *      1) an index into the 'species_mf' array of the species mass fractions
7870  *         of a clean zone's material.
7871  *
7872  *                                  OR
7873  *      2) an index into the 'mix_speclist' array which contains an index
7874  *         into the 'species_mf' of the species mass fractions of a mixed
7875  *         zone's materials.
7876  *
7877  *  Modified
7878  *    Robb Matzke, Mon Nov 28 15:19:50 EST 1994
7879  *    Added device independence stuff.
7880  *
7881  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7882  *    I replaced API_END with API_END_NOPOP.
7883  *
7884  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7885  *    Added a check for variable name validity.
7886  *
7887  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7888  *    Made the error messages a little better.
7889  *
7890  *    Robb Matzke, 2000-05-23
7891  *    The old table of contents is discarded if the directory changes.
7892  *--------------------------------------------------------------------*/
7893 PUBLIC int
DBPutMatspecies(DBfile * dbfile,const char * name,const char * matname,int nmat,int const * nmatspec,int const * speclist,int const * dims,int ndims,int nspecies_mf,DBVCP1_t species_mf,int const * mix_speclist,int mixlen,int datatype,DBoptlist const * optlist)7894 DBPutMatspecies(DBfile *dbfile, const char *name, const char *matname,
7895                 int nmat, int const *nmatspec, int const *speclist, int const *dims,
7896                 int ndims, int nspecies_mf, DBVCP1_t species_mf,
7897                 int const *mix_speclist, int mixlen, int datatype,
7898                 DBoptlist const *optlist)
7899 {
7900     int i, retval, is_empty=1;
7901 
7902     API_BEGIN2("DBPutMatspecies", int, -1, name) {
7903         if (!dbfile)
7904             API_ERROR(NULL, E_NOFILE);
7905         if (SILO_Globals.enableGrabDriver == TRUE)
7906             API_ERROR("DBPutMatspecies", E_GRABBED) ;
7907         if (!name || !*name)
7908             API_ERROR("matspecies name", E_BADARGS);
7909         if (db_VariableNameValid(name) == 0)
7910             API_ERROR("matspecies name", E_INVALIDNAME);
7911         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
7912             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
7913         if (nmat < 0)
7914             API_ERROR("nmat<0", E_BADARGS);
7915         if (ndims < 0)
7916             API_ERROR("ndims<0", E_BADARGS);
7917         if (!dims)
7918             API_ERROR("dims=0", E_BADARGS);
7919         if (nspecies_mf < 0)
7920             API_ERROR("nspecies_mf<0", E_BADARGS);
7921         for (i = 0; i < ndims; i++)
7922         {
7923             if (dims[i] != 0)
7924             {
7925                 is_empty = 0;
7926                 break;
7927             }
7928         }
7929         if (!is_empty && nspecies_mf > 0)
7930         {
7931             if (!matname || !*matname)
7932                 API_ERROR("material name", E_BADARGS);
7933             if (db_VariableNameValid(matname) == 0)
7934                 API_ERROR("material name", E_INVALIDNAME);
7935             if (ndims == 1 && dims[0] <= 0) API_ERROR("dims[0]<=0", E_BADARGS);
7936             if (ndims == 2 && dims[1] <= 0) API_ERROR("dims[1]<=0", E_BADARGS);
7937             if (ndims == 3 && dims[2] <= 0) API_ERROR("dims[2]<=0", E_BADARGS);
7938             if (!nmatspec) API_ERROR("nmatspec=0", E_BADARGS);
7939             if (!speclist) API_ERROR("speclist=0", E_BADARGS);
7940             if (!species_mf) API_ERROR("species_mf=0", E_BADARGS);
7941             if (mixlen < 0)
7942                 API_ERROR("mixlen", E_BADARGS);
7943             if (!mix_speclist && mixlen)
7944                 API_ERROR("mix_speclist", E_BADARGS);
7945         }
7946         else if (!SILO_Globals.allowEmptyObjects)
7947         {
7948             API_ERROR("dims[i]==0 for all i || nspecies_mf==0", E_EMPTYOBJECT);
7949         }
7950         if (!dbfile->pub.p_ms)
7951             API_ERROR(dbfile->pub.name, E_NOTIMP);
7952         retval = (dbfile->pub.p_ms) (dbfile, name, matname,
7953                                      nmat, nmatspec, speclist, dims, ndims,
7954                                      nspecies_mf, species_mf, mix_speclist,
7955                                      mixlen, datatype, optlist);
7956 
7957         /* Zero out the _ma._matnames pointer so we can't accidentially use it
7958          * again. Likewise for matcolors. */
7959         _ms._specnames = NULL;
7960         _ms._speccolors = NULL;
7961 
7962         db_FreeToc(dbfile);
7963         API_RETURN(retval);
7964     }
7965     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
7966 }
7967 
7968 /*-------------------------------------------------------------------------
7969  * Function:    DBPutMultimesh
7970  *
7971  * Purpose:     Writes a multi-bloc kmesh object into the open database.
7972  *              It accepts as input descriptions of the various sub-meshes
7973  *              (blocks) which are part of this mesh.
7974  *
7975  * Return:      Success:        object ID
7976  *
7977  *              Failure:        -1
7978  *
7979  * Programmer:  matzke@viper
7980  *              Tue Nov  8 12:17:57 PST 1994
7981  *
7982  * Modifications:
7983  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
7984  *    I replaced API_END with API_END_NOPOP.
7985  *
7986  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
7987  *    Added a check for variable name validity.
7988  *
7989  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
7990  *    Made the error messages a little better.
7991  *
7992  *    Robb Matzke, 2000-05-23
7993  *    The old table of contents is discarded if the directory changes.
7994  *
7995  *    Mark C. Miller, Wed Jul 14 20:36:23 PDT 2010
7996  *    Added support for nameschemes on multi-block objects. This meant
7997  *    adjusting sanity checks for args as some can be null now.
7998  *-------------------------------------------------------------------------*/
7999 PUBLIC int
DBPutMultimesh(DBfile * dbfile,char const * name,int nmesh,char const * const * meshnames,int const * meshtypes,DBoptlist const * optlist)8000 DBPutMultimesh(DBfile *dbfile, char const *name, int nmesh,
8001     char const * const *meshnames, int const *meshtypes,
8002     DBoptlist const *optlist)
8003 {
8004     int retval;
8005 
8006     API_BEGIN2("DBPutMultimesh", int, -1, name) {
8007         if (!dbfile)
8008             API_ERROR(NULL, E_NOFILE);
8009         if (SILO_Globals.enableGrabDriver == TRUE)
8010             API_ERROR("DBPutMultimesh", E_GRABBED) ;
8011         if (!name || !*name)
8012             API_ERROR("multimesh name", E_BADARGS);
8013         if (db_VariableNameValid(name) == 0)
8014             API_ERROR("multimesh name", E_INVALIDNAME);
8015         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8016             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8017         if (nmesh < 0)
8018             API_ERROR("nmesh", E_BADARGS);
8019         if (!meshnames && nmesh && (!optlist ||
8020             (!DBGetOption(optlist, DBOPT_MB_FILE_NS) &&
8021              !DBGetOption(optlist, DBOPT_MB_BLOCK_NS))))
8022             API_ERROR("mesh names", E_BADARGS);
8023         if (!meshtypes && nmesh && (!optlist ||
8024              !DBGetOption(optlist, DBOPT_MB_BLOCK_TYPE)))
8025             API_ERROR("mesh types", E_BADARGS);
8026         if (!dbfile->pub.p_mm)
8027             API_ERROR(dbfile->pub.name, E_NOTIMP);
8028 
8029         retval = (dbfile->pub.p_mm) (dbfile, name, nmesh, meshnames,
8030                                      meshtypes, optlist);
8031         db_FreeToc(dbfile);
8032         API_RETURN(retval);
8033     }
8034     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8035 }
8036 
8037 /*-------------------------------------------------------------------------
8038  * Function:    DBPutMultimeshadj
8039  *
8040  * Purpose:     Writes a multi-mesh adjacency object into the
8041  *              open database.
8042  *
8043  * Return:      Success:        object ID
8044  *
8045  *              Failure:        -1
8046  *
8047  * Programmer:  Mark C. Miller, August 23, 2005
8048  *
8049  * Notes:       This function is designed to support repeated calls where
8050  *              Different parts of the same object are written at different
8051  *              times.
8052  *
8053  *-------------------------------------------------------------------------*/
8054 PUBLIC int
DBPutMultimeshadj(DBfile * dbfile,char const * name,int nmesh,int const * meshtypes,int const * nneighbors,int const * neighbors,int const * back,int const * lnodelists,int const * const * nodelists,int const * lzonelists,int const * const * zonelists,DBoptlist const * optlist)8055 DBPutMultimeshadj(DBfile *dbfile, char const *name, int nmesh,
8056                   int const *meshtypes, int const *nneighbors,
8057                   int const *neighbors, int const *back,
8058                   int const *lnodelists, int const * const *nodelists,
8059                   int const *lzonelists, int const * const *zonelists,
8060                   DBoptlist const *optlist)
8061 {
8062     int retval;
8063 
8064     API_BEGIN2("DBPutMultimeshadj", int, -1, name) {
8065         if (!dbfile)
8066             API_ERROR(NULL, E_NOFILE);
8067         if (SILO_Globals.enableGrabDriver == TRUE)
8068             API_ERROR("DBPutMultimeshadj", E_GRABBED) ;
8069         if (!name || !*name)
8070             API_ERROR("multimeshadj name", E_BADARGS);
8071         if (db_VariableNameValid(name) == 0)
8072             API_ERROR("multimeshadj name", E_INVALIDNAME);
8073         if (nmesh < 0)
8074             API_ERROR("nmesh", E_BADARGS);
8075         if (!meshtypes && nmesh)
8076             API_ERROR("mesh types", E_BADARGS);
8077         if (!nneighbors && nmesh)
8078             API_ERROR("nneighbors", E_BADARGS);
8079         if (!neighbors && nmesh)
8080             API_ERROR("neighbors", E_BADARGS);
8081         if (lnodelists == NULL && nodelists != NULL)
8082             API_ERROR("non-NULL nodelists", E_BADARGS);
8083         if (lzonelists == NULL && zonelists != NULL)
8084             API_ERROR("non-NULL zonelists", E_BADARGS);
8085         if (!dbfile->pub.p_mmadj)
8086             API_ERROR(dbfile->pub.name, E_NOTIMP);
8087 
8088         retval = (dbfile->pub.p_mmadj) (dbfile, name, nmesh, meshtypes,
8089                                         nneighbors, neighbors, back,
8090                                         lnodelists, nodelists, lzonelists, zonelists,
8091                                         optlist);
8092         db_FreeToc(dbfile);
8093         API_RETURN(retval);
8094     }
8095     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8096 }
8097 
8098 /*-------------------------------------------------------------------------
8099  * Function:    DBPutMultivar
8100  *
8101  * Purpose:     Writes a multi-block variable object to the database.
8102  *
8103  * Return:      Success:        object ID
8104  *
8105  *              Failure:        -1
8106  *
8107  * Programmer:  matzke@viper
8108  *              Tue Nov  8 12:26:30 PST 1994
8109  *
8110  * Modifications:
8111  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8112  *    I replaced API_END with API_END_NOPOP.
8113  *
8114  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8115  *    Added a check for variable name validity.
8116  *
8117  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8118  *    Made the error messages a little better.
8119  *
8120  *    Robb Matzke, 2000-05-23
8121  *    The old table of contents is discarded if the directory changes.
8122  *
8123  *    Mark C. Miller, Wed Jul 14 20:36:23 PDT 2010
8124  *    Added support for nameschemes on multi-block objects. This meant
8125  *    adjusting sanity checks for args as some can be null now.
8126  *-------------------------------------------------------------------------*/
8127 PUBLIC int
DBPutMultivar(DBfile * dbfile,const char * name,int nvar,char const * const * varnames,int const * vartypes,DBoptlist const * optlist)8128 DBPutMultivar(DBfile *dbfile, const char *name, int nvar,
8129               char const * const *varnames, int const *vartypes, DBoptlist const *optlist)
8130 {
8131     int retval;
8132 
8133     API_BEGIN2("DBPutMultivar", int, -1, name) {
8134         if (!dbfile)
8135             API_ERROR(NULL, E_NOFILE);
8136         if (SILO_Globals.enableGrabDriver == TRUE)
8137             API_ERROR("DBPutMultivar", E_GRABBED) ;
8138         if (!name || !*name)
8139             API_ERROR("multivar name", E_BADARGS);
8140         if (db_VariableNameValid(name) == 0)
8141             API_ERROR("multivar name", E_INVALIDNAME);
8142         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8143             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8144         if (nvar < 0)
8145             API_ERROR("nvar", E_BADARGS);
8146         if (!varnames && nvar && (!optlist ||
8147              (!DBGetOption(optlist, DBOPT_MB_FILE_NS) &&
8148               !DBGetOption(optlist, DBOPT_MB_BLOCK_NS))))
8149             API_ERROR("varnames", E_BADARGS);
8150         if (!vartypes && nvar && (!optlist ||
8151              !DBGetOption(optlist, DBOPT_MB_BLOCK_TYPE)))
8152             API_ERROR("vartypes", E_BADARGS);
8153         if (!dbfile->pub.p_mv)
8154             API_ERROR(dbfile->pub.name, E_NOTIMP);
8155 
8156         retval = (dbfile->pub.p_mv) (dbfile, name, nvar, varnames,
8157                                      vartypes, optlist);
8158         db_FreeToc(dbfile);
8159         API_RETURN(retval);
8160     }
8161     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8162 }
8163 
8164 /*-------------------------------------------------------------------------
8165  * Function:    DBPutMultimat
8166  *
8167  * Purpose:     Writes a multi-material object to the database.
8168  *
8169  * Return:      Success:        object ID
8170  *
8171  *              Failure:        -1
8172  *
8173  * Programmer:  matzke@viper
8174  *              Tue Feb 21 12:35:10 EST 1995
8175  *
8176  * Modifications:
8177  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8178  *    Added a check for variable name validity.
8179  *
8180  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8181  *    Made the error messages a little better.
8182  *
8183  *    Robb Matzke, 2000-05-23
8184  *    The old table of contents is discarded if the directory changes.
8185  *
8186  *    Mark C. Miller, Wed Jul 14 20:36:23 PDT 2010
8187  *    Added support for nameschemes on multi-block objects. This meant
8188  *    adjusting sanity checks for args as some can be null now.
8189  *-------------------------------------------------------------------------*/
8190 PUBLIC int
DBPutMultimat(DBfile * dbfile,const char * name,int nmats,char const * const * matnames,DBoptlist const * optlist)8191 DBPutMultimat(DBfile *dbfile, const char *name, int nmats,
8192               char const * const *matnames, DBoptlist const *optlist)
8193 {
8194     int retval;
8195 
8196     API_BEGIN2("DBPutMultimat", int, -1, name) {
8197         if (!dbfile)
8198             API_ERROR(NULL, E_NOFILE);
8199         if (SILO_Globals.enableGrabDriver == TRUE)
8200             API_ERROR("DBPutMultimat", E_GRABBED) ;
8201         if (!name || !*name)
8202             API_ERROR("multimat name", E_BADARGS);
8203         if (db_VariableNameValid(name) == 0)
8204             API_ERROR("multimat name", E_INVALIDNAME);
8205         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8206             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8207         if (nmats < 0)
8208             API_ERROR("nmats", E_BADARGS);
8209         if (!matnames && nmats && (!optlist ||
8210              (!DBGetOption(optlist, DBOPT_MB_FILE_NS) &&
8211               !DBGetOption(optlist, DBOPT_MB_BLOCK_NS))))
8212             API_ERROR("material-names", E_BADARGS);
8213         if (!dbfile->pub.p_mt)
8214             API_ERROR(dbfile->pub.name, E_NOTIMP);
8215 
8216         retval = (dbfile->pub.p_mt) (dbfile, name, nmats, matnames,
8217                                      optlist);
8218 
8219         /* Zero out the _mm._matnames pointer so we can't accidentially use it
8220          * again. Likewise for matcolors. */
8221         _mm._matnames = NULL;
8222         _mm._matcolors = NULL;
8223 
8224         db_FreeToc(dbfile);
8225         API_RETURN(retval);
8226     }
8227     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8228 }
8229 
8230 /*-------------------------------------------------------------------------
8231  * Function:    DBPutMultimatspecies
8232  *
8233  * Purpose:     Writes a multi-material object to the database.
8234  *
8235  * Return:      Success:        object ID
8236  *
8237  *              Failure:        -1
8238  *
8239  * Programmer:  Jeremy S. Meredith
8240  *              Sept 17 1998
8241  *
8242  * Modifications:
8243  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8244  *    Added a check for variable name validity.
8245  *
8246  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8247  *    Made the error messages a little better.
8248  *
8249  *    Robb Matzke, 2000-05-23
8250  *    The old table of contents is discarded if the directory changes.
8251  *
8252  *    Mark C. Miller, Wed Jul 14 20:36:23 PDT 2010
8253  *    Added support for nameschemes on multi-block objects. This meant
8254  *    adjusting sanity checks for args as some can be null now.
8255  *-------------------------------------------------------------------------*/
8256 PUBLIC int
DBPutMultimatspecies(DBfile * dbfile,const char * name,int nspec,char const * const * specnames,DBoptlist const * optlist)8257 DBPutMultimatspecies(DBfile *dbfile, const char *name, int nspec,
8258                      char const * const *specnames, DBoptlist const *optlist)
8259 {
8260     int retval;
8261 
8262     API_BEGIN2("DBPutMultimatspecies", int, -1, name) {
8263         if (!dbfile)
8264             API_ERROR(NULL, E_NOFILE);
8265         if (SILO_Globals.enableGrabDriver == TRUE)
8266             API_ERROR("DBPutMultimatspecies", E_GRABBED) ;
8267         if (!name || !*name)
8268             API_ERROR("multimatspecies name", E_BADARGS);
8269         if (db_VariableNameValid(name) == 0)
8270             API_ERROR("multimatspecies name", E_INVALIDNAME);
8271         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8272             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8273         if (nspec < 0)
8274             API_ERROR("nspec", E_BADARGS);
8275         if (!specnames && nspec && (!optlist ||
8276              (!DBGetOption(optlist, DBOPT_MB_FILE_NS) &&
8277               !DBGetOption(optlist, DBOPT_MB_BLOCK_NS))))
8278             API_ERROR("species-names", E_BADARGS);
8279         if (!dbfile->pub.p_mms)
8280             API_ERROR(dbfile->pub.name, E_NOTIMP);
8281 
8282         retval = (dbfile->pub.p_mms) (dbfile, name, nspec, specnames, optlist);
8283 
8284         /* Zero out the _ma._matnames pointer so we can't accidentially use it
8285          * again. Likewise for matcolors. */
8286         _mm._specnames = NULL;
8287         _mm._speccolors = NULL;
8288 
8289         db_FreeToc(dbfile);
8290         API_RETURN(retval);
8291     }
8292     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8293 }
8294 
8295 /*-------------------------------------------------------------------------
8296  * Function:    DBPutPoinmesh
8297  *
8298  * Purpose:     Accepts pointers to the coordinate arrays and writes the
8299  *              mesh into the database.
8300  *
8301  * Return:      Success:        object ID
8302  *
8303  *              Failure:        -1
8304  *
8305  * Programmer:  matzke@viper
8306  *              Tue Nov  8 12:32:43 PST 1994
8307  *
8308  * Modifications:
8309  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8310  *    I replaced API_END with API_END_NOPOP.
8311  *
8312  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8313  *    Added a check for variable name validity.
8314  *
8315  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8316  *    Made the error messages a little better.
8317  *
8318  *    Robb Matzke, 2000-05-23
8319  *    The old table of contents is discarded if the directory changes.
8320  *-------------------------------------------------------------------------*/
8321 PUBLIC int
DBPutPointmesh(DBfile * dbfile,const char * name,int ndims,DBVCP2_t coords,int nels,int datatype,DBoptlist const * optlist)8322 DBPutPointmesh(DBfile *dbfile, const char *name, int ndims, DBVCP2_t coords,
8323                int nels, int datatype, DBoptlist const *optlist)
8324 {
8325     int retval;
8326 
8327     API_BEGIN2("DBPutPointmesh", int, -1, name) {
8328         if (!dbfile)
8329             API_ERROR(NULL, E_NOFILE);
8330         if (SILO_Globals.enableGrabDriver == TRUE)
8331             API_ERROR("DBPutPointmesh", E_GRABBED) ;
8332         if (!name || !*name)
8333             API_ERROR("pointmesh name", E_BADARGS);
8334         if (db_VariableNameValid(name) == 0)
8335             API_ERROR("pointmesh name", E_INVALIDNAME);
8336         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8337             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8338         if (nels < 0)
8339             API_ERROR("nels<0", E_BADARGS);
8340         if (nels > 0)
8341         {
8342             int i;
8343             void **coords2 = (void**) coords;
8344             if (ndims < 1 || ndims > 3)
8345                 API_ERROR("ndims < 1 || ndims > 3", E_BADARGS);
8346             for (i = 0; i < ndims && coords; i++)
8347                 if (coords2[i] == 0) coords = 0;
8348             if (!coords)
8349                 API_ERROR("coords=0 || coords[i]=0 for some i", E_BADARGS);
8350         }
8351         else if (!SILO_Globals.allowEmptyObjects)
8352         {
8353             API_ERROR("nels==0", E_EMPTYOBJECT);
8354         }
8355 
8356         if (!dbfile->pub.p_pm)
8357             API_ERROR(dbfile->pub.name, E_NOTIMP);
8358 
8359         retval = (dbfile->pub.p_pm) (dbfile, name, ndims, coords, nels,
8360                                      datatype, optlist);
8361         db_FreeToc(dbfile);
8362         API_RETURN(retval);
8363     }
8364     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8365 }
8366 
8367 /*-------------------------------------------------------------------------
8368  * Function:    DBPutPointvar
8369  *
8370  * Purpose:     Accepts pointers to the value arrays and writes the
8371  *              variables into a point-variable object in the database.
8372  *
8373  * Return:      Success:        object ID
8374  *
8375  *              Failure:        -1
8376  *
8377  * Programmer:  matzke@viper
8378  *              Tue Nov  8 12:38:22 PST 1994
8379  *
8380  * Modifications:
8381  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8382  *    I replaced API_END with API_END_NOPOP.
8383  *
8384  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8385  *    Added a check for variable name validity.
8386  *
8387  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8388  *    Made the error messages a little better.
8389  *
8390  *    Robb Matzke, 2000-05-23
8391  *    The old table of contents is discarded if the directory changes.
8392  *-------------------------------------------------------------------------*/
8393 PUBLIC int
DBPutPointvar(DBfile * dbfile,const char * vname,const char * mname,int nvars,DBVCP2_t vars,int nels,int datatype,DBoptlist const * optlist)8394 DBPutPointvar(DBfile *dbfile, const char *vname, const char *mname, int nvars,
8395               DBVCP2_t vars, int nels, int datatype, DBoptlist const *optlist)
8396 {
8397     int retval;
8398 
8399     API_BEGIN2("DBPutPointvar", int, -1, vname) {
8400         if (!dbfile)
8401             API_ERROR(NULL, E_NOFILE);
8402         if (SILO_Globals.enableGrabDriver == TRUE)
8403             API_ERROR("DBPutPointvar", E_GRABBED) ;
8404         if (!vname || !*vname)
8405             API_ERROR("pointvar name", E_BADARGS);
8406         if (db_VariableNameValid(vname) == 0)
8407             API_ERROR("pointvar name", E_INVALIDNAME);
8408         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, vname))
8409             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8410         if (nels < 0)
8411             API_ERROR("nels<0", E_BADARGS);
8412         if (nels)
8413         {
8414             int i;
8415             void **vars2 = (void**) vars;
8416             if (nvars <= 0)
8417                 API_ERROR("nvars<=0", E_BADARGS);
8418             for (i = 0; i < nvars && vars; i++)
8419                 if (!vars2[i]) vars = 0;
8420             if (!vars) API_ERROR("vars==0 || vars[i]==0", E_BADARGS);
8421             if (!mname || !*mname)
8422                 API_ERROR("pointmesh name", E_BADARGS);
8423             if (db_VariableNameValid(mname) == 0)
8424                 API_ERROR("pointmesh name", E_INVALIDNAME);
8425         }
8426         else if (!SILO_Globals.allowEmptyObjects)
8427         {
8428             API_ERROR("nels=0", E_EMPTYOBJECT);
8429         }
8430 
8431         if (!dbfile->pub.p_pv)
8432             API_ERROR(dbfile->pub.name, E_NOTIMP);
8433 
8434         retval = (dbfile->pub.p_pv) (dbfile, vname, mname,
8435                                      nvars, vars, nels, datatype, optlist);
8436         db_FreeToc(dbfile);
8437         API_RETURN(retval);
8438     }
8439     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8440 }
8441 
8442 /*-------------------------------------------------------------------------
8443  * Function:    DBPutPointvar1
8444  *
8445  * Purpose:     Same as DBPutPointvar except only one variable at a time.
8446  *
8447  * Return:      Success:        Object ID
8448  *
8449  *              Failure:        -1
8450  *
8451  * Programmer:  matzke@viper
8452  *              Tue Nov  8 12:46:01 PST 1994
8453  *
8454  * Modifications:
8455  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8456  *    I replaced API_END with API_END_NOPOP.
8457  *
8458  *    Robb Matzke, 2000-05-23
8459  *    The old table of contents is discarded if the directory changes.
8460  *-------------------------------------------------------------------------*/
8461 PUBLIC int
DBPutPointvar1(DBfile * dbfile,const char * vname,const char * mname,DBVCP1_t var,int nels,int datatype,DBoptlist const * optlist)8462 DBPutPointvar1(DBfile *dbfile, const char *vname, const char *mname,
8463                DBVCP1_t var, int nels, int datatype, DBoptlist const *optlist)
8464 {
8465     DBVCP1_t vars[1] = {var};
8466     int retval;
8467 
8468     API_BEGIN2("DBPutPointvar1", int, -1, vname)
8469     {
8470         retval = DBPutPointvar(dbfile, vname, mname, 1, vars,
8471                                nels, datatype, optlist);
8472         db_FreeToc(dbfile);
8473         API_RETURN(retval);
8474     }
8475     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8476 }
8477 
8478 /*-------------------------------------------------------------------------
8479  * Function:    DBPutQuadmesh
8480  *
8481  * Purpose:     Accepts pointers to the coordinate arrays and writes the
8482  *              mesh into a quad-mesh object in the database.
8483  *
8484  * Return:      Success:        Object ID
8485  *
8486  *              Failure:        -1
8487  *
8488  * Programmer:  matzke@viper
8489  *              Tue Nov  8 12:50:40 PST 1994
8490  *
8491  * Modifications:
8492  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8493  *    I replaced API_END with API_END_NOPOP.
8494  *
8495  *    Sean Ahern, Mon Nov  2 17:51:55 PST 1998
8496  *    Removed the requirement for a non-NULL coordnames parameter.
8497  *
8498  *    Sean Ahern, Wed Mar 17 10:12:39 PST 1999
8499  *    Added a check for the coordtype.  It must be DB_COLLINEAR or
8500  *    DB_NONCOLLINEAR.
8501  *
8502  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8503  *    Added a check for variable name validity.
8504  *
8505  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8506  *    Made the error messages a little better.
8507  *
8508  *    Robb Matzke, 2000-05-23
8509  *    The old table of contents is discarded if the directory changes.
8510  *-------------------------------------------------------------------------*/
8511 PUBLIC int
DBPutQuadmesh(DBfile * dbfile,const char * name,char const * const * coordnames,DBVCP2_t coords,int const * dims,int ndims,int datatype,int coordtype,DBoptlist const * optlist)8512 DBPutQuadmesh(DBfile *dbfile, const char *name, char const * const *coordnames,
8513               DBVCP2_t coords, int const *dims, int ndims, int datatype,
8514               int coordtype, DBoptlist const *optlist)
8515 {
8516     int i, retval, is_empty=1;
8517 
8518     API_BEGIN2("DBPutQuadmesh", int, -1, name) {
8519         if (!dbfile)
8520             API_ERROR(NULL, E_NOFILE);
8521         if (SILO_Globals.enableGrabDriver == TRUE)
8522             API_ERROR("DBPutQuadmesh", E_GRABBED) ;
8523         if (!name || !*name)
8524             API_ERROR("quadmesh name", E_BADARGS);
8525         if (db_VariableNameValid(name) == 0)
8526             API_ERROR("quadmesh name", E_INVALIDNAME);
8527         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8528             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8529         if ((coordtype != DB_COLLINEAR) && (coordtype != DB_NONCOLLINEAR))
8530             API_ERROR("coordtype must be DB_COLLINEAR or DB_NONCOLLINEAR", E_BADARGS);
8531         if (ndims < 0)
8532             API_ERROR("ndims", E_BADARGS);
8533         if (!dims)
8534             API_ERROR("dims==0", E_BADARGS);
8535         for (i = 0; i < ndims; i++)
8536         {
8537             if (dims[i] != 0)
8538             {
8539                 is_empty = 0;
8540                 break;
8541             }
8542         }
8543         if (!is_empty)
8544         {
8545             void **coords2 = (void**) coords;
8546             for (i = 0; i < ndims && coords; i++)
8547                 if (!coords2[i]) coords = 0;
8548             if (!coords)
8549                 API_ERROR("coords==0 || coords[i]==0", E_BADARGS);
8550         }
8551         else if (!SILO_Globals.allowEmptyObjects)
8552         {
8553             /* this is an empty object but we don't think it was intentional */
8554             API_ERROR("dims[i]==0 for all i", E_EMPTYOBJECT);
8555         }
8556         if (!dbfile->pub.p_qm)
8557             API_ERROR(dbfile->pub.name, E_NOTIMP);
8558 
8559         retval = (dbfile->pub.p_qm) (dbfile, name, coordnames, coords,
8560                                      dims, ndims, datatype, coordtype,
8561                                      optlist);
8562         db_FreeToc(dbfile);
8563         API_RETURN(retval);
8564     }
8565     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8566 }
8567 
8568 /*-------------------------------------------------------------------------
8569  * Function:    DBPutQuadvar
8570  *
8571  * Purpose:     Writes a variable associated with a quad mesh into a
8572  *              database. Variables will be either node-centered or zone-
8573  *              centered.
8574  *
8575  * Return:      Success:        Object ID
8576  *
8577  *              Failure:        -1
8578  *
8579  * Programmer:  matzke@viper
8580  *              Tue Nov  8 12:57:08 PST 1994
8581  *
8582  * Modifications:
8583  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8584  *    I replaced API_END with API_END_NOPOP.
8585  *
8586  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8587  *    Added a check for variable name validity.
8588  *
8589  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8590  *    Made the error messages a little better.
8591  *
8592  *    Robb Matzke, 2000-05-23
8593  *    The old table of contents is discarded if the directory changes.
8594  *
8595  *    Mark C. Miller, Wed Nov 11 09:19:20 PST 2009
8596  *    Added check for valid centering.
8597  *
8598  *    Mark C. Miller, Thu Feb  4 11:29:35 PST 2010
8599  *    Removed upper bound restriction for nvars.
8600  *-------------------------------------------------------------------------*/
8601 PUBLIC int
DBPutQuadvar(DBfile * dbfile,const char * vname,const char * mname,int nvars,char const * const * varnames,DBVCP2_t vars,int const * dims,int ndims,DBVCP2_t mixvars,int mixlen,int datatype,int centering,DBoptlist const * optlist)8602 DBPutQuadvar(DBfile *dbfile, const char *vname, const char *mname, int nvars,
8603              char const * const *varnames, DBVCP2_t vars, int const *dims, int ndims,
8604              DBVCP2_t mixvars, int mixlen, int datatype, int centering,
8605              DBoptlist const *optlist)
8606 {
8607     int i, retval, is_empty = 1;
8608 
8609     API_BEGIN2("DBPutQuadvar", int, -1, vname) {
8610         if (!dbfile)
8611             API_ERROR(NULL, E_NOFILE);
8612         if (SILO_Globals.enableGrabDriver == TRUE)
8613             API_ERROR("DBPutQuadvar", E_GRABBED) ;
8614         if (!vname || !*vname)
8615             API_ERROR("quadvar name", E_BADARGS);
8616         if (db_VariableNameValid(vname) == 0)
8617             API_ERROR("quadvar name", E_INVALIDNAME);
8618         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, vname))
8619             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8620         if (!mname || !*mname)
8621             API_ERROR("quadmesh name", E_BADARGS);
8622         if (db_VariableNameValid(mname) == 0)
8623             API_ERROR("quadmesh name", E_INVALIDNAME);
8624         if (ndims < 0)
8625             API_ERROR("ndims", E_BADARGS);
8626         if (!dims)
8627             API_ERROR("dims==0", E_BADARGS);
8628         for (i = 0; i < ndims; i++)
8629         {
8630             if (dims[i] != 0)
8631             {
8632                 is_empty = 0;
8633                 break;
8634             }
8635         }
8636         if (!is_empty)
8637         {
8638             int i;
8639             void **vars2 = (void**) vars;
8640             for (i = 0; i < ndims && dims; i++)
8641                 if (!dims[i]) dims = 0;
8642             if (!dims)
8643                 API_ERROR("dims=0 || dims[i]=0", E_BADARGS);
8644             if (nvars < 1)
8645                 API_ERROR("nvars<1", E_BADARGS);
8646             for (i = 0; i < nvars && vars; i++)
8647                 if (!vars2[i]) vars = 0;
8648             vars2 = (void**) mixvars;
8649             for (i = 0; i < nvars && mixvars; i++)
8650                 if (!vars2[i]) mixvars = 0;
8651             for (i = 0; i < nvars && varnames; i++)
8652                 if (!varnames[i] && !*varnames[i]) varnames = 0;
8653             if (!vars)
8654                 API_ERROR("vars=0 || vars[i]=0", E_BADARGS);
8655             if (!varnames)
8656                 API_ERROR("varnames=0 || varnames[i]=0||\"\"", E_BADARGS);
8657             if (mixlen < 0)
8658                 API_ERROR("mixlen", E_BADARGS);
8659             if (!mixvars && mixlen)
8660                 API_ERROR("mixvars", E_BADARGS);
8661         }
8662         else if (!SILO_Globals.allowEmptyObjects)
8663         {
8664             /* this is an empty object but we don't think it was intentional */
8665             API_ERROR("ndims=0", E_EMPTYOBJECT);
8666         }
8667         if (centering != DB_NODECENT && centering != DB_ZONECENT &&
8668             centering != DB_FACECENT && centering != DB_BNDCENT &&
8669             centering != DB_EDGECENT && centering != DB_BLOCKCENT)
8670             API_ERROR("centering", E_BADARGS);
8671         if (!dbfile->pub.p_qv)
8672             API_ERROR(dbfile->pub.name, E_NOTIMP);
8673 
8674 
8675         retval = (dbfile->pub.p_qv) (dbfile, vname, mname,
8676                                      nvars, varnames, vars, dims, ndims,
8677                                      mixvars, mixlen, datatype, centering,
8678                                      optlist);
8679         db_FreeToc(dbfile);
8680         API_RETURN(retval);
8681     }
8682     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8683 }
8684 
8685 /*-------------------------------------------------------------------------
8686  * Function:    DBPutQuadvar1
8687  *
8688  * Purpose:     Same as DBPutQuadvar except for scalar variables.
8689  *
8690  * Return:      Success:        Object ID
8691  *
8692  *              Failure:        -1
8693  *
8694  * Programmer:  matzke@viper
8695  *              Tue Nov  8 13:07:45 PST 1994
8696  *
8697  * Modifications:
8698  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8699  *    I replaced API_END with API_END_NOPOP.
8700  *
8701  *    Robb Matzke, 2000-05-23
8702  *    The old table of contents is discarded if the directory changes.
8703  *-------------------------------------------------------------------------*/
8704 PUBLIC int
DBPutQuadvar1(DBfile * dbfile,const char * vname,const char * mname,void const * var,int const * dims,int ndims,void const * mixvar,int mixlen,int datatype,int centering,DBoptlist const * optlist)8705 DBPutQuadvar1(DBfile *dbfile, const char *vname, const char *mname, void const *var,
8706               int const *dims, int ndims, void const *mixvar, int mixlen, int datatype,
8707               int centering, DBoptlist const *optlist)
8708 {
8709     char const *varnames[1];
8710     void const *vars[1] = {var};
8711     void const *mixvars[1] = {var};
8712     int retval;
8713 
8714     API_BEGIN2("DBPutQuadvar1", int, -1, vname) {
8715         varnames[0] = vname;
8716         vars[0] = var;
8717         mixvars[0] = mixvar;
8718 
8719         retval = DBPutQuadvar(dbfile, vname, mname, 1,
8720                               varnames, vars, dims, ndims,
8721                               mixvars, mixlen,
8722                               datatype, centering, optlist);
8723         db_FreeToc(dbfile);
8724         API_RETURN(retval);
8725     }
8726     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8727 }
8728 
8729 /*-------------------------------------------------------------------------
8730  * Function:    DBPutUcdmesh
8731  *
8732  * Purpose:     Accepts pointers to the coordinate arrays and writes
8733  *              the mesh into a UCD-mesh object in the database.
8734  *
8735  * Return:      Success:        Object ID
8736  *
8737  *              Failure:        -1
8738  *
8739  * Programmer:  matzke@viper
8740  *              Tue Nov  8 13:13:46 PST 1994
8741  *
8742  * Modifications:
8743  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8744  *    I replaced API_END with API_END_NOPOP.
8745  *
8746  *    Sean Ahern, Mon Nov  2 17:51:55 PST 1998
8747  *    Removed the requirement for a non-NULL coordnames parameter.
8748  *
8749  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8750  *    Added a check for variable name validity.
8751  *
8752  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8753  *    Made the error messages a little better.
8754  *
8755  *    Robb Matzke, 2000-05-23
8756  *    The old table of contents is discarded if the directory changes.
8757  *-------------------------------------------------------------------------*/
8758 PUBLIC int
DBPutUcdmesh(DBfile * dbfile,const char * name,int ndims,char const * const * coordnames,DBVCP2_t coords,int nnodes,int nzones,const char * zonel_name,const char * facel_name,int datatype,DBoptlist const * optlist)8759 DBPutUcdmesh(DBfile *dbfile, const char *name, int ndims,
8760              char const * const *coordnames, DBVCP2_t coords, int nnodes,
8761              int nzones, const char *zonel_name, const char *facel_name,
8762              int datatype, DBoptlist const *optlist)
8763 {
8764     int retval;
8765     char *zl_name;
8766 
8767     API_BEGIN2("DBPutUcdmesh", int, -1, name) {
8768         if (!dbfile)
8769             API_ERROR(NULL, E_NOFILE);
8770         if (SILO_Globals.enableGrabDriver == TRUE)
8771             API_ERROR("DBPutUcdmesh", E_GRABBED) ;
8772         if (!name || !*name)
8773             API_ERROR("UCDmesh name", E_BADARGS);
8774         if (db_VariableNameValid(name) == 0)
8775             API_ERROR("UCDmesh name", E_INVALIDNAME);
8776         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8777             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8778         if (ndims < 0)
8779             API_ERROR("ndims<0", E_BADARGS);
8780         if (nnodes < 0)
8781             API_ERROR("nnodes<0", E_BADARGS);
8782         if (nnodes)
8783         {
8784             int i;
8785             void **coords2 = (void**) coords;
8786             if (nzones <= 0)
8787                 API_ERROR("nzones<=0", E_BADARGS);
8788             for (i = 0; i < ndims && coords; i++)
8789                 if (coords2[i] == 0) coords = 0;;
8790             if (!coords)
8791                 API_ERROR("coords==0 || coords[i]==0", E_BADARGS);
8792             if ((zl_name = (char*)DBGetOption(optlist, DBOPT_PHZONELIST)))
8793             {
8794                 if (!zl_name || !*zl_name)
8795                     API_ERROR("zonelist name specified with DBOPT_PHZONELIST is null or \"\"", E_BADARGS);
8796                 if (db_VariableNameValid(zl_name) == 0)
8797                     API_ERROR("zonelist name specified with DBOPT_PHZONELIST", E_INVALIDNAME);
8798             }
8799             else if (zonel_name)
8800             {
8801                 if (!*zonel_name)
8802                     API_ERROR("zonel_name==\"\"", E_BADARGS);
8803                 if (db_VariableNameValid(zonel_name) == 0)
8804                     API_ERROR("zonel_name", E_INVALIDNAME);
8805             }
8806             else if (facel_name)
8807             {
8808                 if (!*facel_name)
8809                     API_ERROR("facel_name==\"\"", E_BADARGS);
8810                 if (db_VariableNameValid(facel_name) == 0)
8811                     API_ERROR("facel_name", E_INVALIDNAME);
8812             }
8813             else
8814             {
8815                 API_ERROR("no zonelist or facelist specified", E_BADARGS);
8816             }
8817         }
8818         else if (!SILO_Globals.allowEmptyObjects)
8819         {
8820             /* this is an empty object but we don't know if it was intentional */
8821             API_ERROR("ndims==0 || nnodes==0", E_EMPTYOBJECT);
8822         }
8823 
8824         if (!dbfile->pub.p_um)
8825             API_ERROR(dbfile->pub.name, E_NOTIMP);
8826 
8827         retval = (dbfile->pub.p_um) (dbfile, name, ndims, coordnames,
8828                                      coords, nnodes, nzones,
8829                                      zonel_name, facel_name,
8830                                      datatype, optlist);
8831         db_FreeToc(dbfile);
8832         API_RETURN(retval);
8833     }
8834     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8835 }
8836 
8837 /*-------------------------------------------------------------------------
8838  * Function:    DBPutUcdsubmesh
8839  *
8840  * Purpose:     Accepts names of parent mesh with coordinate arrays and writes
8841  *              the mesh into a UCD-mesh object in the database.
8842  *
8843  * Return:      Success:        Object ID
8844  *
8845  *              Failure:        -1
8846  *
8847  * Programmer:  reus@ferret
8848  *              Wed Dec  9 15:17:00 PST 1998
8849  *
8850  * Modifications:
8851  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8852  *    Added a check for variable name validity.
8853  *
8854  *    Robb Matzke, 2000-05-23
8855  *    The old table of contents is discarded if the directory changes.
8856  *-------------------------------------------------------------------------*/
8857 PUBLIC int
DBPutUcdsubmesh(DBfile * dbfile,const char * name,const char * parentmesh,int nzones,const char * zonel_name,const char * facel_name,DBoptlist const * optlist)8858 DBPutUcdsubmesh(DBfile *dbfile, const char *name, const char *parentmesh,
8859                 int nzones, const char *zonel_name, const char *facel_name,
8860                 DBoptlist const *optlist)
8861 {
8862     int retval;
8863 
8864     API_DEPRECATE2("DBPutUcdsubmesh", int, -1, name, 4, 6, "MRG Trees") {
8865         if (!dbfile)
8866             API_ERROR(NULL, E_NOFILE);
8867         if (SILO_Globals.enableGrabDriver == TRUE)
8868             API_ERROR("DBPutUcdsubmesh", E_GRABBED) ;
8869         if (!name || !*name)
8870             API_ERROR("mesh name", E_BADARGS);
8871         if (db_VariableNameValid(name) == 0)
8872             API_ERROR("mesh name", E_INVALIDNAME);
8873         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
8874             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8875         if (!parentmesh || !*parentmesh)
8876             API_ERROR("parent mesh name", E_BADARGS);
8877         if (db_VariableNameValid(parentmesh) == 0)
8878             API_ERROR("parent mesh name", E_INVALIDNAME);
8879         if (nzones < 0)
8880             API_ERROR("nzones", E_BADARGS);
8881         if (!dbfile->pub.p_sm)
8882             API_ERROR(dbfile->pub.name, E_NOTIMP);
8883 
8884 
8885         retval = (dbfile->pub.p_sm) (dbfile, name, parentmesh,
8886                                      nzones, zonel_name,
8887                                      facel_name, optlist);
8888         db_FreeToc(dbfile);
8889         API_RETURN(retval);
8890     }
8891     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
8892 }
8893 
8894 /*-------------------------------------------------------------------------
8895  * Function:    DBPutUcdvar
8896  *
8897  * Purpose:     Writes a variable associated with a UCD mesh into the
8898  *              database.  Note that variables will be either node-centered
8899  *              or zone-centered.  A UCD-var object contains the variable
8900  *              values, plus the object ID of the associated UCD mesh.  Other
8901  *              information can also be included.  This function is useful
8902  *              for writing vector and tensor fields, wereas the companion
8903  *              function, DBPutUcdvar1(), is appropriate for writing
8904  *              scalar fields.
8905  *
8906  * Return:      Success:        Object ID
8907  *
8908  *              Failure:        -1
8909  *
8910  * Programmer:  robb@cloud
8911  *              Wed Nov  9 12:02:56 EST 1994
8912  *
8913  * Modifications:
8914  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
8915  *    I replaced API_END with API_END_NOPOP.
8916  *
8917  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
8918  *    Added a check for variable name validity.
8919  *
8920  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
8921  *    Made the error messages a little better.
8922  *
8923  *    Robb Matzke, 2000-05-23
8924  *    The old table of contents is discarded if the directory changes.
8925  *
8926  *    Mark C. Miller, Wed Nov 11 09:19:20 PST 2009
8927  *    Added check for valid centering.
8928  *
8929  *    Mark C. Miller, Thu Feb  4 11:28:55 PST 2010
8930  *    Removed upper bound restriction on nvars.
8931  *-------------------------------------------------------------------------*/
8932 PUBLIC int
DBPutUcdvar(DBfile * dbfile,const char * vname,const char * mname,int nvars,char const * const * varnames,DBVCP2_t vars,int nels,DBVCP2_t mixvars,int mixlen,int datatype,int centering,DBoptlist const * optlist)8933 DBPutUcdvar(DBfile *dbfile, const char *vname, const char *mname, int nvars,
8934             char const * const *varnames, DBVCP2_t vars, int nels, DBVCP2_t mixvars,
8935             int mixlen, int datatype, int centering, DBoptlist const *optlist)
8936 {
8937     int retval;
8938 
8939     API_BEGIN2("DBPutUcdvar", int, -1, vname) {
8940         if (!dbfile)
8941             API_ERROR(NULL, E_NOFILE);
8942         if (SILO_Globals.enableGrabDriver == TRUE)
8943             API_ERROR("DBPutUcdvar", E_GRABBED) ;
8944         if (!vname || !*vname)
8945             API_ERROR("UCDvar name", E_BADARGS);
8946         if (db_VariableNameValid(vname) == 0)
8947             API_ERROR("UCDvar name", E_INVALIDNAME);
8948         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, vname))
8949             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
8950         if (!mname || !*mname)
8951             API_ERROR("UCDmesh name", E_BADARGS);
8952         if (db_VariableNameValid(mname) == 0)
8953             API_ERROR("UCDmesh name", E_INVALIDNAME);
8954         if (nels < 0)
8955             API_ERROR("nels<0", E_BADARGS);
8956         if (nels)
8957         {
8958             int i;
8959             void **vars2 = (void**) vars;
8960             if (nvars <= 0)
8961                 API_ERROR("nvars<0", E_BADARGS);
8962             for (i = 0; i < nvars && vars; i++)
8963                 if (vars2[i] == 0) vars = 0;
8964             for (i = 0; i < nvars && varnames; i++)
8965                 if (!varnames[i] && !*varnames[i]) varnames = 0;
8966             if (mixlen < 0)
8967                 API_ERROR("mixlen", E_BADARGS);
8968             if (mixvars)
8969             {
8970                 vars2 = (void**) mixvars;
8971                 for (i = 0; i < nvars && mixvars; i++)
8972                     if (vars2[i] == 0) mixvars = 0;
8973             }
8974             if (!vars)
8975                 API_ERROR("vars=0 || vars[i]=0", E_BADARGS);
8976             if (!varnames)
8977                 API_ERROR("varnames=0 || varnames[i]=0", E_BADARGS);
8978             if (mixlen && !mixvars)
8979                 API_ERROR("mixvars=0 || mixvars[i]=0", E_BADARGS);
8980         }
8981         else if (!SILO_Globals.allowEmptyObjects)
8982         {
8983             /* this is an empty object but we don't know if it was intentional */
8984             API_ERROR("nvars=0 || nels==0", E_EMPTYOBJECT);
8985         }
8986         if (centering != DB_NODECENT && centering != DB_ZONECENT &&
8987             centering != DB_FACECENT && centering != DB_BNDCENT &&
8988             centering != DB_EDGECENT && centering != DB_BLOCKCENT)
8989             API_ERROR("centering", E_BADARGS);
8990         if (!dbfile->pub.p_uv)
8991             API_ERROR(dbfile->pub.name, E_NOTIMP);
8992 
8993         retval = (dbfile->pub.p_uv) (dbfile, vname, mname,
8994                                      nvars, varnames, vars, nels, mixvars,
8995                                      mixlen, datatype, centering, optlist);
8996         db_FreeToc(dbfile);
8997         API_RETURN(retval);
8998     }
8999     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9000 }
9001 
9002 /*-------------------------------------------------------------------------
9003  * Function:    DBPutUcdvar1
9004  *
9005  * Purpose:     Same as DBPutUcdvar() except for scalar variables.
9006  *
9007  * Return:      Success:        Object ID
9008  *
9009  *              Failure:        -1
9010  *
9011  * Programmer:  robb@cloud
9012  *              Wed Nov  9 12:14:28 EST 1994
9013  *
9014  * Modifications:
9015  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
9016  *    I replaced API_END with API_END_NOPOP.
9017  *
9018  *    Robb Matzke, 2000-05-23
9019  *    The old table of contents is discarded if the directory changes.
9020  *-------------------------------------------------------------------------*/
9021 PUBLIC int
DBPutUcdvar1(DBfile * dbfile,const char * vname,const char * mname,void const * var,int nels,void const * mixvar,int mixlen,int datatype,int centering,DBoptlist const * optlist)9022 DBPutUcdvar1(DBfile *dbfile, const char *vname, const char *mname, void const *var,
9023              int nels, void const *mixvar, int mixlen, int datatype, int centering,
9024              DBoptlist const *optlist)
9025 {
9026     void const *vars[1] = {var};
9027     void const *mixvars[1] = {mixvar};
9028     char const *varnames[1];
9029     int            retval;
9030 
9031     API_BEGIN2("DBPutUcdvar1", int, -1, vname)
9032     {
9033         varnames[0] = vname;
9034         vars[0] = var;
9035         mixvars[0] = mixvar;
9036         retval = DBPutUcdvar(dbfile, vname, mname, 1, varnames, vars,
9037                      nels, mixvars, mixlen, datatype, centering, optlist);
9038         db_FreeToc(dbfile);
9039         API_RETURN(retval);
9040     }
9041     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9042 }
9043 
9044 /*-------------------------------------------------------------------------
9045  * Function:    DBPutZonelist
9046  *
9047  * Purpose:     Writes a zonelist object into the open database.  The name
9048  *              assigned to this object can in turn be used as the
9049  *              `zonel_name' parameter to the DBPutUcdmesh() function.
9050  *
9051  * Return:      Success:        0
9052  *
9053  *              Failure:        -1
9054  *
9055  * Programmer:  robb@cloud
9056  *              Wed Nov  9 12:20:22 EST 1994
9057  *
9058  * Modifications:
9059  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
9060  *    I replaced API_END with API_END_NOPOP.
9061  *
9062  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
9063  *    Added a check for variable name validity.
9064  *
9065  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
9066  *    Made the error messages a little better.
9067  *
9068  *    Robb Matzke, 2000-05-23
9069  *    The old table of contents is discarded if the directory changes.
9070  *-------------------------------------------------------------------------*/
9071 PUBLIC int
DBPutZonelist(DBfile * dbfile,const char * name,int nzones,int ndims,int const * nodelist,int lnodelist,int origin,int const * shapesize,int const * shapecnt,int nshapes)9072 DBPutZonelist(DBfile *dbfile, const char *name, int nzones, int ndims,
9073               int const *nodelist, int lnodelist, int origin, int const *shapesize,
9074               int const *shapecnt, int nshapes)
9075 {
9076     int retval;
9077 
9078     API_DEPRECATE2("DBPutZonelist", int, -1, name, 4, 6, "DBPutZonelist2()") {
9079         if (!dbfile)
9080             API_ERROR(NULL, E_NOFILE);
9081         if (SILO_Globals.enableGrabDriver == TRUE)
9082             API_ERROR("DBPutZonelist", E_GRABBED) ;
9083         if (!name || !*name)
9084             API_ERROR("zonelist name", E_BADARGS);
9085         if (db_VariableNameValid(name) == 0)
9086             API_ERROR("zonelist name", E_INVALIDNAME);
9087         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
9088             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
9089         if (nzones < 0)
9090             API_ERROR("nzones", E_BADARGS);
9091         if (nzones)
9092         {
9093             if (ndims <= 0)
9094                 API_ERROR("ndims<=0", E_BADARGS);
9095             if (lnodelist <= 0)
9096                 API_ERROR("lnodelist<=", E_BADARGS);
9097             if (!nodelist)
9098                 API_ERROR("nodelist=0", E_BADARGS);
9099             if (0 != origin && 1 != origin)
9100                 API_ERROR("origin!=0||1", E_BADARGS);
9101             if (nshapes <= 0)
9102                 API_ERROR("nshapes<=0", E_BADARGS);
9103             if (!shapesize)
9104                 API_ERROR("shapesize=0", E_BADARGS);
9105             if (!shapecnt)
9106                 API_ERROR("shapecnt=0", E_BADARGS);
9107         }
9108         else if (!SILO_Globals.allowEmptyObjects)
9109         {
9110             /* this is an empty object but we don't know if it was intentional */
9111             API_ERROR("nzones=0", E_EMPTYOBJECT);
9112         }
9113         else
9114         {
9115             lnodelist = 0;
9116             nshapes = 0;
9117         }
9118         if (!dbfile->pub.p_zl)
9119             API_ERROR(dbfile->pub.name, E_NOTIMP);
9120 
9121         retval = (dbfile->pub.p_zl) (dbfile, name, nzones, ndims,
9122                                      nodelist, lnodelist, origin, shapesize,
9123                                      shapecnt, nshapes);
9124         db_FreeToc(dbfile);
9125         API_RETURN(retval);
9126     }
9127     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9128 }
9129 
9130 /*-------------------------------------------------------------------------
9131  * Function:    DBPutZonelist2
9132  *
9133  * Purpose:     Writes a zonelist object into the open database.  The name
9134  *              assigned to this object can in turn be used as the
9135  *              `zonel_name' parameter to the DBPutUcdmesh() function.
9136  *
9137  * Return:      Success:        0
9138  *
9139  *              Failure:        -1
9140  *
9141  * Programmer:  brugger@kickit
9142  *              Tue Mar 30 10:41:12 PST 1999
9143  *
9144  * Modifications:
9145  *    Jeremy Meredith, Fri May 21 10:04:25 PDT 1999
9146  *    Added an option list to the arguments and to the call to p_zl2().
9147  *
9148  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
9149  *    Added a check for variable name validity.
9150  *
9151  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
9152  *    Made the error messages a little better.
9153  *
9154  *    Robb Matzke, 2000-05-23
9155  *    The old table of contents is discarded if the directory changes.
9156  *-------------------------------------------------------------------------*/
9157 PUBLIC int
DBPutZonelist2(DBfile * dbfile,const char * name,int nzones,int ndims,int const * nodelist,int lnodelist,int origin,int lo_offset,int hi_offset,int const * shapetype,int const * shapesize,int const * shapecnt,int nshapes,DBoptlist const * optlist)9158 DBPutZonelist2(DBfile *dbfile, const char *name, int nzones, int ndims,
9159                int const *nodelist, int lnodelist, int origin, int lo_offset,
9160                int hi_offset, int const *shapetype, int const *shapesize, int const *shapecnt,
9161                int nshapes, DBoptlist const *optlist)
9162 {
9163     int retval;
9164 
9165     API_BEGIN2("DBPutZonelist2", int, -1, name) {
9166         if (!dbfile)
9167             API_ERROR(NULL, E_NOFILE);
9168         if (SILO_Globals.enableGrabDriver == TRUE)
9169             API_ERROR("DBPutZonelist2", E_GRABBED) ;
9170         if (!name || !*name)
9171             API_ERROR("zonelist name", E_BADARGS);
9172         if (db_VariableNameValid(name) == 0)
9173             API_ERROR("zonelist name", E_INVALIDNAME);
9174         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
9175             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
9176         if (nzones < 0)
9177             API_ERROR("nzones", E_BADARGS);
9178         if (nzones)
9179         {
9180             if (ndims <= 0)
9181                 API_ERROR("ndims<=0", E_BADARGS);
9182             if (lnodelist <= 0)
9183                 API_ERROR("lnodelist<=0", E_BADARGS);
9184             if (nshapes <= 0)
9185                 API_ERROR("nshapes<=0", E_BADARGS);
9186             if (!nodelist)
9187                 API_ERROR("nodelist=0", E_BADARGS);
9188             if (!shapetype)
9189                 API_ERROR("shapetype=0", E_BADARGS);
9190             if (!shapesize)
9191                 API_ERROR("shapesize=0", E_BADARGS);
9192             if (!shapecnt)
9193                 API_ERROR("shapecnt=0", E_BADARGS);
9194             if (0 != origin && 1 != origin)
9195                 API_ERROR("origin!=0||1", E_BADARGS);
9196             if (lo_offset < 0)
9197                 API_ERROR("lo_offset<0", E_BADARGS);
9198             if (hi_offset < 0)
9199                 API_ERROR("hi_offset<0", E_BADARGS);
9200 #ifndef _MSC_VER
9201 #warning HI AND LO OFFSET NOT VALID IN PRESENCE OF EXPLICIT GHOST LABELS
9202 #endif
9203         }
9204         else if (!SILO_Globals.allowEmptyObjects)
9205         {
9206             /* this is an empty object but we don't know if it was intentional */
9207             API_ERROR("nzones=0", E_EMPTYOBJECT);
9208         }
9209         else
9210         {
9211             lnodelist = 0;
9212             nshapes = 0;
9213         }
9214         if (!dbfile->pub.p_zl2)
9215             API_ERROR(dbfile->pub.name, E_NOTIMP);
9216         retval = (dbfile->pub.p_zl2) (dbfile, name, nzones, ndims,
9217                                       nodelist, lnodelist, origin, lo_offset,
9218                                       hi_offset, shapetype, shapesize,
9219                                       shapecnt, nshapes, optlist);
9220         db_FreeToc(dbfile);
9221         API_RETURN(retval);
9222     }
9223     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9224 }
9225 
9226 /*-------------------------------------------------------------------------
9227  * Function:    DBPutPHZonelist
9228  *
9229  * Purpose:     Writes a polyhedral zonelist object into the open database.
9230  *              The name assigned to this object can in turn be used as the
9231  *              parameter to a DBOPT_PHZONELIST option in the optlist passed to
9232  *              the DBPutUcdmesh() function.
9233  *
9234  * Return:      Success:        0
9235  *
9236  *              Failure:        -1
9237  *
9238  * Programmer:  Mark C. Miller
9239  *              Tuesday, July 26, 2004
9240  *
9241  *-------------------------------------------------------------------------*/
9242 PUBLIC int
DBPutPHZonelist(DBfile * dbfile,const char * name,int nfaces,int const * nodecnt,int lnodelist,int const * nodelist,const char * extface,int nzones,int const * facecnt,int lfacelist,int const * facelist,int origin,int lo_offset,int hi_offset,DBoptlist const * optlist)9243 DBPutPHZonelist(DBfile *dbfile, const char *name,
9244     int nfaces, int const *nodecnt, int lnodelist, int const *nodelist,
9245     const char *extface, int nzones, int const *facecnt, int lfacelist,
9246     int const *facelist, int origin, int lo_offset, int hi_offset,
9247     DBoptlist const *optlist)
9248 {
9249     int retval;
9250 
9251     API_BEGIN2("DBPutPHZonelist", int, -1, name) {
9252 
9253         if (!dbfile)
9254             API_ERROR(NULL, E_NOFILE);
9255         if (SILO_Globals.enableGrabDriver == TRUE)
9256             API_ERROR("DBPutPHZonelist", E_GRABBED) ;
9257         if (!name || !*name)
9258             API_ERROR("zonelist name", E_BADARGS);
9259         if (db_VariableNameValid(name) == 0)
9260             API_ERROR("zonelist name", E_INVALIDNAME);
9261         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
9262             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
9263         if (nfaces < 0)
9264             API_ERROR("nfaces<0", E_BADARGS);
9265         if (nfaces)
9266         {
9267             if (0 != origin && 1 != origin)
9268                 API_ERROR("origin", E_BADARGS);
9269             if (!nodecnt)
9270                 API_ERROR("nodecnt==0", E_BADARGS);
9271             if (!lnodelist)
9272                 API_ERROR("lnodelist==0", E_BADARGS);
9273             if (!nodelist)
9274                 API_ERROR("nodelist==0", E_BADARGS);
9275             if (nzones < 0)
9276                 API_ERROR("nzones<0", E_BADARGS);
9277             if (nzones)
9278             {
9279                 if ((lo_offset < 0) || (lo_offset >= nzones))
9280                     API_ERROR("lo_offset", E_BADARGS);
9281                 if ((hi_offset < 0) || (hi_offset >= nzones))
9282                     API_ERROR("hi_offset", E_BADARGS);
9283                 if (lo_offset > hi_offset)
9284                     API_ERROR("hi_offset", E_BADARGS);
9285                 if (!facecnt)
9286                     API_ERROR("facecnt==0", E_BADARGS);
9287                 if (!lfacelist)
9288                     API_ERROR("lfacelist==0", E_BADARGS);
9289                 if (!facelist)
9290                     API_ERROR("facelist==0", E_BADARGS);
9291             }
9292         }
9293         else if (!SILO_Globals.allowEmptyObjects)
9294         {
9295             /* this is an empty object but we don't know if it was intentional */
9296             API_ERROR("nfaces==0", E_EMPTYOBJECT);
9297         }
9298         if (!dbfile->pub.p_phzl)
9299             API_ERROR(dbfile->pub.name, E_NOTIMP);
9300 
9301         retval = (dbfile->pub.p_phzl) (dbfile, name, nfaces, nodecnt,
9302                                        lnodelist, nodelist, extface,
9303                                        nzones, facecnt, lfacelist, facelist,
9304                                        origin, lo_offset, hi_offset,
9305                                        optlist);
9306 
9307         db_FreeToc(dbfile);
9308         API_RETURN(retval);
9309     }
9310     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9311 }
9312 
9313 /*-------------------------------------------------------------------------
9314  * Function:    DBPutCsgmesh
9315  *
9316  * Purpose:     Writes a CSG (Constructive Solid Geometry) mesh object to
9317  *              a silo database.
9318  *
9319  * Return:      Success:        Object ID
9320  *
9321  *              Failure:        -1
9322  *
9323  * Programmer:  Mark C. Miller
9324  *              Wed Jul 27 14:22:03 PDT 2005
9325  *-------------------------------------------------------------------------*/
9326 PUBLIC int
DBPutCsgmesh(DBfile * dbfile,const char * name,int ndims,int nbounds,const int * typeflags,const int * bndids,const void * coeffs,int lcoeffs,int datatype,const double * extents,const char * zonel_name,DBoptlist const * optlist)9327 DBPutCsgmesh(DBfile *dbfile, const char *name, int ndims,
9328              int nbounds,
9329              const int *typeflags, const int *bndids/*optional*/,
9330              const void *coeffs, int lcoeffs, int datatype,
9331              const double *extents, const char *zonel_name, DBoptlist const *optlist)
9332 {
9333     int retval;
9334 
9335     API_BEGIN2("DBPutCsgmesh", int, -1, name) {
9336         if (!dbfile)
9337             API_ERROR(NULL, E_NOFILE);
9338         if (SILO_Globals.enableGrabDriver == TRUE)
9339             API_ERROR("DBPutCsgmesh", E_GRABBED) ;
9340         if (!name || !*name)
9341             API_ERROR("CSGmesh name", E_BADARGS);
9342         if (db_VariableNameValid(name) == 0)
9343             API_ERROR("CSGmesh name", E_INVALIDNAME);
9344         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
9345             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
9346         if (nbounds < 0)
9347             API_ERROR("nbounds<0", E_BADARGS);
9348         if (nbounds)
9349         {
9350             if (ndims < 0)
9351                 API_ERROR("ndims<0", E_BADARGS);
9352             if (lcoeffs < 0)
9353                 API_ERROR("lcoeffs<0", E_BADARGS);
9354             if (!(ndims == 2 || ndims == 3))
9355                 API_ERROR("ndims must be either 2 or 3", E_BADARGS);
9356             if (!typeflags) API_ERROR("typeflags==0", E_BADARGS);
9357             if (!coeffs) API_ERROR("coeffs==0", E_BADARGS);
9358             if (!extents) API_ERROR("extents==0", E_BADARGS);
9359             if (!zonel_name || !*zonel_name) API_ERROR("zonel_name", E_BADARGS);
9360             if (db_VariableNameValid(zonel_name) == 0)
9361                 API_ERROR("zonelist name", E_INVALIDNAME);
9362         }
9363         else if (!SILO_Globals.allowEmptyObjects)
9364         {
9365             API_ERROR("nbounds==0 || ndims==0 || lcoeffs==0", E_EMPTYOBJECT);
9366         }
9367         if (!dbfile->pub.p_csgm)
9368             API_ERROR(dbfile->pub.name, E_NOTIMP);
9369 
9370         retval = (dbfile->pub.p_csgm) (dbfile, name, ndims,
9371                                      nbounds, typeflags, bndids, coeffs,
9372                                      lcoeffs, datatype, extents, zonel_name,
9373                                      optlist);
9374 
9375         db_FreeToc(dbfile);
9376         API_RETURN(retval);
9377     }
9378     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9379 }
9380 
9381 /*-------------------------------------------------------------------------
9382  * Function:    DBGetCsgmesh
9383  *
9384  * Purpose:     Allocates a DBcsgmesh data structure and reads a CSG mesh
9385  *              from the data file.
9386  *
9387  * Return:      Success:        Pointer to the new DBcsgmesh struct
9388  *
9389  *              Failure:        NULL
9390  *
9391  * Programmer:  Mark C. Miller
9392  *              Wed Jul 27 14:22:03 PDT 2005
9393  *
9394  *-------------------------------------------------------------------------*/
9395 PUBLIC DBcsgmesh *
DBGetCsgmesh(DBfile * dbfile,const char * name)9396 DBGetCsgmesh(DBfile *dbfile, const char *name)
9397 {
9398     DBcsgmesh     *csgm = NULL;
9399 
9400     API_BEGIN2("DBGetCsgmesh", DBcsgmesh *, NULL, name) {
9401         if (!dbfile)
9402             API_ERROR(NULL, E_NOFILE);
9403         if (SILO_Globals.enableGrabDriver == TRUE)
9404             API_ERROR("DBGetCsgmesh", E_GRABBED) ;
9405         if (!name || !*name)
9406             API_ERROR("CSGmesh name", E_BADARGS);
9407         if (!dbfile->pub.g_csgm)
9408             API_ERROR(dbfile->pub.name, E_NOTIMP);
9409         csgm = ((dbfile->pub.g_csgm) (dbfile, name));
9410         if (!csgm)
9411         {
9412             API_RETURN(NULL);
9413         }
9414         API_RETURN(csgm);
9415     }
9416     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9417 }
9418 
9419 /*-------------------------------------------------------------------------
9420  * Function:    DBPutCSGZonelist
9421  *
9422  * Purpose:     Writes a CSG zonelist object into the open database.
9423  *              The name assigned to this object can in turn be used as the
9424  *              `zonel_name' parameter to the DBPutCsgmesh() function.
9425  *
9426  * Return:      Success:        0
9427  *
9428  *              Failure:        -1
9429  *
9430  * Programmer:  Mark C. Miller
9431  *              Wed Jul 27 14:22:03 PDT 2005
9432  *-------------------------------------------------------------------------*/
9433 
9434 PUBLIC int
DBPutCSGZonelist(DBfile * dbfile,const char * name,int nregs,const int * typeflags,const int * leftids,const int * rightids,const void * xforms,int lxforms,int datatype,int nzones,const int * zonelist,DBoptlist const * optlist)9435 DBPutCSGZonelist(DBfile *dbfile, const char *name, int nregs,
9436                  const int *typeflags,
9437                  const int *leftids, const int *rightids,
9438                  const void *xforms, int lxforms, int datatype,
9439                  int nzones, const int *zonelist, DBoptlist const *optlist)
9440 {
9441     int retval;
9442 
9443     API_BEGIN2("DBPutCSGZonelist", int, -1, name) {
9444         if (!dbfile)
9445             API_ERROR(NULL, E_NOFILE);
9446         if (SILO_Globals.enableGrabDriver == TRUE)
9447             API_ERROR("DBPutCSGZonelist", E_GRABBED) ;
9448         if (!name || !*name)
9449             API_ERROR("zonelist name", E_BADARGS);
9450         if (db_VariableNameValid(name) == 0)
9451             API_ERROR("zonelist name", E_INVALIDNAME);
9452         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
9453             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
9454         if (nzones)
9455         {
9456             if (nregs < 0)
9457                 API_ERROR("nregs", E_BADARGS);
9458             if (nzones < 0)
9459                 API_ERROR("nzones", E_BADARGS);
9460             if (!typeflags)
9461                 API_ERROR("typeflags", E_BADARGS);
9462             if (!leftids)
9463                 API_ERROR("leftids", E_BADARGS);
9464             if (!rightids)
9465                 API_ERROR("rightids", E_BADARGS);
9466             if (!zonelist)
9467                 API_ERROR("zonelist", E_BADARGS);
9468             if ((xforms && lxforms <= 0) || (!xforms && lxforms > 0))
9469                 API_ERROR("xforms and lxforms", E_BADARGS);
9470         }
9471         else if (!SILO_Globals.allowEmptyObjects)
9472         {
9473             /* this is an empty object but we don't know if it was intentional */
9474             API_ERROR("nregs==0 || nzones==0", E_EMPTYOBJECT);
9475         }
9476 
9477         if (!dbfile->pub.p_csgzl)
9478             API_ERROR(dbfile->pub.name, E_NOTIMP);
9479 
9480         retval = (dbfile->pub.p_csgzl) (dbfile, name, nregs,
9481                                         typeflags, leftids, rightids,
9482                                         xforms, lxforms, datatype,
9483                                         nzones, zonelist, optlist);
9484         db_FreeToc(dbfile);
9485         API_RETURN(retval);
9486     }
9487     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9488 }
9489 
9490 /*-------------------------------------------------------------------------
9491  * Function:    DBGetCSGZonelist
9492  *
9493  * Purpose:     Allocate and read a DBcsgzonelist structure.
9494  *
9495  * Return:      Success:        ptr to new DBcsgzonelist.
9496  *
9497  *              Failure:        NULL
9498  *
9499  * Programmer:  Mark C. Miller
9500  *              Wed Jul 27 14:22:03 PDT 2005
9501  *
9502  *-------------------------------------------------------------------------*/
9503 PUBLIC DBcsgzonelist*
DBGetCSGZonelist(DBfile * dbfile,const char * name)9504 DBGetCSGZonelist(DBfile *dbfile, const char *name)
9505 {
9506     DBcsgzonelist * retval = NULL;
9507 
9508     API_BEGIN2("DBGetCSGZonelist", DBcsgzonelist *, NULL, name) {
9509         if (!dbfile)
9510             API_ERROR(NULL, E_NOFILE);
9511         if (SILO_Globals.enableGrabDriver == TRUE)
9512             API_ERROR("DBGetCSGZonelist", E_GRABBED) ;
9513         if (!name || !*name)
9514             API_ERROR("CSG zonelist name", E_BADARGS);
9515         if (!dbfile->pub.g_csgzl)
9516             API_ERROR(dbfile->pub.name, E_NOTIMP);
9517 
9518         retval = (dbfile->pub.g_csgzl) (dbfile, name);
9519         API_RETURN(retval);
9520     }
9521     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9522 }
9523 
9524 /*-------------------------------------------------------------------------
9525  * Function:    DBPutCsgvar
9526  *
9527  * Purpose:     Writes a variable associated with a CSG mesh into the
9528  *              database.  Note that variables will be either
9529  *              boundary-centered or zone-centered. A CSG-var object
9530  *              contains the variable values, plus the object ID of the
9531  *              associated CSG mesh.  Other information can also be included.
9532  *
9533  * Return:      Success:        Object ID
9534  *
9535  *              Failure:        -1
9536  *
9537  * Programmer:  Mark C. Miller
9538  *              Wed Jul 27 14:22:03 PDT 2005
9539  *
9540  *-------------------------------------------------------------------------*/
9541 PUBLIC int
DBPutCsgvar(DBfile * dbfile,const char * vname,const char * meshname,int nvars,char const * const * varnames,DBVCP2_t _vars,int nvals,int datatype,int centering,DBoptlist const * optlist)9542 DBPutCsgvar(DBfile *dbfile, const char *vname, const char *meshname,
9543             int nvars, char const * const *varnames, DBVCP2_t _vars,
9544             int nvals, int datatype, int centering, DBoptlist const *optlist)
9545 {
9546     int retval;
9547     void const * const *vars = (void const * const *) _vars;
9548 
9549     API_BEGIN2("DBPutCsgvar", int, -1, vname) {
9550         if (!dbfile)
9551             API_ERROR(NULL, E_NOFILE);
9552         if (SILO_Globals.enableGrabDriver == TRUE)
9553             API_ERROR("DBPutCsgvar", E_GRABBED) ;
9554         if (!vname || !*vname)
9555             API_ERROR("CSGvar name", E_BADARGS);
9556         if (db_VariableNameValid(vname) == 0)
9557             API_ERROR("CSGvar name", E_INVALIDNAME);
9558         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, vname))
9559             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
9560         if (nvals < 0)
9561             API_ERROR("nvals<0", E_BADARGS);
9562         if (nvals)
9563         {
9564             int i;
9565             if (!meshname || !*meshname)
9566                 API_ERROR("CSGmesh name", E_BADARGS);
9567             if (nvars <= 0)
9568                 API_ERROR("nvars<0", E_BADARGS);
9569             if (db_VariableNameValid(meshname) == 0)
9570                 API_ERROR("CSGmesh name", E_INVALIDNAME);
9571             for (i = 0; i < nvars && vars; i++)
9572                 if (!vars[i]) vars = 0;
9573             for (i = 0; i < nvars && varnames; i++)
9574                 if (!varnames[i] && !*varnames[i]) varnames = 0;
9575             if (!vars) API_ERROR("vars==0 || vars[i]==0", E_BADARGS);
9576             if (!varnames) API_ERROR("varnames==0 || varnames[i]==0", E_BADARGS);
9577             if (!(centering == DB_ZONECENT || centering == DB_BNDCENT))
9578                 API_ERROR("centering", E_BADARGS);
9579         }
9580         else if (!SILO_Globals.allowEmptyObjects)
9581         {
9582             API_ERROR("nvars=0 || nvals=0", E_EMPTYOBJECT);
9583         }
9584         if (!dbfile->pub.p_csgv)
9585             API_ERROR(dbfile->pub.name, E_NOTIMP);
9586 
9587         retval = (dbfile->pub.p_csgv) (dbfile, vname, meshname,
9588                                      nvars, varnames, vars, nvals,
9589                                      datatype, centering, optlist);
9590         db_FreeToc(dbfile);
9591         API_RETURN(retval);
9592     }
9593     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9594 }
9595 
9596 /*-------------------------------------------------------------------------
9597  * Function:    DBGetCsgvar
9598  *
9599  * Purpose:     Allocates a DBcsgvar structure and reads a variable associated
9600  *              with a CSG mesh from the database.
9601  *
9602  * Return:      Success:        Pointer to the new DBucdvar struct
9603  *
9604  *              Failure:        NULL
9605  *
9606  * Programmer:  matzke@viper
9607  *              Tue Nov  8 11:04:35 PST 1994
9608  *
9609  * Modifications:
9610  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
9611  *    Added a check for variable name validity.
9612  *
9613  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
9614  *    Made the error messages a little better.
9615  *-------------------------------------------------------------------------*/
9616 PUBLIC DBcsgvar *
DBGetCsgvar(DBfile * dbfile,const char * name)9617 DBGetCsgvar(DBfile *dbfile, const char *name)
9618 {
9619     DBcsgvar * retval = NULL;
9620 
9621     API_BEGIN2("DBGetCsgvar", DBcsgvar *, NULL, name) {
9622         if (!dbfile)
9623             API_ERROR(NULL, E_NOFILE);
9624         if (SILO_Globals.enableGrabDriver == TRUE)
9625             API_ERROR("DBGetCsgvar", E_GRABBED) ;
9626         if (!name || !*name)
9627             API_ERROR("CSGvar name", E_BADARGS);
9628         if (!dbfile->pub.g_csgv)
9629             API_ERROR(dbfile->pub.name, E_NOTIMP);
9630 
9631         retval = (dbfile->pub.g_csgv) (dbfile, name);
9632         API_RETURN(retval);
9633     }
9634     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
9635 }
9636 
9637 
9638 /*----------------------------------------------------------------------
9639  *  Routine                                                  _DBstrprint
9640  *
9641  *  Purpose
9642  *
9643  *      This function prints an array of strings in either column- or
9644  *      row-major order.
9645  *
9646  *  Programmer
9647  *
9648  *      Jeff Long
9649  *  Arguments:
9650  *      fp             File pointer for output of printing
9651  *      strs           Array of character strings to print
9652  *      nstrs          Number of character strings in 'strs'
9653  *      order          Printing order: 'c' for by-column, 'r' for by-row
9654  *      left_margin    Width of left margin (in chars)
9655  *      col_margin     Width of empty spaces between columns (in chars)
9656  *      line_width     Width of entire output line.
9657  *
9658  * Modified
9659  *    Robb Matzke, Wed Jan 11 06:41:23 PST 1995
9660  *    Changed name from strprint since that conflicted with MeshTV.
9661  *
9662  *    Eric Brugger, Tue Feb  7 09:06:58 PST 1995
9663  *    I modified the argument declaration to reflect argument promotions.
9664  *---------------------------------------------------------------------*/
9665 INTERNAL int
_DBstrprint(FILE * fp,char * strs[],int nstrs,int order,int left_margin,int col_margin,int line_width)9666 _DBstrprint(FILE *fp, char *strs[], int nstrs, int order, int left_margin,
9667             int col_margin, int line_width)
9668 {
9669     char         **sorted_strs = NULL;
9670     int            i, j, index;
9671     int            maxwidth;
9672     int            nrows, ncols;
9673     double         dtmp;
9674     char          *me = "_DBstrprint";
9675 
9676     if (nstrs <= 0)
9677         return db_perror("nstrs", E_BADARGS, me);
9678     if (left_margin < 0 || left_margin > line_width) {
9679         return db_perror("left margin", E_BADARGS, me);
9680     }
9681 
9682      /*----------------------------------------
9683       *  Sort strings into alphabetical order.
9684       *---------------------------------------*/
9685     sorted_strs = ALLOC_N(char *, nstrs);
9686     for (i = 0; i < nstrs; i++)
9687         sorted_strs[i] = strs[i];
9688 
9689     _DBsort_list(sorted_strs, nstrs);
9690 
9691      /*----------------------------------------
9692       *  Find maximum string width.
9693       *---------------------------------------*/
9694     maxwidth = strlen(sorted_strs[0]);
9695 
9696     for (i = 1; i < nstrs; i++) {
9697         maxwidth = MAX(maxwidth, (int)strlen(sorted_strs[i]));
9698     }
9699 
9700      /*----------------------------------------
9701       *  Determine number of columns and rows.
9702       *---------------------------------------*/
9703     ncols = (line_width - left_margin) / (maxwidth + col_margin);
9704     if (ncols <= 0) {
9705         FREE(sorted_strs);
9706         return (OOPS);
9707     }
9708 
9709     dtmp = (double)nstrs / (double)ncols;
9710     nrows = (int)ceil(dtmp);
9711     if (nrows <= 0) {
9712         FREE(sorted_strs);
9713         return -1;
9714     }
9715 
9716      /*----------------------------------------
9717       *  Print strings in requested order.
9718       *---------------------------------------*/
9719 
9720     if (order == 'c') {
9721         /*------------------------------
9722          *  Print by column
9723          *-----------------------------*/
9724 
9725         for (i = 0; i < nrows; i++) {
9726             index = i;
9727 
9728             fprintf(fp, "%*s", left_margin, " ");
9729 
9730             for (j = 0; j < ncols; j++) {
9731 
9732                 fprintf(fp, "%-*s%*s", maxwidth, sorted_strs[index],
9733                         col_margin, " ");
9734 
9735                 index += nrows;
9736                 if (index >= nstrs)
9737                     break;
9738             }
9739             fprintf(fp, "\n");
9740         }
9741 
9742     }
9743     else {
9744         /*------------------------------
9745          *  Print by row
9746          *-----------------------------*/
9747 
9748         for (i = 0; i < nrows; i++) {
9749             index = i * ncols;
9750 
9751             fprintf(fp, "%*s", left_margin, " ");
9752 
9753             for (j = 0; j < ncols; j++) {
9754 
9755                 fprintf(fp, "%-*s%*s", maxwidth, sorted_strs[index],
9756                         col_margin, " ");
9757 
9758                 index++;
9759                 if (index >= nstrs)
9760                     break;
9761             }
9762             fprintf(fp, "\n");
9763         }
9764 
9765     }
9766 
9767     FREE(sorted_strs);
9768     return 0;
9769 }
9770 
9771 static int
qsort_strcmp(const void * str1,const void * str2)9772 qsort_strcmp(const void *str1, const void *str2)
9773 {
9774    return(strcmp(*((const char **)str1), *((const char **)str2)));
9775 }
9776 
9777 /*----------------------------------------------------------------------
9778  *  Function                                                _DBsort_list
9779  *
9780  *  Purpose
9781  *
9782  *      Sort a list of character strings. Algorithm taken from
9783  *      _SX_sort_lists() -- courtesy of Stewart Brown.
9784  *
9785  * Modified
9786  *    Robb Matzke, Wed Jan 11 06:39:16 PST 1995
9787  *    Changed name from sort_list because it conflicts with MeshTV.
9788  *
9789  *    Sean Ahern, Fri Mar  2 09:45:05 PST 2001
9790  *    Changed this sort to a qsort, as suggested by Dan Schikore.
9791  *---------------------------------------------------------------------*/
9792 INTERNAL void
_DBsort_list(char ** ss,int n)9793 _DBsort_list(char **ss, int n)
9794 {
9795     qsort(ss, n, sizeof(char *), qsort_strcmp);
9796 }
9797 
9798 /*---------------------------------------------------------------------------
9799  * arrminmax - Return the min and max value of the given float array.
9800  *
9801  * Modified
9802  *    Robb Matzke, Wed Jan 11 06:43:08 PST 1995
9803  *    Changed name from arrminmax since that conflicted with MeshTV.
9804  *
9805  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
9806  *    Made the error messages a little better.
9807  *---------------------------------------------------------------------------*/
9808 INTERNAL int
_DBarrminmax(float arr[],int len,float * arr_min,float * arr_max)9809 _DBarrminmax(float arr[], int len, float *arr_min, float *arr_max)
9810 {
9811     int             i;
9812     char           *me = "_DBarrminmax";
9813 
9814     if (!arr)
9815         return db_perror("arr pointer", E_BADARGS, me);
9816     if (len <= 0)
9817         return db_perror("len", E_BADARGS, me);
9818 
9819     *arr_min = arr[0];
9820     *arr_max = arr[0];
9821 
9822     for (i = 1; i < len; i++)
9823     {
9824         *arr_min = MIN(*arr_min, arr[i]);
9825         *arr_max = MAX(*arr_max, arr[i]);
9826     }
9827 
9828     return 0;
9829 }
9830 
9831 /*---------------------------------------------------------------------------
9832  * iarrminmax - Return the min and max value of the given int array.
9833  *
9834  * Modified:
9835  *    Robb Matzke, Wed Jan 11 06:43:42 PST 1995
9836  *    Changed name from iarrminmax since that conflicted with MeshTV.
9837  *
9838  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
9839  *    Made the error messages a little better.
9840  *---------------------------------------------------------------------------*/
9841 INTERNAL int
_DBiarrminmax(int arr[],int len,int * arr_min,int * arr_max)9842 _DBiarrminmax(int arr[], int len, int *arr_min, int *arr_max)
9843 {
9844     int             i;
9845     char           *me = "_DBiarrminmax";
9846 
9847     if (!arr)
9848         return db_perror("arr pointer", E_BADARGS, me);
9849     if (len <= 0)
9850         return db_perror("len", E_BADARGS, me);
9851 
9852     *arr_min = arr[0];
9853     *arr_max = arr[0];
9854 
9855     for (i = 1; i < len; i++)
9856     {
9857         *arr_min = MIN(*arr_min, arr[i]);
9858         *arr_max = MAX(*arr_max, arr[i]);
9859     }
9860 
9861     return 0;
9862 }
9863 
9864 /*---------------------------------------------------------------------------
9865  * darrminmax - Return the min and max value of the given double array.
9866  *
9867  * Modified:
9868  *    Robb Matzke, Wed Jan 11 06:44:16 PST 1995
9869  *    Changed name from darrminmax since that conflicted with MeshTV.
9870  *
9871  *    Sean Ahern, Tue Sep 28 11:00:13 PDT 1999
9872  *    Made the error messages a little better.
9873  *---------------------------------------------------------------------------*/
9874 INTERNAL int
_DBdarrminmax(double arr[],int len,double * arr_min,double * arr_max)9875 _DBdarrminmax(double arr[], int len, double *arr_min, double *arr_max)
9876 {
9877     int             i;
9878     char           *me = "_DBdarrminmax";
9879 
9880     if (!arr)
9881         return db_perror("arr pointer", E_BADARGS, me);
9882     if (len <= 0)
9883         return db_perror("len", E_BADARGS, me);
9884 
9885     *arr_min = arr[0];
9886     *arr_max = arr[0];
9887 
9888     for (i = 1; i < len; i++)
9889     {
9890         *arr_min = MIN(*arr_min, arr[i]);
9891         *arr_max = MAX(*arr_max, arr[i]);
9892     }
9893 
9894     return 0;
9895 }
9896 
9897 /***********************************************************************
9898  *
9899  * Purpose: Return the min and max values of a subset of the given
9900  *          array.
9901  *
9902  * Programmer: Eric S. Brugger
9903  * Date:       May 26, 1995
9904  *
9905  * Input arguments:
9906  *    arr      : The array to evaluate.
9907  *    datatype : The data type of the array.
9908  *    nx       : The x dimension of the array.
9909  *    ny       : The y dimension of the array.
9910  *    nz       : The z dimension of the array.
9911  *    ixmin    : The 0 origin min index in the x direction.
9912  *    ixmax    : The 0 origin max index in the x direction.
9913  *    iymin    : The 0 origin min index in the y direction.
9914  *    iymax    : The 0 origin max index in the y direction.
9915  *    izmin    : The 0 origin min index in the z direction.
9916  *    izmax    : The 0 origin max index in the z direction.
9917  *
9918  * Output arguments:
9919  *    amin     : The minimum value in the array.
9920  *    amax     : The maximum value in the array.
9921  *
9922  * Input/Output arguments:
9923  *
9924  * Notes:
9925  *
9926  * Modifications:
9927  *    Eric Brugger, Tue May 30 17:03:51 PDT 1995
9928  *    I changed the initial calculation of the index to use ixmin,
9929  *    iymin, and izmin instead of i, j, k which were not initialized.
9930  *
9931  *    Jim Reus, 23 Apr 97
9932  *    I changed to prototype form, moved location within file.
9933  *
9934  *    Eric Brugger, Thu Sep 23 15:05:18 PDT 1999
9935  *    I removed the unused argument nz.
9936  ***********************************************************************/
9937 
9938 INTERNAL int
_DBSubsetMinMax3(float arr[],int datatype,float * amin,float * amax,int nx,int ny,int ixmin,int ixmax,int iymin,int iymax,int izmin,int izmax)9939 _DBSubsetMinMax3(float arr[], int datatype, float *amin, float *amax , int nx,
9940                  int ny, int ixmin, int ixmax, int iymin , int iymax,
9941                  int izmin, int izmax)
9942 {
9943     int             i, j, k, index, nxy;
9944     float           tmin, tmax;
9945     double          dtmin, dtmax;
9946     double         *darr, *damin, *damax;
9947 
9948     switch (datatype)
9949     {
9950     case DB_FLOAT:
9951 
9952         nxy = nx * ny;
9953 
9954         index = INDEX3(ixmin, iymin, izmin, nx, nxy);
9955         tmin = arr[index];
9956         tmax = arr[index];
9957 
9958         for (k = izmin; k <= izmax; k++)
9959         {
9960             for (j = iymin; j <= iymax; j++)
9961             {
9962                 for (i = ixmin; i <= ixmax; i++)
9963                 {
9964                     index = INDEX3(i, j, k, nx, nxy);
9965                     tmin = MIN(tmin, arr[index]);
9966                     tmax = MAX(tmax, arr[index]);
9967                 }
9968             }
9969         }
9970 
9971         *amin = tmin;
9972         *amax = tmax;
9973         break;
9974 
9975     case DB_DOUBLE:
9976 
9977         darr = (double *)arr;
9978 
9979         nxy = nx * ny;
9980 
9981         index = INDEX3(ixmin, iymin, izmin, nx, nxy);
9982         dtmin = darr[index];
9983         dtmax = darr[index];
9984 
9985         for (k = izmin; k <= izmax; k++)
9986         {
9987             for (j = iymin; j <= iymax; j++)
9988             {
9989                 for (i = ixmin; i <= ixmax; i++)
9990                 {
9991                     index = INDEX3(i, j, k, nx, nxy);
9992                     dtmin = MIN(dtmin, darr[index]);
9993                     dtmax = MAX(dtmax, darr[index]);
9994                 }
9995             }
9996         }
9997 
9998         damin = (double *)amin;
9999         damax = (double *)amax;
10000         *damin = dtmin;
10001         *damax = dtmax;
10002         break;
10003 
10004     default:
10005         break;
10006     }
10007 
10008     return 0;
10009 }
10010 
10011 /*----------------------------------------------------------------------
10012  * Routine                                               CSGM_CalcExtents
10013  *
10014  * Purpose
10015  *
10016  *      Return the extents of the given csg mesh.
10017  *
10018  *--------------------------------------------------------------------*/
10019 INTERNAL int
CSGM_CalcExtents(int datatype,int ndims,int nbounds,const int * typeflags,const void * coeffs,double * min_extents,double * max_extents)10020 CSGM_CalcExtents(int datatype, int ndims, int nbounds,
10021                const int *typeflags, const void *coeffs,
10022                double *min_extents, double *max_extents)
10023 {
10024     min_extents[0] = -DBL_MAX;
10025     min_extents[1] = -DBL_MAX;
10026     min_extents[2] = -DBL_MAX;
10027     max_extents[0] = DBL_MAX;
10028     max_extents[1] = DBL_MAX;
10029     max_extents[2] = DBL_MAX;
10030     return 0;
10031 }
10032 
10033 /*----------------------------------------------------------------------
10034  *  Routine                                               _DBQMCalcExtents
10035  *
10036  *  Purpose
10037  *
10038  *      Return the extents of the given quad mesh.
10039  *
10040  *      Works for 1D, 2D and 3D meshes, collinear or non-collinear.
10041  *
10042  *  Modification History
10043  *    Jeff Long, 11/16/92
10044  *    Modified handling of double precision coords so that extents
10045  *    are returned as floats.
10046  *
10047  *    Robb Matzke, Wed Jan 11 06:34:09 PST 1995
10048  *    Changed name from QM_CalcExtents because it conflicts with MeshTV.
10049  *
10050  *    Eric Brugger, Wed Feb 15 08:12:43 PST 1995
10051  *    I removed the error message that precision had been lost.
10052  *    Their is no loss of precision because all the casts from
10053  *    double to float were done on pointers.  Casting of a pointer
10054  *    just makes the compiler happy and has no impact on the value
10055  *    pointed to.
10056  *
10057  *    Sean Ahern, Mon Oct 19 18:17:10 PDT 1998
10058  *    Added the ability to have the extents returned either as float or
10059  *    double.
10060  *--------------------------------------------------------------------*/
10061 INTERNAL int
_DBQMCalcExtents(DBVCP2_t coord_arrays,int datatype,int const * min_index,int const * max_index,int const * dims,int ndims,int coordtype,void * min_extents,void * max_extents)10062 _DBQMCalcExtents(DBVCP2_t coord_arrays, int datatype, int const *min_index,
10063                  int const *max_index, int const *dims, int ndims, int coordtype,
10064                  void *min_extents, void *max_extents)
10065 {
10066     float         *x = NULL, *y = NULL, *z = NULL;
10067     double        *dx = NULL, *dy = NULL, *dz = NULL;
10068     double        *dmin_extents = NULL, *dmax_extents = NULL;
10069     float         *fmin_extents = NULL, *fmax_extents = NULL;
10070     int            i, is_empty = 1;
10071     char          *me = "_DBQMCalcExtents";
10072 
10073     for (i = 0; i < ndims; i++)
10074     {
10075         if (dims[i] > 0)
10076         {
10077             is_empty = 0;
10078             break;
10079         }
10080     }
10081 
10082     if (is_empty) return 0;
10083 
10084     if (datatype == DB_FLOAT)
10085     {
10086         fmin_extents = (float*)min_extents;
10087         fmax_extents = (float*)max_extents;
10088 
10089         /* Initialize extent arrays */
10090         for (i = 0; i < ndims; i++) {
10091             fmin_extents[i] = 0.;
10092             fmax_extents[i] = 0.;
10093         }
10094     } else if (datatype == DB_DOUBLE)
10095     {
10096         dmin_extents = (double*)min_extents;
10097         dmax_extents = (double*)max_extents;
10098 
10099         /* Initialize extent arrays */
10100         for (i = 0; i < ndims; i++) {
10101             dmin_extents[i] = 0.;
10102             dmax_extents[i] = 0.;
10103         }
10104     }
10105 
10106     /* Read default coordinate variables. */
10107     switch (ndims) {
10108         case 3:
10109             z = ((float**)coord_arrays)[2];
10110             /* Fall through */
10111         case 2:
10112             y = ((float**)coord_arrays)[1];
10113             /* Fall through */
10114         case 1:
10115             x = ((float**)coord_arrays)[0];
10116             break;
10117         default:
10118             break;
10119     }
10120 
10121     if (datatype == DB_DOUBLE) {
10122         dx = (double *)x;
10123         dy = (double *)y;
10124         dz = (double *)z;
10125     }
10126 
10127     /* Get mesh coordinate extents. */
10128     switch (coordtype) {
10129 
10130         case DB_COLLINEAR:
10131 
10132             switch (ndims) {
10133                 case 3:
10134                     if (datatype == DB_DOUBLE) {
10135                         dmin_extents[2] = dz[min_index[2]];
10136                         dmax_extents[2] = dz[max_index[2]];
10137                     }
10138                     else {
10139                         fmin_extents[2] = z[min_index[2]];
10140                         fmax_extents[2] = z[max_index[2]];
10141                     }
10142                 case 2:
10143                     if (datatype == DB_DOUBLE) {
10144                         dmin_extents[1] = dy[min_index[1]];
10145                         dmax_extents[1] = dy[max_index[1]];
10146                     }
10147                     else {
10148                         fmin_extents[1] = y[min_index[1]];
10149                         fmax_extents[1] = y[max_index[1]];
10150                     }
10151                 case 1:
10152                     if (datatype == DB_DOUBLE) {
10153                         dmin_extents[0] = dx[min_index[0]];
10154                         dmax_extents[0] = dx[max_index[0]];
10155                     }
10156                     else {
10157                         fmin_extents[0] = x[min_index[0]];
10158                         fmax_extents[0] = x[max_index[0]];
10159                     }
10160                     break;
10161             }
10162             break;
10163 
10164         case DB_NONCOLLINEAR:
10165 
10166             switch (ndims) {
10167                 case 3:
10168                     if (datatype == DB_DOUBLE) {
10169                         _DBSubsetMinMax3((float *)dx, datatype,
10170                                          (float *)(&dmin_extents[0]),
10171                                          (float *)(&dmax_extents[0]),
10172                                          dims[0], dims[1],
10173                                          min_index[0], max_index[0],
10174                                          min_index[1], max_index[1],
10175                                          min_index[2], max_index[2]);
10176                         _DBSubsetMinMax3((float *)dy, datatype,
10177                                          (float *)(&dmin_extents[1]),
10178                                          (float *)(&dmax_extents[1]),
10179                                          dims[0], dims[1],
10180                                          min_index[0], max_index[0],
10181                                          min_index[1], max_index[1],
10182                                          min_index[2], max_index[2]);
10183                         _DBSubsetMinMax3((float *)dz, datatype,
10184                                          (float *)(&dmin_extents[2]),
10185                                          (float *)(&dmax_extents[2]),
10186                                          dims[0], dims[1],
10187                                          min_index[0], max_index[0],
10188                                          min_index[1], max_index[1],
10189                                          min_index[2], max_index[2]);
10190                     }
10191                     else {
10192                         _DBSubsetMinMax3(x, datatype,
10193                                          &fmin_extents[0], &fmax_extents[0],
10194                                          dims[0], dims[1],
10195                                          min_index[0], max_index[0],
10196                                          min_index[1], max_index[1],
10197                                          min_index[2], max_index[2]);
10198                         _DBSubsetMinMax3(y, datatype,
10199                                          &fmin_extents[1], &fmax_extents[1],
10200                                          dims[0], dims[1],
10201                                          min_index[0], max_index[0],
10202                                          min_index[1], max_index[1],
10203                                          min_index[2], max_index[2]);
10204                         _DBSubsetMinMax3(z, datatype,
10205                                          &fmin_extents[2], &fmax_extents[2],
10206                                          dims[0], dims[1],
10207                                          min_index[0], max_index[0],
10208                                          min_index[1], max_index[1],
10209                                          min_index[2], max_index[2]);
10210                     }
10211                     break;
10212                 case 2:
10213                     if (datatype == DB_DOUBLE) {
10214                         _DBSubsetMinMax2((float *)dx, datatype,
10215                                          (float *)(&dmin_extents[0]),
10216                                          (float *)(&dmax_extents[0]),
10217                                          dims[0],
10218                                          min_index[0], max_index[0],
10219                                          min_index[1], max_index[1]);
10220                         _DBSubsetMinMax2((float *)dy, datatype,
10221                                          (float *)(&dmin_extents[1]),
10222                                          (float *)(&dmax_extents[1]),
10223                                          dims[0],
10224                                          min_index[0], max_index[0],
10225                                          min_index[1], max_index[1]);
10226                     }
10227                     else {
10228 
10229                         _DBSubsetMinMax2(x, datatype,
10230                                          &fmin_extents[0], &fmax_extents[0],
10231                                          dims[0],
10232                                          min_index[0], max_index[0],
10233                                          min_index[1], max_index[1]);
10234 
10235                         _DBSubsetMinMax2(y, datatype,
10236                                          &fmin_extents[1], &fmax_extents[1],
10237                                          dims[0],
10238                                          min_index[0], max_index[0],
10239                                          min_index[1], max_index[1]);
10240                     }
10241                     break;
10242                 case 1:
10243                     return db_perror("1-d noncollinear", E_NOTIMP, me);
10244             }
10245             break;
10246 
10247         default:
10248             return db_perror("default case", E_INTERNAL, me);
10249     }
10250 
10251     return 0;
10252 }
10253 
10254 /*--------------------------------------------------------------------------
10255  *  Routine                                                  _DBSubsetMinMax2
10256  *
10257  *  Purpose
10258  *
10259  *      Return the min and max values of a subset of the given array.
10260  *
10261  *  Paramters
10262  *
10263  *      arr       =|  The array to evaluate
10264  *      datatype  =|  The type of data pointed to by 'arr'. (float or double)
10265  *      amin,amax  |= Returned min,max values
10266  *      nx,ny     =|  The dimensions of 'arr'
10267  *      ixmin...  =|  The actual 0-origin indeces to use for subselection
10268  *
10269  * Modified
10270  *    Robb Matzke, Wed Jan 11 06:46:23 PST 1995
10271  *    Changed name from SubsetMinMax2 since that conflicted with MeshTV.
10272  *
10273  *    Eric Brugger, Thu Mar 14 16:22:08 PST 1996
10274  *    I corrected a bug in the calculation of the minimum, where it
10275  *    got the initial minimum value by indexing into the coordinate
10276  *    arrays as 1d arrays instead of a 2d arrays.
10277  *
10278  *    Eric Brugger, Thu Sep 23 15:05:18 PDT 1999
10279  *    I removed the unused argument ny.
10280  *--------------------------------------------------------------------------*/
10281 INTERNAL int
_DBSubsetMinMax2(void const * arr,int datatype,float * amin,float * amax,int nx,int ixmin,int ixmax,int iymin,int iymax)10282 _DBSubsetMinMax2(void const *arr, int datatype, float *amin, float *amax, int nx,
10283                  int ixmin, int ixmax, int iymin, int iymax)
10284 {
10285     int            k, j, index;
10286     float          tmin, tmax;
10287     double         dtmin, dtmax;
10288     double        *darr = NULL, *damin = NULL, *damax = NULL;
10289     float         *farr = NULL;
10290 
10291     switch (datatype) {
10292         case DB_FLOAT:
10293 
10294             farr = (float *)arr;
10295 
10296             index = INDEX (ixmin, iymin, nx);
10297             tmin = farr[index];
10298             tmax = farr[index];
10299 
10300             for (j = iymin; j <= iymax; j++) {
10301                 for (k = ixmin; k <= ixmax; k++) {
10302                     index = INDEX (k, j, nx);
10303                     tmin = MIN (tmin, farr[index]);
10304                     tmax = MAX (tmax, farr[index]);
10305                 }
10306             }
10307             *amin = tmin;
10308             *amax = tmax;
10309             break;
10310 
10311         case DB_DOUBLE:
10312 
10313             darr = (double *)arr;
10314 
10315             index = INDEX (ixmin, iymin, nx);
10316             dtmin = darr[index];
10317             dtmax = darr[index];
10318 
10319             for (j = iymin; j <= iymax; j++) {
10320                 for (k = ixmin; k <= ixmax; k++) {
10321                     index = INDEX (k, j, nx);
10322                     dtmin = MIN (dtmin, darr[index]);
10323                     dtmax = MAX (dtmax, darr[index]);
10324                 }
10325             }
10326 
10327             damin = (double *)amin;
10328             damax = (double *)amax;
10329             *damin = dtmin;
10330             *damax = dtmax;
10331             break;
10332 
10333         default:
10334             break;
10335     }
10336     return 0;
10337 }
10338 
10339 /*----------------------------------------------------------------------
10340  * Routine                                               UM_CalcExtents
10341  *
10342  * Purpose
10343  *
10344  *      Return the extents of the given ucd mesh.
10345  *
10346  * Modifications:
10347  *      Sean Ahern, Wed Oct 21 10:55:21 PDT 1998
10348  *      Changed the function so that the min_extents and max_extents are
10349  *      passed in as void* variables.
10350  *--------------------------------------------------------------------*/
10351 INTERNAL int
UM_CalcExtents(DBVCP2_t coord_arrays,int datatype,int ndims,int nnodes,void * min_extents,void * max_extents)10352 UM_CalcExtents(DBVCP2_t coord_arrays, int datatype, int ndims, int nnodes,
10353                void *min_extents, void *max_extents)
10354 {
10355     int            i, j;
10356     double       **dcoord_arrays = NULL;
10357     double        *dmin_extents = NULL, *dmax_extents = NULL;
10358     float         *fmin_extents = NULL, *fmax_extents = NULL;
10359     float        **fcoord_arrays = NULL;
10360 
10361     if (nnodes <= 0) return 0;
10362 
10363     if (datatype == DB_DOUBLE) {
10364 
10365         dmin_extents = (double *)min_extents;
10366         dmax_extents = (double *)max_extents;
10367         dcoord_arrays = (double **)coord_arrays;
10368 
10369         /* Initialize extent arrays */
10370         for (i = 0; i < ndims; i++) {
10371             dmin_extents[i] = dcoord_arrays[i][0];
10372             dmax_extents[i] = dcoord_arrays[i][0];
10373         }
10374 
10375         for (i = 0; i < ndims; i++) {
10376             for (j = 0; j < nnodes; j++) {
10377                 dmin_extents[i] = MIN(dmin_extents[i], dcoord_arrays[i][j]);
10378                 dmax_extents[i] = MAX(dmax_extents[i], dcoord_arrays[i][j]);
10379             }
10380         }
10381 
10382     }
10383     else {
10384         fmin_extents = (float *)min_extents;
10385         fmax_extents = (float *)max_extents;
10386         fcoord_arrays = (float **)coord_arrays;
10387 
10388         /* Initialize extent arrays */
10389         for (i = 0; i < ndims; i++) {
10390             fmin_extents[i] = fcoord_arrays[i][0];
10391             fmax_extents[i] = fcoord_arrays[i][0];
10392         }
10393 
10394         for (i = 0; i < ndims; i++) {
10395             for (j = 0; j < nnodes; j++) {
10396                 fmin_extents[i] = MIN(fmin_extents[i], fcoord_arrays[i][j]);
10397                 fmax_extents[i] = MAX(fmax_extents[i], fcoord_arrays[i][j]);
10398             }
10399         }
10400 
10401     }
10402 
10403     return 0;
10404 }
10405 
10406 /*-------------------------------------------------------------------------
10407  * Function:    db_ProcessOptlist
10408  *
10409  * Purpose:     Process the options list for an object and initializes the
10410  *              object's global data.  Each object type has its own global data
10411  *              so that `cycle' for one type of object is different from
10412  *              `cycle' for another type of object.  This results form trying
10413  *              to stay compatible with the previous version, where each
10414  *              object had its own source file with global variables
10415  *              declared `static'.
10416  *
10417  *              Some objects share the same global data.  They are:
10418  *                      DB_MULTIMESH    and DB_MULTIVAR (_mm)
10419  *                      DB_POINTMESH    and DB_POINTVAR (_pm)
10420  *                      DB_QUADMESH     and DB_QUADVAR  (_qm)
10421  *                      DB_UCDMESH      and DB_UCDVAR   (_um)
10422  *
10423  *
10424  * Return:      Success:        0, no options or all options processed.
10425  *
10426  *              Failure:        >0, number of unrecognized options.
10427  *                              -1, bad objtype
10428  *
10429  * Programmer:  matzke@viper
10430  *              Wed Dec 14 13:36:04 PST 1994
10431  *
10432  * Modifications:
10433  *    Eric Brugger, Fri Jan 12 18:36:56 PST 1996
10434  *    I added the case for DB_MULTIMESH.
10435  *
10436  *    Robb Matzke, 18 Jun 1997
10437  *    Added DB_ASCII_LABEL for DB_QUADMESH and DB_QUADVAR.
10438  *
10439  *    Eric Brugger, Wed Oct 15 15:37:22 PDT 1997
10440  *    I added DBOPT_HI_OFFSET and DBOPT_LO_OFFSET to DB_UCDVAR.
10441  *
10442  *    Eric Brugger, Thu Oct 16 10:31:26 PDT 1997
10443  *    I added DBOPT_MATNOS and DBOPT_NMATNOS to DB_MULTIMAT (which
10444  *    is covered by the DB_MULTIMESH case).
10445  *
10446  *    Jeremy Meredith, Sept 18 1998
10447  *    Added options DBOPT_MATNAME, DBOPT_NMAT, and DBOPT_NMATSPEC
10448  *    to DB_MULTIMATSPECIES (covered by DB_MULTIMESH case).
10449  *
10450  *    Jeremy Meredith, Fri May 21 10:04:25 PDT 1999
10451  *    Added DBOPT_GROUPNUM to the point, quad, and ucd meshes.
10452  *    Added DBOPT_BASEINDEX to the quad mesh; set it from the origin if needed.
10453  *    Added DBOPT_NODENUM to the ucd mesh.
10454  *    Added a DB_ZONELIST type.
10455  *    Added DBOPT_ZONENUM to the ucd zonelist.
10456  *    Added DBOPT_BLOCKORIGIN, _GROUPORIGIN, and _NGROUPS to the multimesh.
10457  *
10458  *    Jeremy Meredith, Wed Jul  7 12:15:31 PDT 1999
10459  *    I removed the DBOPT_ORIGIN from the species object.
10460  *
10461  *    Sean Ahern, Tue Feb  5 10:22:25 PST 2002
10462  *    Added names for materials.
10463  *
10464  *    Brad Whitlock, Wed Jan 18 15:36:55 PST 2006
10465  *    Added ascii_labels for ucdvars.
10466  *
10467  *    Thomas R. Treadway, Wed Jun 28 10:31:45 PDT 2006
10468  *    Added topo_dim to ucdmesh.
10469  *
10470  *    Thomas R. Treadway, Thu Jul  6 17:05:24 PDT 2006
10471  *    Added reference to curve options.
10472  *
10473  *    Thomas R. Treadway, Thu Jul 20 11:06:27 PDT 2006
10474  *    Added lgroupings, groupings, and groupnames to multimesh options.
10475  *
10476  *    Mark C. Miller, Mon Aug  7 17:03:51 PDT 2006
10477  *    Added DBOPT_MATCOLORS, DBOPT_MATNAMES options to multimesh
10478  *
10479  *    Thomas R. Treadway, Tue Aug 15 14:05:59 PDT 2006
10480  *    Added DBOPT_ALLOWMAT0
10481  *
10482  *    Mark C. Miller, Tue Sep  8 15:40:51 PDT 2009
10483  *    Added names and colors for species.
10484  *
10485  *    Mark C. Miller, Wed Sep 23 11:49:34 PDT 2009
10486  *    Added DBOPT_LLONGNZNUM for long long global node/zone numbers
10487  *    to pointmeshes, ucdmeshes, zonelists.
10488  *
10489  *    Mark C. Miller, Thu Nov  5 16:14:12 PST 2009
10490  *    Added conserved/extensive options to all var objects.
10491  *
10492  *    Mark C. Miller, Fri Nov 13 15:33:02 PST 2009
10493  *    Add DBOPT_LLONGNZNUM to polyhedral zonelist object.
10494  *
10495  *    Mark C. Miller, Wed Jul 14 20:36:23 PDT 2010
10496  *    Added support for nameschemes options on multi-block objects.
10497  *-------------------------------------------------------------------------*/
10498 INTERNAL int
db_ProcessOptlist(int objtype,DBoptlist const * const optlist)10499 db_ProcessOptlist(int objtype, DBoptlist const * const optlist)
10500 {
10501     int             i, j, *ip = NULL, unused = 0;
10502     char           *me = "db_ProcessOptlist";
10503 
10504     if (!optlist || optlist->numopts < 0)
10505         return 0;
10506 
10507     for (i = 0; i < optlist->numopts; i++)
10508     {
10509         if (optlist->options[i] >= DBOPT_FIRST &&
10510             optlist->options[i] <= DBOPT_LAST)
10511             continue;
10512         return db_perror(NULL, E_BADOPTCLASS, me);
10513     }
10514 
10515     switch (objtype)
10516     {
10517         case DB_CSGMESH:
10518         case DB_CSGVAR:
10519             for (i = 0; i < optlist->numopts; i++)
10520             {
10521                 switch (optlist->options[i])
10522                 {
10523                     case DBOPT_TIME:
10524                         _csgm._time = DEREF(float, optlist->values[i]);
10525                         _csgm._time_set = TRUE;
10526                         break;
10527 
10528                     case DBOPT_DTIME:
10529                         _csgm._dtime = DEREF(double, optlist->values[i]);
10530                         _csgm._dtime_set = TRUE;
10531                         break;
10532 
10533                     case DBOPT_CYCLE:
10534                         _csgm._cycle = DEREF(int, optlist->values[i]);
10535                         break;
10536 
10537                     case DBOPT_LABEL:
10538                         _csgm._label = (char *)optlist->values[i];
10539                         break;
10540 
10541                     case DBOPT_XLABEL:
10542                         _csgm._labels[0] = (char *)optlist->values[i];
10543                         break;
10544 
10545                     case DBOPT_YLABEL:
10546                         _csgm._labels[1] = (char *)optlist->values[i];
10547                         break;
10548 
10549                     case DBOPT_ZLABEL:
10550                         _csgm._labels[2] = (char *)optlist->values[i];
10551                         break;
10552 
10553                     case DBOPT_UNITS:
10554                         _csgm._unit = (char *)optlist->values[i];
10555                         break;
10556 
10557                     case DBOPT_XUNITS:
10558                         _csgm._units[0] = (char *)optlist->values[i];
10559                         break;
10560 
10561                     case DBOPT_YUNITS:
10562                         _csgm._units[1] = (char *)optlist->values[i];
10563                         break;
10564 
10565                     case DBOPT_ZUNITS:
10566                         _csgm._units[2] = (char *)optlist->values[i];
10567                         break;
10568 
10569                     case DBOPT_USESPECMF:
10570                         _csgm._use_specmf = DEREF(int, optlist->values[i]);
10571                         break;
10572 
10573                     case DBOPT_GROUPNUM:
10574                         DEPRECATE_MSG("DBOPT_GROUPNUM",4,6,"MRG Trees")
10575                         _csgm._group_no = DEREF(int, optlist->values[i]);
10576                         break;
10577 
10578                     case DBOPT_ORIGIN:
10579                         _csgm._origin = DEREF(int, optlist->values[i]);
10580                         break;
10581 
10582                     case DBOPT_BNDNAMES:
10583                         _csgm._bndnames = (char **)optlist->values[i];
10584                         break;
10585 
10586                     case DBOPT_HIDE_FROM_GUI:
10587                         _csgm._guihide = DEREF(int, optlist->values[i]);
10588                         break;
10589 
10590                     case DBOPT_MRGTREE_NAME:
10591                         _csgm._mrgtree_name = (char *)optlist->values[i];
10592                         break;
10593 
10594                     case DBOPT_REGION_PNAMES:
10595                         _csgm._region_pnames = (char **) optlist->values[i];
10596                         break;
10597 
10598                     case DBOPT_TV_CONNECTIVITY:
10599                         _csgm._tv_connectivity = DEREF(int, optlist->values[i]);
10600                         break;
10601 
10602                     case DBOPT_DISJOINT_MODE:
10603                         _csgm._disjoint_mode = DEREF(int, optlist->values[i]);
10604                         break;
10605 
10606                     case DBOPT_CONSERVED:
10607                         _csgm._conserved = DEREF(int, optlist->values[i]);
10608                         break;
10609 
10610                     case DBOPT_EXTENSIVE:
10611                         _csgm._extensive = DEREF(int, optlist->values[i]);
10612                         break;
10613 
10614                     case DBOPT_MISSING_VALUE:
10615                         _csgm._missing_value = DEREF(double, optlist->values[i]);
10616                         break;
10617 
10618                     case DBOPT_ALT_NODENUM_VARS:
10619                         _csgm._alt_nodenum_vars = (char **) optlist->values[i];
10620                         break;
10621 
10622                     default:
10623                         unused++;
10624                         break;
10625                 }
10626             }
10627             break;
10628 
10629         case DB_MATERIAL:
10630             for (i = 0; i < optlist->numopts; i++)
10631             {
10632                 switch (optlist->options[i])
10633                 {
10634                     case DBOPT_MAJORORDER:
10635                         _ma._majororder = DEREF(int, optlist->values[i]);
10636                         break;
10637 
10638                     case DBOPT_ORIGIN:
10639                         _ma._origin = DEREF(int, optlist->values[i]);
10640                         break;
10641 
10642                     case DBOPT_MATNAMES:
10643                         _ma._matnames = (char **) optlist->values[i];
10644                         break;
10645 
10646                     case DBOPT_MATCOLORS:
10647                         _ma._matcolors = (char **) optlist->values[i];
10648                         break;
10649 
10650                     case DBOPT_ALLOWMAT0:
10651                         _ma._allowmat0 = DEREF(int, optlist->values[i]);
10652                         break;
10653 
10654                     case DBOPT_HIDE_FROM_GUI:
10655                         _ma._guihide = DEREF(int, optlist->values[i]);
10656                         break;
10657 
10658                     default:
10659                         unused++;
10660                         break;
10661                 }
10662             }
10663             break;
10664 
10665         case DB_MATSPECIES:
10666             for (i = 0; i < optlist->numopts; i++)
10667             {
10668                 switch (optlist->options[i])
10669                 {
10670                     case DBOPT_MAJORORDER:
10671                         _ms._majororder = DEREF(int, optlist->values[i]);
10672                         break;
10673 
10674                     case DBOPT_HIDE_FROM_GUI:
10675                         _ms._guihide = DEREF(int, optlist->values[i]);
10676                         break;
10677 
10678                     case DBOPT_SPECNAMES:
10679                         _ms._specnames = (char **) optlist->values[i];
10680                         break;
10681 
10682                     case DBOPT_SPECCOLORS:
10683                         _ms._speccolors = (char **) optlist->values[i];
10684                         break;
10685 
10686                     default:
10687                         unused++;
10688                         break;
10689                 }
10690             }
10691             break;
10692 
10693         case DB_POINTMESH:
10694         case DB_POINTVAR:
10695             for (i = 0; i < optlist->numopts; i++)
10696             {
10697                 switch (optlist->options[i])
10698                 {
10699                     case DBOPT_TIME:
10700                         _pm._time = DEREF(float, optlist->values[i]);
10701                         _pm._time_set = 1;
10702                         break;
10703 
10704                     case DBOPT_DTIME:
10705                         _pm._dtime = DEREF(double, optlist->values[i]);
10706                         _pm._dtime_set = 1;
10707                         break;
10708 
10709                     case DBOPT_CYCLE:
10710                         _pm._cycle = DEREF(int, optlist->values[i]);
10711                         break;
10712 
10713                     case DBOPT_NSPACE:
10714                         _pm._nspace = DEREF(int, optlist->values[i]);
10715                         break;
10716 
10717                     case DBOPT_ORIGIN:
10718                         _pm._origin = DEREF(int, optlist->values[i]);
10719                         break;
10720 
10721                     case DBOPT_HI_OFFSET:
10722                         _pm._hi_offset = DEREF(int, optlist->values[i]);
10723                         break;
10724 
10725                     case DBOPT_LO_OFFSET:
10726                         _pm._lo_offset = DEREF(int, optlist->values[i]);
10727                         break;
10728 
10729                     case DBOPT_LABEL:
10730                         _pm._label = (char *)optlist->values[i];
10731                         break;
10732 
10733                     case DBOPT_XLABEL:
10734                         _pm._labels[0] = (char *)optlist->values[i];
10735                         break;
10736 
10737                     case DBOPT_YLABEL:
10738                         _pm._labels[1] = (char *)optlist->values[i];
10739                         break;
10740 
10741                     case DBOPT_ZLABEL:
10742                         _pm._labels[2] = (char *)optlist->values[i];
10743                         break;
10744 
10745                     case DBOPT_UNITS:
10746                         _pm._unit = (char *)optlist->values[i];
10747                         break;
10748 
10749                     case DBOPT_XUNITS:
10750                         _pm._units[0] = (char *)optlist->values[i];
10751                         break;
10752 
10753                     case DBOPT_YUNITS:
10754                         _pm._units[1] = (char *)optlist->values[i];
10755                         break;
10756 
10757                     case DBOPT_ZUNITS:
10758                         _pm._units[2] = (char *)optlist->values[i];
10759                         break;
10760 
10761                     case DBOPT_GROUPNUM:
10762                         DEPRECATE_MSG("DBOPT_GROUPNUM",4,6,"MRG Trees")
10763                         _pm._group_no = DEREF(int, optlist->values[i]);
10764                         break;
10765 
10766                     case DBOPT_HIDE_FROM_GUI:
10767                         _pm._guihide = DEREF(int, optlist->values[i]);
10768                         break;
10769 
10770                     case DBOPT_ASCII_LABEL:
10771                         _pm._ascii_labels = DEREF(int, optlist->values[i]);
10772                         break;
10773 
10774                     case DBOPT_NODENUM:
10775                         _pm._gnodeno = (int*)optlist->values[i];
10776                         break;
10777 
10778                     case DBOPT_MRGTREE_NAME:
10779                         _pm._mrgtree_name = (char *)optlist->values[i];
10780                         break;
10781 
10782                     case DBOPT_REGION_PNAMES:
10783                         _pm._region_pnames = (char **) optlist->values[i];
10784                         break;
10785 
10786                     case DBOPT_LLONGNZNUM:
10787                         _pm._llong_gnodeno = DEREF(int, optlist->values[i]);
10788                         break;
10789 
10790                     case DBOPT_CONSERVED:
10791                         _pm._conserved = DEREF(int, optlist->values[i]);
10792                         break;
10793 
10794                     case DBOPT_EXTENSIVE:
10795                         _pm._extensive = DEREF(int, optlist->values[i]);
10796                         break;
10797 
10798                     case DBOPT_MISSING_VALUE:
10799                         _pm._missing_value = DEREF(double, optlist->values[i]);
10800                         break;
10801 
10802                     case DBOPT_GHOST_NODE_LABELS:
10803                         _pm._ghost_node_labels = (char *)optlist->values[i];
10804                         break;
10805 
10806                     case DBOPT_ALT_NODENUM_VARS:
10807                         _pm._alt_nodenum_vars = (char **) optlist->values[i];
10808                         break;
10809 
10810                     default:
10811                         unused++;
10812                         break;
10813                 }
10814             }
10815             break;
10816 
10817         case DB_QUADMESH:
10818         case DB_QUADVAR:
10819             for (i = 0; i < optlist->numopts; i++)
10820             {
10821                 switch (optlist->options[i])
10822                 {
10823                     case DBOPT_TIME:
10824                         _qm._time = DEREF(float, optlist->values[i]);
10825                         _qm._time_set = TRUE;
10826                         break;
10827 
10828                     case DBOPT_DTIME:
10829                         _qm._dtime = DEREF(double, optlist->values[i]);
10830                         _qm._dtime_set = TRUE;
10831                         break;
10832 
10833                     case DBOPT_CYCLE:
10834                         _qm._cycle = DEREF(int, optlist->values[i]);
10835                         break;
10836 
10837                     case DBOPT_COORDSYS:
10838                         _qm._coord_sys = DEREF(int, optlist->values[i]);
10839                         break;
10840 
10841                     case DBOPT_FACETYPE:
10842                         _qm._facetype = DEREF(int, optlist->values[i]);
10843                         break;
10844 
10845                     case DBOPT_MAJORORDER:
10846                         _qm._majororder = DEREF(int, optlist->values[i]);
10847                         break;
10848 
10849                     case DBOPT_NSPACE:
10850                         _qm._nspace = DEREF(int, optlist->values[i]);
10851                         break;
10852 
10853                     case DBOPT_ORIGIN:
10854                         _qm._origin = DEREF(int, optlist->values[i]);
10855                         if (! _qm._baseindex_set)
10856                         {
10857                             for (j = 0; j < _qm._ndims; j++)
10858                                 _qm._baseindex[j] = _qm._origin;
10859                         }
10860                         break;
10861 
10862                     case DBOPT_PLANAR:
10863                         _qm._planar = DEREF(int, optlist->values[i]);
10864                         break;
10865 
10866                     case DBOPT_HI_OFFSET:
10867                         ip = (int *)optlist->values[i];
10868                         for (j = 0; j < _qm._ndims; j++)
10869                             _qm._hi_offset[j] = ip[j];
10870                         break;
10871 
10872                     case DBOPT_LO_OFFSET:
10873                         ip = (int *)optlist->values[i];
10874                         for (j = 0; j < _qm._ndims; j++)
10875                             _qm._lo_offset[j] = ip[j];
10876                         break;
10877 
10878                     case DBOPT_LABEL:
10879                         _qm._label = (char *)optlist->values[i];
10880                         break;
10881 
10882                     case DBOPT_XLABEL:
10883                         _qm._labels[0] = (char *)optlist->values[i];
10884                         break;
10885 
10886                     case DBOPT_YLABEL:
10887                         _qm._labels[1] = (char *)optlist->values[i];
10888                         break;
10889 
10890                     case DBOPT_ZLABEL:
10891                         _qm._labels[2] = (char *)optlist->values[i];
10892                         break;
10893 
10894                     case DBOPT_UNITS:
10895                         _qm._unit = (char *)optlist->values[i];
10896                         break;
10897 
10898                     case DBOPT_XUNITS:
10899                         _qm._units[0] = (char *)optlist->values[i];
10900                         break;
10901 
10902                     case DBOPT_YUNITS:
10903                         _qm._units[1] = (char *)optlist->values[i];
10904                         break;
10905 
10906                     case DBOPT_ZUNITS:
10907                         _qm._units[2] = (char *)optlist->values[i];
10908                         break;
10909 
10910                     case DBOPT_USESPECMF:
10911                         _qm._use_specmf = DEREF(int, optlist->values[i]);
10912                         break;
10913 
10914                     case DBOPT_ASCII_LABEL:
10915                         _qm._ascii_labels = DEREF(int, optlist->values[i]);
10916                         break;
10917 
10918                     case DBOPT_GROUPNUM:
10919                         DEPRECATE_MSG("DBOPT_GROUPNUM",4,6,"MRG Trees")
10920                         _qm._group_no = DEREF(int, optlist->values[i]);
10921                         break;
10922 
10923                     case DBOPT_BASEINDEX:
10924                         ip = (int *)optlist->values[i];
10925                         for (j = 0; j < _qm._ndims; j++)
10926                             _qm._baseindex[j] = ip[j];
10927                         _qm._baseindex_set = TRUE;
10928                         break;
10929 
10930                     case DBOPT_HIDE_FROM_GUI:
10931                         _qm._guihide = DEREF(int, optlist->values[i]);
10932                         break;
10933 
10934                     case DBOPT_MRGTREE_NAME:
10935                         _qm._mrgtree_name = (char *)optlist->values[i];
10936                         break;
10937 
10938                     case DBOPT_REGION_PNAMES:
10939                         _qm._region_pnames = (char **) optlist->values[i];
10940                         break;
10941 
10942                     case DBOPT_CONSERVED:
10943                         _qm._conserved = DEREF(int, optlist->values[i]);
10944                         break;
10945 
10946                     case DBOPT_EXTENSIVE:
10947                         _qm._extensive = DEREF(int, optlist->values[i]);
10948                         break;
10949 
10950                     case DBOPT_MISSING_VALUE:
10951                         _qm._missing_value = DEREF(double, optlist->values[i]);
10952                         break;
10953 
10954                     case DBOPT_GHOST_NODE_LABELS:
10955                         _qm._ghost_node_labels = (char *)optlist->values[i];
10956                         break;
10957 
10958                     case DBOPT_GHOST_ZONE_LABELS:
10959                         _qm._ghost_zone_labels = (char *)optlist->values[i];
10960                         break;
10961 
10962                     case DBOPT_ALT_NODENUM_VARS:
10963                         _qm._alt_nodenum_vars = (char **) optlist->values[i];
10964                         break;
10965 
10966                     case DBOPT_ALT_ZONENUM_VARS:
10967                         _qm._alt_zonenum_vars = (char **) optlist->values[i];
10968                         break;
10969 
10970                     default:
10971                         unused++;
10972                         break;
10973                 }
10974             }
10975             break;
10976 
10977         case DB_UCDMESH:
10978         case DB_UCDVAR:
10979             for (i = 0; i < optlist->numopts; i++)
10980             {
10981                 switch (optlist->options[i])
10982                 {
10983                     case DBOPT_TIME:
10984                         _um._time = DEREF(float, optlist->values[i]);
10985                         _um._time_set = TRUE;
10986                         break;
10987 
10988                     case DBOPT_DTIME:
10989                         _um._dtime = DEREF(double, optlist->values[i]);
10990                         _um._dtime_set = TRUE;
10991                         break;
10992 
10993                     case DBOPT_CYCLE:
10994                         _um._cycle = DEREF(int, optlist->values[i]);
10995                         break;
10996 
10997                     case DBOPT_COORDSYS:
10998                         _um._coord_sys = DEREF(int, optlist->values[i]);
10999                         break;
11000 
11001                     case DBOPT_TOPO_DIM:
11002                         /* The value of '_topo_dim' member is designed such
11003                            that a value of zero (which can be a valid topological
11004                            dimension specified by a caller) represents the
11005                            NOT SET value. So, we always add 1 to whatever the
11006                            caller gives us. */
11007                         _um._topo_dim = DEREF(int, optlist->values[i])+1;
11008                         break;
11009 
11010                     case DBOPT_FACETYPE:
11011                         _um._facetype = DEREF(int, optlist->values[i]);
11012                         break;
11013 
11014                     case DBOPT_ORIGIN:
11015                         _um._origin = DEREF(int, optlist->values[i]);
11016                         break;
11017 
11018                     case DBOPT_PLANAR:
11019                         _um._planar = DEREF(int, optlist->values[i]);
11020                         break;
11021 
11022                     case DBOPT_LABEL:
11023                         _um._label = (char *)optlist->values[i];
11024                         break;
11025 
11026                     case DBOPT_XLABEL:
11027                         _um._labels[0] = (char *)optlist->values[i];
11028                         break;
11029 
11030                     case DBOPT_YLABEL:
11031                         _um._labels[1] = (char *)optlist->values[i];
11032                         break;
11033 
11034                     case DBOPT_ZLABEL:
11035                         _um._labels[2] = (char *)optlist->values[i];
11036                         break;
11037 
11038                     case DBOPT_UNITS:
11039                         _um._unit = (char *)optlist->values[i];
11040                         break;
11041 
11042                     case DBOPT_XUNITS:
11043                         _um._units[0] = (char *)optlist->values[i];
11044                         break;
11045 
11046                     case DBOPT_YUNITS:
11047                         _um._units[1] = (char *)optlist->values[i];
11048                         break;
11049 
11050                     case DBOPT_ZUNITS:
11051                         _um._units[2] = (char *)optlist->values[i];
11052                         break;
11053 
11054                     case DBOPT_USESPECMF:
11055                         _um._use_specmf = DEREF(int, optlist->values[i]);
11056                         break;
11057 
11058                     case DBOPT_ASCII_LABEL:
11059                         _um._ascii_labels = DEREF(int, optlist->values[i]);
11060                         break;
11061 
11062                     case DBOPT_HI_OFFSET:
11063                         _um._hi_offset = DEREF(int, optlist->values[i]);
11064                         _um._hi_offset_set = TRUE;
11065                         break;
11066 
11067                     case DBOPT_LO_OFFSET:
11068                         _um._lo_offset = DEREF(int, optlist->values[i]);
11069                         _um._lo_offset_set = TRUE;
11070                         break;
11071 
11072                     case DBOPT_GROUPNUM:
11073                         DEPRECATE_MSG("DBOPT_GROUPNUM",4,6,"MRG Trees")
11074                         _um._group_no = DEREF(int, optlist->values[i]);
11075                         break;
11076 
11077                     case DBOPT_NODENUM:
11078                         _um._gnodeno = (int*)optlist->values[i];
11079                         break;
11080 
11081                     case DBOPT_PHZONELIST:
11082                         _um._phzl_name = (char *)optlist->values[i];
11083                         break;
11084 
11085                     case DBOPT_HIDE_FROM_GUI:
11086                         _um._guihide = DEREF(int, optlist->values[i]);
11087                         break;
11088 
11089                     case DBOPT_MRGTREE_NAME:
11090                         _um._mrgtree_name = (char *)optlist->values[i];
11091                         break;
11092 
11093                     case DBOPT_REGION_PNAMES:
11094                         _um._region_pnames = (char **) optlist->values[i];
11095                         break;
11096 
11097                     case DBOPT_TV_CONNECTIVITY:
11098                         _um._tv_connectivity = DEREF(int, optlist->values[i]);
11099                         break;
11100 
11101                     case DBOPT_DISJOINT_MODE:
11102                         _um._disjoint_mode = DEREF(int, optlist->values[i]);
11103                         break;
11104 
11105                     case DBOPT_LLONGNZNUM:
11106                         _um._llong_gnodeno = DEREF(int, optlist->values[i]);
11107                         break;
11108 
11109                     case DBOPT_CONSERVED:
11110                         _um._conserved = DEREF(int, optlist->values[i]);
11111                         break;
11112 
11113                     case DBOPT_EXTENSIVE:
11114                         _um._extensive = DEREF(int, optlist->values[i]);
11115                         break;
11116 
11117                     case DBOPT_MISSING_VALUE:
11118                         _um._missing_value = DEREF(double, optlist->values[i]);
11119                         break;
11120 
11121                     case DBOPT_GHOST_NODE_LABELS:
11122                         _um._ghost_node_labels = (char *)optlist->values[i];
11123                         break;
11124 
11125                     case DBOPT_ALT_NODENUM_VARS:
11126                         _um._alt_nodenum_vars = (char **) optlist->values[i];
11127                         break;
11128 
11129                     default:
11130                         unused++;
11131                         break;
11132                 }
11133             }
11134             break;
11135 
11136         case DB_ZONELIST:
11137             for (i = 0; i < optlist->numopts; i++)
11138             {
11139                 switch (optlist->options[i])
11140                 {
11141                     case DBOPT_ZONENUM:
11142                         _uzl._gzoneno = (int*)optlist->values[i];
11143                         break;
11144 
11145                     case DBOPT_LLONGNZNUM:
11146                         _uzl._llong_gzoneno = DEREF(int, optlist->values[i]);
11147                         break;
11148 
11149                     case DBOPT_GHOST_ZONE_LABELS:
11150                         _uzl._ghost_zone_labels = (char *)optlist->values[i];
11151                         break;
11152 
11153                     case DBOPT_ALT_ZONENUM_VARS:
11154                         _uzl._alt_zonenum_vars = (char **) optlist->values[i];
11155                         break;
11156 
11157                     default:
11158                         unused++;
11159                         break;
11160                 }
11161             }
11162             break;
11163 
11164         case DB_PHZONELIST:
11165             for (i = 0; i < optlist->numopts; i++)
11166             {
11167                 switch (optlist->options[i])
11168                 {
11169                     case DBOPT_ZONENUM:
11170                         _phzl._gzoneno = (int*)optlist->values[i];
11171                         break;
11172 
11173                     case DBOPT_LLONGNZNUM:
11174                         _phzl._llong_gzoneno = DEREF(int, optlist->values[i]);
11175                         break;
11176 
11177                     case DBOPT_GHOST_ZONE_LABELS:
11178                         _phzl._ghost_zone_labels = (char *)optlist->values[i];
11179                         break;
11180 
11181                     case DBOPT_ALT_ZONENUM_VARS:
11182                         _phzl._alt_zonenum_vars = (char **) optlist->values[i];
11183                         break;
11184 
11185                     default:
11186                         unused++;
11187                         break;
11188                 }
11189             }
11190             break;
11191 
11192         case DB_CSGZONELIST:
11193             for (i = 0; i < optlist->numopts; i++)
11194             {
11195                 switch (optlist->options[i])
11196                 {
11197                     case DBOPT_REGNAMES:
11198                         _csgzl._regnames = (char **) optlist->values[i];
11199                         break;
11200 
11201                     case DBOPT_ZONENAMES:
11202                         _csgzl._zonenames = (char **) optlist->values[i];
11203                         break;
11204 
11205                     case DBOPT_ALT_ZONENUM_VARS:
11206                         _csgzl._alt_zonenum_vars = (char **) optlist->values[i];
11207                         break;
11208 
11209                     default:
11210                         unused++;
11211                         break;
11212                 }
11213             }
11214             break;
11215 
11216         case DB_MULTIMESH:
11217             for (i = 0; i < optlist->numopts; i++)
11218             {
11219                 switch (optlist->options[i])
11220                 {
11221                     case DBOPT_TIME:
11222                         _mm._time = DEREF(float, optlist->values[i]);
11223                         _mm._time_set = TRUE;
11224                         break;
11225 
11226                     case DBOPT_DTIME:
11227                         _mm._dtime = DEREF(double, optlist->values[i]);
11228                         _mm._dtime_set = TRUE;
11229                         break;
11230 
11231                     case DBOPT_CYCLE:
11232                         _mm._cycle = DEREF(int, optlist->values[i]);
11233                         break;
11234 
11235                     case DBOPT_MATNOS:
11236                         _mm._matnos = (int *) optlist->values[i];
11237                         break;
11238 
11239                     case DBOPT_NMATNOS:
11240                         _mm._nmatnos = DEREF(int, optlist->values[i]);
11241                         break;
11242 
11243                     case DBOPT_MATNAME:
11244                         _mm._matname = (char *) optlist->values[i];
11245                         break;
11246 
11247                     case DBOPT_NMAT:
11248                         _mm._nmat = DEREF(int,optlist->values[i]);
11249                         break;
11250 
11251                     case DBOPT_NMATSPEC:
11252                         _mm._nmatspec = (int *) optlist->values[i];
11253                         break;
11254 
11255                     case DBOPT_BLOCKORIGIN:
11256                         _mm._blockorigin = DEREF(int, optlist->values[i]);
11257                         break;
11258 
11259                     case DBOPT_GROUPORIGIN:
11260                         DEPRECATE_MSG("DBOPT_GROUPORIGIN",4,6,"MRG Trees")
11261                         _mm._grouporigin = DEREF(int, optlist->values[i]);
11262                         break;
11263 
11264                     case DBOPT_NGROUPS:
11265                         DEPRECATE_MSG("DBOPT_NGROUPS",4,6,"MRG Trees")
11266                         _mm._ngroups = DEREF(int, optlist->values[i]);
11267                         break;
11268 
11269                     case DBOPT_EXTENTS_SIZE:
11270                         _mm._extentssize = DEREF(int, optlist->values[i]);
11271                         break;
11272 
11273                     case DBOPT_EXTENTS:
11274                         _mm._extents = (double *) optlist->values[i];
11275                         break;
11276 
11277                     case DBOPT_ZONECOUNTS:
11278                         _mm._zonecounts = (int *) optlist->values[i];
11279                         break;
11280 
11281                     case DBOPT_MIXLENS:
11282                         _mm._mixlens = (int *) optlist->values[i];
11283                         break;
11284 
11285                     case DBOPT_MATCOUNTS:
11286                         _mm._matcounts = (int *) optlist->values[i];
11287                         break;
11288 
11289                     case DBOPT_MATLISTS:
11290                         _mm._matlists = (int *) optlist->values[i];
11291                         break;
11292 
11293                     case DBOPT_HAS_EXTERNAL_ZONES:
11294                         _mm._has_external_zones = (int *) optlist->values[i];
11295                         break;
11296 
11297                     case DBOPT_HIDE_FROM_GUI:
11298                         _mm._guihide = DEREF(int, optlist->values[i]);
11299                         break;
11300 
11301                     case DBOPT_GROUPINGS_SIZE:
11302                         DEPRECATE_MSG("DBOPT_GROUPINGS_SIZE",4,6,"MRG Trees")
11303                         _mm._lgroupings = DEREF(int, optlist->values[i]);
11304                         break;
11305 
11306                     case DBOPT_GROUPINGS:
11307                         DEPRECATE_MSG("DBOPT_GROUPINGS",4,6,"MRG Trees")
11308                         _mm._groupings = (int *) optlist->values[i];
11309                         break;
11310 
11311                     case DBOPT_GROUPINGNAMES:
11312                         DEPRECATE_MSG("DBOPT_GROUPINGNAMES",4,6,"MRG Trees")
11313                         _mm._groupnames = (char **) optlist->values[i];
11314                         break;
11315 
11316                     case DBOPT_MATCOLORS:
11317                         _mm._matcolors = (char **) optlist->values[i];
11318                         break;
11319 
11320                     case DBOPT_MATNAMES:
11321                         _mm._matnames = (char **) optlist->values[i];
11322                         break;
11323 
11324                     case DBOPT_ALLOWMAT0:
11325                         _mm._allowmat0 = DEREF(int, optlist->values[i]);
11326                         break;
11327 
11328                     case DBOPT_MRGTREE_NAME:
11329                         _mm._mrgtree_name = (char *)optlist->values[i];
11330                         break;
11331 
11332                     case DBOPT_REGION_PNAMES:
11333                         _mm._region_pnames = (char **) optlist->values[i];
11334                         break;
11335 
11336                     case DBOPT_MMESH_NAME:
11337                         _mm._mmesh_name = (char *)optlist->values[i];
11338                         break;
11339 
11340                     case DBOPT_TENSOR_RANK:
11341                         _mm._tensor_rank = DEREF(int, optlist->values[i]);
11342                         break;
11343 
11344                     case DBOPT_TV_CONNECTIVITY:
11345                         _mm._tv_connectivity = DEREF(int, optlist->values[i]);
11346                         break;
11347 
11348                     case DBOPT_DISJOINT_MODE:
11349                         _mm._disjoint_mode = DEREF(int, optlist->values[i]);
11350                         break;
11351 
11352                     case DBOPT_TOPO_DIM:
11353                         /* The value of '_topo_dim' member is designed such
11354                            that a value of zero (which can be a valid topological
11355                            dimension specified by a caller) represents the
11356                            NOT SET value. So, we always add 1 to whatever the
11357                            caller gives us. */
11358                         _mm._topo_dim = DEREF(int, optlist->values[i])+1;
11359                         break;
11360 
11361                     case DBOPT_SPECNAMES:
11362                         _mm._specnames = (char **) optlist->values[i];
11363                         break;
11364 
11365                     case DBOPT_SPECCOLORS:
11366                         _mm._speccolors = (char **) optlist->values[i];
11367                         break;
11368 
11369                     case DBOPT_CONSERVED:
11370                         _mm._conserved = DEREF(int, optlist->values[i]);
11371                         break;
11372 
11373                     case DBOPT_EXTENSIVE:
11374                         _mm._extensive = DEREF(int, optlist->values[i]);
11375                         break;
11376 
11377                     case DBOPT_MB_FILE_NS:
11378                         _mm._file_ns = (char *) optlist->values[i];
11379                         break;
11380 
11381                     case DBOPT_MB_BLOCK_NS:
11382                         _mm._block_ns = (char *) optlist->values[i];
11383                         break;
11384 
11385                     case DBOPT_MB_BLOCK_TYPE:
11386                         _mm._block_type = DEREF(int, optlist->values[i]);
11387                         break;
11388 
11389                     case DBOPT_MB_EMPTY_LIST:
11390                         _mm._empty_list = (int *) optlist->values[i];
11391                         break;
11392 
11393                     case DBOPT_MB_EMPTY_COUNT:
11394                         _mm._empty_cnt = DEREF(int, optlist->values[i]);
11395                         break;
11396 
11397                     case DBOPT_MB_REPR_BLOCK_IDX:
11398                         /* +1 to support zero value indicating NOT SET */
11399                         _mm._repr_block_idx = DEREF(int,optlist->values[i])+1;
11400                         break;
11401 
11402                     case DBOPT_MISSING_VALUE:
11403                         _mm._missing_value = DEREF(double, optlist->values[i]);
11404                         break;
11405 
11406                     case DBOPT_ALT_NODENUM_VARS:
11407                         _mm._alt_nodenum_vars = (char**) optlist->values[i];
11408                         break;
11409 
11410                     case DBOPT_ALT_ZONENUM_VARS:
11411                         _mm._alt_zonenum_vars = (char**) optlist->values[i];
11412                         break;
11413 
11414                     default:
11415                         unused++;
11416                         break;
11417                 }
11418             }
11419             break;
11420 
11421         case DB_CURVE:
11422             for (i = 0; i < optlist->numopts; i++)
11423             {
11424                 switch (optlist->options[i])
11425                 {
11426                     case DBOPT_LABEL:
11427                         _cu._label = (char *)optlist->values[i];
11428                         break;
11429 
11430                     case DBOPT_XLABEL:
11431                         _cu._labels[0] = (char *)optlist->values[i];
11432                         break;
11433 
11434                     case DBOPT_YLABEL:
11435                         _cu._labels[1] = (char *)optlist->values[i];
11436                         break;
11437 
11438                     case DBOPT_XUNITS:
11439                         _cu._units[0] = (char *)optlist->values[i];
11440                         break;
11441 
11442                     case DBOPT_YUNITS:
11443                         _cu._units[1] = (char *)optlist->values[i];
11444                         break;
11445 
11446                     case DBOPT_XVARNAME:
11447                         _cu._varname[0] = (char *)optlist->values[i];
11448                         break;
11449 
11450                     case DBOPT_YVARNAME:
11451                         _cu._varname[1] = (char *)optlist->values[i];
11452                         break;
11453 
11454                     case DBOPT_HIDE_FROM_GUI:
11455                         _cu._guihide = DEREF(int, optlist->values[i]);
11456                         break;
11457 
11458                     case DBOPT_REFERENCE:
11459                         _cu._reference = (char *)optlist->values[i];
11460                         break;
11461 
11462                     case DBOPT_COORDSYS:
11463                         _cu._coord_sys = DEREF(int, optlist->values[i]);
11464                         break;
11465 
11466                     case DBOPT_MISSING_VALUE:
11467                         _cu._missing_value = DEREF(double, optlist->values[i]);
11468                         break;
11469 
11470                     default:
11471                         unused++;
11472                         break;
11473                 }
11474             }
11475             break;
11476 
11477         case DB_DEFVARS:
11478             for (i = 0; i < optlist->numopts; i++)
11479             {
11480                 switch (optlist->options[i])
11481                 {
11482                     case DBOPT_HIDE_FROM_GUI:
11483                         _dv._guihide = DEREF(int, optlist->values[i]);
11484                         break;
11485 
11486                     default:
11487                         unused++;
11488                         break;
11489                 }
11490             }
11491             break;
11492 
11493         case DB_MRGTREE:
11494             for (i = 0; i < optlist->numopts; i++)
11495             {
11496                 switch (optlist->options[i])
11497                 {
11498                     case DBOPT_MRGV_ONAMES:
11499                         _mrgt._mrgvar_onames = (char **) optlist->values[i];
11500                         break;
11501 
11502                     case DBOPT_MRGV_RNAMES:
11503                         _mrgt._mrgvar_rnames = (char **) optlist->values[i];
11504                         break;
11505 
11506                     default:
11507                         unused++;
11508                         break;
11509                 }
11510             }
11511             break;
11512 
11513         default:
11514             return db_perror(NULL, E_NOTIMP, me);
11515     }
11516 
11517     return 0;
11518 }
11519 
11520 /*-------------------------------------------------------------------------
11521  * Function:    DBInqCompoundarray
11522  *
11523  * Purpose:     Inquire compound array attributes
11524  *
11525  * Return:      Success:        OKAY
11526  *
11527  *              Failure:        OOPS
11528  *
11529  * Arguments:
11530  *      dbfile         ptr to data file
11531  *      array_name     array name
11532  *
11533  *                Output args
11534  *      elemnames      simple array names
11535  *      elemlengths    simple array sizes
11536  *      nelems         number of simple arrys
11537  *      nvalues        number of values
11538  *      datatype       value data type
11539  *
11540  * Programmer:  matzke@viper
11541  *              Tue Oct 25 13:58:53 PDT 1994
11542  *
11543  * Modifications:
11544  *    matzke@viper, Mon Oct 31 13:39:10 PST 1994
11545  *    No longer calls DBGetCompoundarray.
11546  *
11547  *    Eric Brugger, Tue Feb  7 08:09:26 PST 1995
11548  *    I replaced API_END with API_END_NOPOP.
11549  *
11550  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
11551  *    Added a check for variable name validity.
11552  *-------------------------------------------------------------------------*/
11553 PUBLIC int
DBInqCompoundarray(DBfile * dbfile,const char * array_name,char ** elemnames[],int ** elemlengths,int * nelems,int * nvalues,int * datatype)11554 DBInqCompoundarray(DBfile *dbfile, const char *array_name,
11555                    char **elemnames[], int **elemlengths, int *nelems,
11556                    int *nvalues, int *datatype)
11557 
11558 {
11559     DBcompoundarray *ca = NULL;
11560 
11561     API_BEGIN2("DBInqCompoundarray", int, -1, array_name) {
11562         if (!array_name || !*array_name)
11563             API_ERROR("array name", E_BADARGS);
11564         if (SILO_Globals.enableGrabDriver == TRUE)
11565             API_ERROR("DBInqCompoundarray", E_GRABBED) ;
11566         if (elemnames)
11567             *elemnames = NULL;
11568         if (elemlengths)
11569             *elemlengths = NULL;
11570         if (nelems)
11571             *nelems = 0;
11572         if (nvalues)
11573             *nvalues = 0;
11574         if (datatype)
11575             *datatype = 0;
11576 
11577         if (!dbfile->pub.g_ca)
11578             API_ERROR(dbfile->pub.name, E_NOTIMP);
11579         ca = DBGetCompoundarray(dbfile, array_name);
11580         if (!ca)
11581             API_ERROR("DBGetCompoundarray", E_CALLFAIL);
11582 
11583         if (elemnames) {
11584             *elemnames = ca->elemnames;
11585             ca->elemnames = NULL;  /*so we don't free it... */
11586         }
11587         if (elemlengths) {
11588             *elemlengths = ca->elemlengths;
11589             ca->elemlengths = NULL;
11590         }
11591         if (nelems)
11592             *nelems = ca->nelems;
11593         if (nvalues)
11594             *nvalues = ca->nvalues;
11595         if (datatype)
11596             *datatype = ca->datatype;
11597 
11598         DBFreeCompoundarray(ca);
11599     }
11600     API_END;
11601 
11602     return(0);
11603 }
11604 
11605 /*-------------------------------------------------------------------------
11606  * Function:    DBGetComponentNames
11607  *
11608  * Purpose:     Returns the component names for the specified object.
11609  *              Each component name also has a variable name under which
11610  *              the component value is stored in the data file.  The
11611  *              COMP_NAMES and FILE_NAMES output arguments will point to
11612  *              an array of pointers to names.  Each name as well as the
11613  *              two arrays will be allocated with `malloc'.
11614  *
11615  * Return:      Success:        Number of components found for the
11616  *                              specified object.
11617  *
11618  *              Failure:        zero.
11619  *
11620  * Programmer:  Robb Matzke
11621  *              robb@callisto.nuance.mdn.com
11622  *              May 20, 1996
11623  *
11624  * Modifications:
11625  *    Sean Ahern, Tue Sep 28 10:48:06 PDT 1999
11626  *    Added a check for variable name validity.
11627  *
11628  *    Mark C. Miller, Tue Sep  6 10:57:55 PDT 2005
11629  *    Deprecated this function
11630  *-------------------------------------------------------------------------*/
11631 PUBLIC int
DBGetComponentNames(DBfile * dbfile,const char * objname,char *** comp_names,char *** file_names)11632 DBGetComponentNames(DBfile *dbfile, const char *objname,
11633                     char ***comp_names, char ***file_names)
11634 {
11635     int retval;
11636 
11637     API_DEPRECATE2("DBGetComponentNames", int, -1, objname, 4,6,"")
11638     {
11639         if (!dbfile)
11640             API_ERROR(NULL, E_NOFILE);
11641         if (!dbfile->pub.g_compnames)
11642             API_ERROR(dbfile->pub.name, E_NOTIMP);
11643         if (!objname || !*objname)
11644             API_ERROR("object name", E_BADARGS);
11645 
11646         retval = (dbfile->pub.g_compnames) (dbfile, objname,
11647                                             comp_names, file_names);
11648         API_RETURN(retval);
11649     }
11650     API_END_NOPOP;  /* If API_RETURN above is removed, use API_END instead */
11651 }
11652 
11653 /*----------------------------------------------------------------------
11654  * Routine                                             db_SplitShapelist
11655  *
11656  * Purpose
11657  *
11658  *    Split the shapecnts in the zone list so that an entry in the
11659  *    shapecnt array will either refer to all real zones or all ghost
11660  *    zones.
11661  *
11662  * Programmer
11663  *
11664  *    Eric Brugger, January 22, 1999
11665  *
11666  * Notes
11667  *
11668  * Modifications
11669  *    Eric Brugger, Wed Mar 31 11:36:42 PST 1999
11670  *    Modify the routine to handle polyhedra.  This turned out to be
11671  *    a significant rewrite of the routine.
11672  *
11673  *    Eric Brugger, Tue Apr 20 09:24:51 PDT 1999
11674  *    Correct a bug where the nshapes field was always zero when the
11675  *    shapetype field was NULL.
11676  *
11677  *    Jeremy Meredith, Fri Aug 13 13:53:57 PDT 1999
11678  *    Corrected a bug where nshapes was still not incremented enough if
11679  *    shapetype was NULL.  This was causing ghost zones to disappear.
11680  *
11681  *    Mark C. Miller, Mon Jun 21 18:06:36 PDT 2004
11682  *    Moved from silo_pdb.c to public place where any driver can call
11683  *--------------------------------------------------------------------*/
11684 INTERNAL int
db_SplitShapelist(DBucdmesh * um)11685 db_SplitShapelist (DBucdmesh *um)
11686 {
11687     int       *shapecnt=NULL, *shapesize=NULL, *shapetype=NULL, nshapes;
11688     int       *zonelist=NULL, nzones;
11689     int        min_index, max_index;
11690     int       *shapecnt2=NULL, *shapesize2=NULL, *shapetype2=NULL, nshapes2;
11691     int        i, iz, izl, deltaiz;
11692     int        isplit, splits[3];
11693 
11694     shapecnt  = um->zones->shapecnt;
11695     shapesize = um->zones->shapesize;
11696     shapetype = um->zones->shapetype;
11697     nshapes   = um->zones->nshapes;
11698     zonelist  = um->zones->nodelist;
11699     min_index = um->zones->min_index;
11700     max_index = um->zones->max_index;
11701     nzones    = um->zones->nzones;
11702 
11703     nshapes2   = 0;
11704     shapecnt2  = ALLOC_N (int, nshapes+2);
11705     shapesize2 = ALLOC_N (int, nshapes+2);
11706     if (shapetype != NULL)
11707     {
11708         shapetype2 = ALLOC_N (int, nshapes+2);
11709     }
11710 
11711     if (min_index > 0)
11712     {
11713         splits[0] = min_index;
11714         splits[1] = max_index + 1;
11715         splits[2] = nzones;
11716     }
11717     else
11718     {
11719         splits[0] = max_index + 1;
11720         splits[1] = nzones;
11721         splits[2] = 0;
11722     }
11723 
11724     isplit = 0;
11725     i = 0;
11726     iz = 0;
11727     izl = 0;
11728     while (iz < nzones)
11729     {
11730         if (splits[isplit] - iz >= shapecnt[i])
11731         {
11732             shapecnt2 [nshapes2]   = shapecnt[i];
11733             shapesize2[nshapes2]   = shapesize[i];
11734             if (shapetype != NULL)
11735             {
11736                 shapetype2[nshapes2] = shapetype[i];
11737             }
11738             nshapes2++;
11739             isplit += (splits[isplit] - iz == shapecnt[i]) ? 1 : 0;
11740             iz += shapecnt[i];
11741             if (shapetype != NULL && shapetype[i] == DB_ZONETYPE_POLYHEDRON)
11742             {
11743                 izl += shapesize[i];
11744             }
11745             else
11746             {
11747                 izl += shapesize[i] * shapecnt[i];
11748             }
11749             i++;
11750         }
11751         else
11752         {
11753             deltaiz = splits[isplit] - iz;
11754             shapecnt2[nshapes2] = deltaiz;
11755             if (shapetype != NULL && shapetype[i] == DB_ZONETYPE_POLYHEDRON)
11756             {
11757                 int       j, k;
11758                 int       izlInit, nFaces;
11759 
11760                 izlInit = izl;
11761                 for (j = 0; j < deltaiz; j++)
11762                 {
11763                     nFaces = zonelist[izl++];
11764                     for (k = 0; k < nFaces; k++)
11765                     {
11766                         izl += zonelist[izl] + 1;
11767                     }
11768                 }
11769                 shapesize2[nshapes2] = izl - izlInit;
11770                 shapesize[i] -= izl - izlInit;
11771             }
11772             else
11773             {
11774                 izl += shapesize[i] * deltaiz;
11775                 shapesize2[nshapes2] = shapesize[i];
11776             }
11777             if (shapetype != NULL)
11778             {
11779                 shapetype2[nshapes2] = shapetype[i];
11780             }
11781             nshapes2++;
11782             shapecnt[i] -= deltaiz;
11783             isplit++;
11784             iz += deltaiz;
11785         }
11786     }
11787 
11788     FREE (shapecnt);
11789     FREE (shapesize);
11790     FREE (shapetype);
11791     um->zones->shapecnt  = shapecnt2;
11792     um->zones->shapesize = shapesize2;
11793     um->zones->shapetype = shapetype2;
11794     um->zones->nshapes   = nshapes2;
11795 
11796     return 0;
11797 }
11798 
11799 /*----------------------------------------------------------------------
11800  *  Routine                                   db_ResetGlobalData_Csgmesh
11801  *
11802  *  Purpose
11803  *
11804  *      Reset global data to default values. For internal use only.
11805  *
11806  *  Programmer
11807  *
11808  *    Mark C. Miller, Wed Aug  3 14:39:03 PDT 2005
11809  *
11810  *  Modifications:
11811  *    Mark C. Miller, Mon Jan 12 16:29:19 PST 2009
11812  *    Removed explicit setting of data members already handled
11813  *    correctly by memset to zero.
11814  *--------------------------------------------------------------------*/
11815 INTERNAL int
db_ResetGlobalData_Csgmesh()11816 db_ResetGlobalData_Csgmesh () {
11817 
11818    memset(&_csgm, 0, sizeof(_csgm));
11819    _csgm._use_specmf = DB_OFF;
11820    _csgm._group_no = -1;
11821    _csgm._missing_value = DB_MISSING_VALUE_NOT_SET;
11822 
11823    return 0;
11824 }
11825 /*----------------------------------------------------------------------
11826  *  Routine                                 db_ResetGlobalData_PointMesh
11827  *
11828  *  Purpose
11829  *
11830  *      Reset global data to default values. For internal use only.
11831  *
11832  *  Programmer
11833  *
11834  *      Jeffery W. Long, NSSD-B
11835  *
11836  *  Notes
11837  *
11838  *      It is assumed that _ndims has a valid value before this
11839  *      function is invoked. (It is assigned to _nspace.)
11840  *
11841  *  Modifications
11842  *
11843  *      Al Leibee, Mon Apr 18 07:45:58 PDT 1994
11844  *      Added _dtime.
11845  *
11846  *      Jeremy Meredith, Fri May 21 10:04:25 PDT 1999
11847  *      Init group_no to -1.
11848  *
11849  *    Mark C. Miller, Mon Jun 21 18:06:36 PDT 2004
11850  *    Moved from silo_pdb.c to public place where any driver can call
11851  *
11852  *    Mark C. Miller, Mon Jan 12 16:29:19 PST 2009
11853  *    Removed explicit setting of data members already handled
11854  *    correctly by memset to zero.
11855  *--------------------------------------------------------------------*/
11856 INTERNAL int
db_ResetGlobalData_PointMesh(int ndims)11857 db_ResetGlobalData_PointMesh (int ndims) {
11858 
11859    memset(&_pm, 0, sizeof(_pm));
11860    _pm._ndims = ndims;
11861    _pm._nspace = ndims;
11862    _pm._group_no = -1;
11863    _pm._missing_value = DB_MISSING_VALUE_NOT_SET;
11864    return 0;
11865 }
11866 
11867 /*----------------------------------------------------------------------
11868  *  Routine                                  db_ResetGlobalData_QuadMesh
11869  *
11870  *  Purpose
11871  *
11872  *      Reset global data to default values. For internal use only.
11873  *
11874  *  Programmer
11875  *
11876  *      Jeffery W. Long, NSSD-B
11877  *
11878  *  Notes
11879  *
11880  *      It is assumed that _ndims has a valid value before this
11881  *      function is invoked. (It is assigned to _nspace.)
11882  *
11883  *  Modifications
11884  *
11885  *     Al Leibee, Wed Aug  3 16:57:38 PDT 1994
11886  *     Added _use_specmf.
11887  *
11888  *     Al Leibee, Sun Apr 17 07:54:25 PDT 1994
11889  *     Added dtime.
11890  *
11891  *     Robb Matzke, 18 Jun 1997
11892  *     Initialize ascii_labels field to FALSE.
11893  *
11894  *     Eric Brugger, Mon Oct  6 15:11:26 PDT 1997
11895  *     I modified the routine to initialize lo_offset and hi_offset.
11896  *
11897  *     Jeremy Meredith, Fri May 21 10:04:25 PDT 1999
11898  *     Init group_no to -1.  Init baseindex and baseindex_set.
11899  *
11900  *    Mark C. Miller, Mon Jun 21 18:06:36 PDT 2004
11901  *    Moved from silo_pdb.c to public place where any driver can call
11902  *
11903  *    Mark C. Miller, Mon Jan 12 16:29:19 PST 2009
11904  *    Removed explicit setting of data members already handled
11905  *    correctly by memset to zero.
11906  *--------------------------------------------------------------------*/
11907 INTERNAL int
db_ResetGlobalData_QuadMesh(int ndims)11908 db_ResetGlobalData_QuadMesh (int ndims) {
11909 
11910    FREE(_qm._meshname);
11911    memset(&_qm, 0, sizeof(_qm));
11912 
11913    _qm._coord_sys = DB_OTHER;
11914    _qm._facetype = DB_RECTILINEAR;
11915    _qm._ndims = ndims;
11916    _qm._nspace = ndims;
11917    _qm._planar = DB_AREA;
11918    _qm._use_specmf = DB_OFF;
11919    _qm._group_no = -1;
11920    _qm._missing_value = DB_MISSING_VALUE_NOT_SET;
11921 
11922    return 0;
11923 }
11924 
11925 
11926 /*-------------------------------------------------------------------------
11927  * Function:    db_ResetGlobalData_Curve
11928  *
11929  * Purpose:     Reset global data to default values.
11930  *
11931  * Return:      void
11932  *
11933  * Programmer:  Robb Matzke
11934  *              robb@callisto.nuance.com
11935  *              May 16, 1996
11936  *
11937  * Modifications:
11938  *
11939  *    Mark C. Miller, Mon Jun 21 18:06:36 PDT 2004
11940  *    Moved from silo_pdb.c to public place where any driver can call
11941  *-------------------------------------------------------------------------*/
11942 INTERNAL void
db_ResetGlobalData_Curve(void)11943 db_ResetGlobalData_Curve (void) {
11944 
11945    memset (&_cu, 0, sizeof(_cu)) ;
11946    _cu._missing_value = DB_MISSING_VALUE_NOT_SET;
11947 }
11948 
11949 /*----------------------------------------------------------------------
11950  *  Routine                                   db_ResetGlobalData_Ucdmesh
11951  *
11952  *  Purpose
11953  *
11954  *      Reset global data to default values. For internal use only.
11955  *
11956  *  Programmer
11957  *
11958  *      Jeffery W. Long, NSSD-B
11959  *
11960  *  Notes
11961  *
11962  *      It is assumed that _ndims has a valid value before this
11963  *      function is invoked. (It is assigned to _nspace.)
11964  *
11965  *  Modifications
11966  *     Al Leibee, Wed Aug  3 16:57:38 PDT 1994
11967  *     Added _use_specmf.
11968  *
11969  *     Al Leibee, Mon Apr 18 07:45:58 PDT 1994
11970  *     Added _dtime.
11971  *
11972  *     Eric Brugger, Wed Oct 15 14:45:47 PDT 1997
11973  *     Added _hi_offset and _lo_offset.
11974  *
11975  *     Jeremy Meredith, Fri May 21 10:04:25 PDT 1999
11976  *     Init group_no to -1.
11977  *
11978  *     Mark C. Miller, Mon Jun 21 18:06:36 PDT 2004
11979  *     Moved from silo_pdb.c to public place where any driver can call
11980  *
11981  *     Brad Whitlock, Wed Jan 18 15:38:39 PST 2006
11982  *     Added _ascii_labels.
11983  *
11984  *     Thomas R. Treadway, Wed Jun 28 10:31:45 PDT 2006
11985  *     Added _topo_dim..
11986  *
11987  *     Mark C. Miller, Tue Jan  6 22:12:43 PST 2009
11988  *     Made default value for topo_dim to be NOT SET (-1).
11989  *
11990  *     Mark C. Miller, Mon Jan 12 16:26:08 PST 2009
11991  *     Replaced 'topo_dim' with 'tdim_plus1', removed it from being
11992  *     explicitly set. Likewise, removed explicit setting of other
11993  *     entries that are already correctly handled by memset to zero.
11994  *--------------------------------------------------------------------*/
11995 INTERNAL int
db_ResetGlobalData_Ucdmesh(int ndims,int nnodes,int nzones)11996 db_ResetGlobalData_Ucdmesh (int ndims, int nnodes, int nzones) {
11997 
11998    memset(&_um, 0, sizeof(_um));
11999    _um._coord_sys = DB_OTHER;
12000    _um._facetype = DB_RECTILINEAR;
12001    _um._ndims = ndims;
12002    _um._nnodes = nnodes;
12003    _um._nzones = nzones;
12004    _um._planar = DB_OTHER;
12005    _um._use_specmf = DB_OFF;
12006    _um._group_no = -1;
12007    _um._missing_value = DB_MISSING_VALUE_NOT_SET;
12008 
12009    return 0;
12010 }
12011 
12012 /*----------------------------------------------------------------------
12013  *  Routine                               db_ResetGlobalData_Ucdzonelist
12014  *
12015  *  Purpose
12016  *
12017  *      Reset global data to default values. For internal use only.
12018  *
12019  *  Programmer
12020  *
12021  *      Jeremy Meredith, May 21 1999
12022  *
12023  *  Notes
12024  *
12025  *  Modifications
12026  *
12027  *      Hank Childs, Thu Jan  6 16:10:03 PST 2000
12028  *      Added void to function signature to avoid compiler warning.
12029  *
12030  *    Mark C. Miller, Mon Jun 21 18:06:36 PDT 2004
12031  *    Moved from silo_pdb.c to public place where any driver can call
12032  *--------------------------------------------------------------------*/
12033 INTERNAL int
db_ResetGlobalData_Ucdzonelist(void)12034 db_ResetGlobalData_Ucdzonelist (void) {
12035 
12036    memset(&_uzl, 0, sizeof(_uzl));
12037 
12038    return 0;
12039 }
12040 
12041 /*----------------------------------------------------------------------
12042  * Routine                                  db_ResetGlobalData_MultiMesh
12043  *
12044  * Purpose
12045  *
12046  *    Reset global data to default values. For internal use only.
12047  *
12048  * Programmer
12049  *
12050  *    Eric Brugger, January 12, 1996
12051  *
12052  * Notes
12053  *
12054  * Modifications
12055  *    Eric Brugger, Thu Oct 16 10:40:00 PDT 1997
12056  *    I added the options DBOPT_MATNOS and DBOPT_NMATNOS.
12057  *
12058  *    Jeremy Meredith Sept 18 1998
12059  *    Added options DBOPT_MATNAME, DBOPT_NMAT, and DBOPT_NMATSPEC.
12060  *
12061  *    Jeremy Meredith, Fri May 21 10:04:25 PDT 1999
12062  *    Added _blockorigin, _grouporigin, and _ngroups.
12063  *
12064  *    Mark C. Miller, Mon Jun 21 18:06:36 PDT 2004
12065  *    Moved from silo_pdb.c to public place where any driver can call
12066  *
12067  *    Thomas R. Treadway, Thu Jul 20 11:06:27 PDT 2006
12068  *    Added _lgroupings, _groupings, and _groupnames.
12069  *
12070  *    Mark C. Miller, Mon Jan 12 16:28:18 PST 2009
12071  *    Removed explicit setting of members already correctly handled
12072  *    by memset to zero.
12073  *
12074  *    Mark C. Miller, Thu Aug 30 17:55:43 PDT 2012
12075  *    Removed setting nmatnos to -1.
12076  *--------------------------------------------------------------------*/
12077 INTERNAL int
db_ResetGlobalData_MultiMesh(void)12078 db_ResetGlobalData_MultiMesh (void) {
12079    memset(&_mm, 0, sizeof(_mm));
12080    _mm._nmat = -1;
12081    _mm._blockorigin = 1;
12082    _mm._grouporigin = 1;
12083    _mm._missing_value = DB_MISSING_VALUE_NOT_SET;
12084    return 0;
12085 }
12086 
12087 /*----------------------------------------------------------------------
12088  * Routine                                  db_ResetGlobalData_Defvars
12089  *
12090  * Purpose
12091  *
12092  *    Reset global data to default values. For internal use only.
12093  *
12094  * Programmer:
12095  *
12096  *    Mark C. Miller, March 22, 2006
12097  *--------------------------------------------------------------------*/
12098 INTERNAL int
db_ResetGlobalData_Defvars(void)12099 db_ResetGlobalData_Defvars (void) {
12100    memset(&_dv, 0, sizeof(_dv));
12101    return 0;
12102 }
12103 
12104 INTERNAL int
db_ResetGlobalData_Mrgtree(void)12105 db_ResetGlobalData_Mrgtree (void) {
12106    memset(&_mrgt, 0, sizeof(_mrgt));
12107    return 0;
12108 }
12109 
12110 /*----------------------------------------------------------------------
12111  * Routine                                  db_FullName2BaseName
12112  *
12113  * Purpose
12114  *
12115  *    Given a the full path name of an object in the db, return
12116  *    the object's basename.
12117  *
12118  * Programmer
12119  *
12120  *    Mark C. Miller, June 22, 2004
12121  *
12122  * Modifications:
12123  *    Mark C. Miller, Thu Sep  7 10:50:55 PDT 2006
12124  *    Made it just use Jim Reus' new basename routine.
12125  *--------------------------------------------------------------------*/
12126 INTERNAL char *
db_FullName2BaseName(const char * path)12127 db_FullName2BaseName(const char *path)
12128 {
12129    return db_basename(path);
12130 }
12131 
12132 /*----------------------------------------------------------------------
12133  * Purpose
12134  *
12135  *    catenate an array of strings into a single, semicolon seperated
12136  *    string list
12137  *
12138  * Programmer
12139  *
12140  *    Mark C. Miller, July 20, 2005
12141  *
12142  * Modifications:
12143  *    Mark C. Miller, Wed Oct  3 21:51:42 PDT 2007
12144  *    Made it handle null string as no chars output and empty string
12145  *    ("") as '\n' output so during readback, we can construct either
12146  *    null ptrs or emtpy strings correctly.
12147  *    Made it handle a variable length list where n is unspecified.
12148  *
12149  *    Mark C. Miller, Wed Jul 14 20:38:46 PDT 2010
12150  *    Made this function public, replacing 'db_' with 'DB' in name.
12151  *--------------------------------------------------------------------*/
12152 PUBLIC void
DBStringArrayToStringList(char const * const * strArray,int n,char ** strList,int * m)12153 DBStringArrayToStringList(
12154     char const * const *strArray,
12155     int n,
12156     char **strList,
12157     int *m
12158 )
12159 {
12160     int i, len;
12161     char *s = NULL;
12162 
12163     /* if n is unspecified, determine it by counting forward until
12164        we get a null pointer */
12165     if (n < 0)
12166     {
12167         n = 0;
12168         while (strArray[n] != 0)
12169             n++;
12170     }
12171 
12172     /*
12173      * Create a string which is a semi-colon separated list of strings
12174      */
12175      for (i=len=0; i<n; i++)
12176      {
12177          if (strArray[i])
12178              len += strlen(strArray[i])+1;
12179          else
12180              len += 2;
12181      }
12182      s = (char*)malloc(len+1);
12183      for (i=len=0; i<n; i++) {
12184          if (i) s[len++] = ';';
12185          if (strArray[i])
12186          {
12187              strcpy(s+len, strArray[i]);
12188              len += strlen(strArray[i]);
12189          }
12190          else
12191          {
12192              s[len++] = '\n';
12193          }
12194      }
12195      len++; /*count last null*/
12196 
12197      *strList = s;
12198      *m = len;
12199 }
12200 
12201 /*----------------------------------------------------------------------
12202  * Purpose
12203  *
12204  *    Decompose a single, semicolon seperated string list into an array
12205  *    of strings
12206  *
12207  * Programmer
12208  *
12209  *    Mark C. Miller, July 20, 2005
12210  *
12211  * Modfications:
12212  *
12213  *    Mark C. Miller, Fri Jul 14 23:39:32 PDT 2006
12214  *    Fixed problem with empty strings in the input list being skipped
12215  *
12216  *    Mark C. Miller, Wed Oct  3 21:54:35 PDT 2007
12217  *    Made it return empty or null strings depending on input
12218  *    Made it handle a variable length list where n is unspecified
12219  *
12220  *    Mark C. Miller, Mon Nov  9 12:10:47 PST 2009
12221  *    Added logic to handle swapping of slash character between
12222  *    windows/linux. Note that swapping of slash character only
12223  *    makes sense in certain context and only when it appears in
12224  *    a string BEFORE a colon character. We try to minimize the
12225  *    amount of work we do looking for a colon character by
12226  *    remembering where we find it in the last substring.
12227  *
12228  *    Mark C. Miller, Thu Dec 17 17:09:27 PST 2009
12229  *    Fixed UMR on strLen when n>=0.
12230  *
12231  *    Mark C. Miller, Wed Jul 14 20:38:46 PDT 2010
12232  *    Made this function public, replacing 'db_' with 'DB' in name.
12233  *    Merged fixes from 4.7.3 patches to fix problems with swaping
12234  *    the slash character.
12235  *
12236  *    Mark C. Miller, Wed Jun 30 16:01:17 PDT 2010
12237  *    Made logic for handling slash swap more sane. Now, swapping is
12238  *    performed AFTER the list of strings has been broken out into
12239  *    separate arrays.
12240  *
12241  *    Mark C. Miller, Fri Oct 12 22:57:23 PDT 2012
12242  *    Changed interface to return value for number of strings as well
12243  *    as accept an input value or nothing at all.
12244  *--------------------------------------------------------------------*/
12245 PUBLIC char **
DBStringListToStringArray(char const * strList,int * _n,int skipSemicolonAtIndexZero)12246 DBStringListToStringArray(char const *strList, int *_n, int skipSemicolonAtIndexZero)
12247 {
12248     int i, l, n, add1 = 0;
12249     char **retval;
12250 
12251     /* if n is unspecified (<0), compute it by counting semicolons */
12252     if (_n == 0 || *_n < 0)
12253     {
12254         add1 = 1;
12255         n = 1;
12256         i = (skipSemicolonAtIndexZero&&strList[0]==';')?1:0;
12257         while (strList[i] != '\0')
12258         {
12259             if (strList[i] == ';')
12260                 n++;
12261             i++;
12262         }
12263     }
12264     else
12265     {
12266         n = *_n;
12267     }
12268 
12269     retval = (char**) calloc(n+add1, sizeof(char*));
12270     for (i=0, l=(skipSemicolonAtIndexZero&&strList[0]==';')?1:0; i<n; i++)
12271     {
12272         if (strList[l] == ';')
12273         {
12274             retval[i] = STRDUP("");
12275             l += 1;
12276         }
12277         else if (strList[l] == '\n')
12278         {
12279             retval[i] = 0;
12280             l += 2;
12281         }
12282         else
12283         {
12284             int len, lstart = l;
12285             while (strList[l] != ';' && strList[l] != '\0')
12286                 l++;
12287             len = l-lstart;
12288             retval[i] = (char *) malloc(len+1);
12289             memcpy(retval[i],&strList[lstart],len);
12290             retval[i][len] = '\0';
12291             l++;
12292         }
12293     }
12294     if (add1) retval[i] = 0;
12295 
12296     /* Return value of n computed if requested */
12297     if (_n && *_n < 0) *_n = n;
12298 
12299     return retval;
12300 }
12301 
12302 INTERNAL int
db_StringListToStringArrayMBOpt(char * strList,char *** retArray,char ** alloc_flag,int nblocks)12303 db_StringListToStringArrayMBOpt(char *strList, char ***retArray, char **alloc_flag, int nblocks)
12304 {
12305     int i=0, s=0, n=0, hasColon=0, nearlyDone = 0, completelyDone = 0, slashCharsToSwap[128];
12306     char **strArray;
12307     static char const *me = "DBStringListToStringArrayMBOpt";
12308 
12309     if (!strList) return 0;
12310 
12311     if (nblocks <= 0)
12312         return db_perror("nblocks", E_BADARGS, me);
12313 
12314     strArray = (char **) malloc(nblocks * sizeof(char*));
12315     if (strList[0] == ';')
12316         i = 1;
12317     strArray[n++] = &strList[i];
12318     while (!completelyDone)
12319     {
12320         switch (strList[i])
12321         {
12322             case '\0':
12323                 completelyDone = 1; // note fall-through to next case
12324             case ';':
12325             {
12326                 strList[i] = '\0';
12327                 if (!completelyDone) i++;
12328                 if (strList[i] != '\0')
12329                     strArray[n++] = &strList[i];
12330                 if (hasColon)
12331                 {
12332                     int j;
12333                     for (j = 0; j < hasColon; j++)
12334 #if !defined(_WIN32)
12335                         strList[slashCharsToSwap[j]] = '/';
12336 #else
12337                         strList[slashCharsToSwap[j]] = '\\';
12338 #endif
12339                 }
12340                 s = 0;
12341                 hasColon = 0;
12342                 break;
12343             }
12344 #if !defined(_WIN32) /* linux case */
12345             case '\\':
12346 #else                /* windows case */
12347             case '/':
12348 #endif
12349             {
12350                 if (hasColon)
12351                     break;
12352                 slashCharsToSwap[s++] = i;
12353                 if (s == sizeof(slashCharsToSwap)/sizeof(slashCharsToSwap[0]))
12354                 {
12355                     free(strList);
12356                     free(strArray);
12357                     return db_perror("exceeded slashCharsToSwap size", E_INTERNAL, me);
12358                 }
12359                 break;
12360             }
12361             case ':':
12362             {
12363                 hasColon = s;
12364                 break;
12365             }
12366         }
12367         if (!completelyDone)
12368         {
12369             if (strList[i] != '\0')
12370                 i++;
12371             if (strList[i] == '\0')
12372                 nearlyDone = 1;
12373         }
12374     }
12375 
12376     if (n != nblocks)
12377     {
12378         free(strArray);
12379         return db_perror("incorrect number of block names", E_INTERNAL, me);
12380     }
12381 
12382     /* ensure we store the originally allocated pointer for later free's */
12383     *alloc_flag = strList;
12384 
12385     *retArray = strArray;
12386 
12387     return 0;
12388 }
12389 
12390 /*-------------------------------------------------------------------------
12391  * Function:    DBSortObjectsByOffset
12392  *
12393  * Purpose:     Determines the offset within the Silo file of each object
12394  *              in the list of objects passed in and returns an array
12395  *              and returns an integer array indicating their ordering.
12396  *
12397  * Return:      Success:        Non-zero.
12398  *              Failure:        zero.
12399  *
12400  * Programmer:  Mark C. Miller, Thu Jul 15 06:40:27 PDT 2010
12401  *-------------------------------------------------------------------------*/
12402 PUBLIC int
DBSortObjectsByOffset(DBfile * dbfile,int nobjs,const char * const * const names,int * ordering)12403 DBSortObjectsByOffset(DBfile *dbfile, int nobjs,
12404     const char *const *const names, int *ordering)
12405 {
12406     int retval;
12407 
12408     API_BEGIN2("DBSortObjectsByOffset", int, -1, api_dummy);
12409     {
12410         if (!dbfile)
12411             API_ERROR(NULL, E_NOFILE);
12412         if (nobjs <= 0)
12413             API_ERROR("nobjs", E_BADARGS);
12414         if (!names)
12415             API_ERROR("names", E_BADARGS);
12416         if (!ordering)
12417             API_ERROR("ordering", E_BADARGS);
12418         if (!dbfile->pub.sort_obo)
12419             API_ERROR(dbfile->pub.name, E_NOTIMP);
12420 
12421         retval = (dbfile->pub.sort_obo) (dbfile, nobjs, names, ordering);
12422 
12423         API_RETURN(retval);
12424     }
12425     API_END_NOPOP;  /* If API_RETURN above is removed, use API_END instead */
12426 }
12427 
12428 /*----------------------------------------------------------------------
12429  * Purpose
12430  *
12431  *    Break an extend driver id into type and subtype
12432  *
12433  * Programmer
12434  *
12435  *    Mark C. Miller, July 31, 2006
12436  *
12437  * Modifications:
12438  *  Mark C. Miller, Mon Aug 21 23:14:29 PDT 2006
12439  *  Made code that references DB_HDF5 conditionally compiled
12440  *
12441  *  Mark C. Miller, Thu Feb 11 09:51:28 PST 2010
12442  *  Changed logic for how subtype is handled.
12443  *
12444  *  Mark C. Miller, Thu Feb 25 19:00:09 PST 2010
12445  *  Versions of silo 4.7.2 and earlier used a bit of a brain dead way
12446  *  to specify alternative HDF5 vfds by manipulating the high order
12447  *  bits in the integer 'type' arg to DBCreate/DBOpen. For example, the
12448  *  default HDF5 driver was '7' while HDF5 w/STDIO vfd was '0x200'. This
12449  *  was inflexible and unable to handle the large variety of options
12450  *  available in HDF5.
12451  *
12452  *  Versions of silo newer than 4.7.2 use a global array of options
12453  *  sets registered and stored in the SILO_Globals structure. So,
12454  *  a particular set of HDF5 vfd options is identified by a single
12455  *  integer indexing into this global list of options. It is this integer
12456  *  index that is shifted left by 11 bits to make space for the primary
12457  *  Silo driver id (e.g. DB_PDB or DB_HDF5) and obsoleted HDF5 vfd
12458  *  specifications and then OR'd into the integer 'type' arg in the
12459  *  DBCreate/DBOpen calls to specify HDF5 vfd options.
12460  *
12461  *  In the initial implementation of this new approach using a global
12462  *  array of options sets, we allowed for a total of 32 (5 bits)
12463  *  options sets plus another 10 default options sets for convenience.
12464  *  But, we don't actually store the 10 default options set and use
12465  *  only the integer identifer between 0 and 9 to identify them.
12466  *  So, the identifier for a given options set ranges from 0...41
12467  *  requiring a total of 6 bits. Those 6 bits are 0x1F800.
12468  *--------------------------------------------------------------------*/
12469 INTERNAL void
db_DriverTypeAndFileOptionsSetId(int driver,int * type,int * _opts_set_id)12470 db_DriverTypeAndFileOptionsSetId(int driver, int *type, int *_opts_set_id)
12471 {
12472     int theType = driver&0xF;
12473     int opts_set_id = 0;
12474 
12475     if (driver > DB_NFORMATS)
12476     {
12477         opts_set_id = (driver&0x1F800)>>11;
12478 #ifdef DB_HDF5X
12479         if (theType == DB_HDF5X)
12480         {
12481             int obsolete_subType = driver&0x700;
12482             switch (obsolete_subType)
12483             {
12484                 case DB_HDF5_SEC2_OBSOLETE:
12485                     opts_set_id = DB_FILE_OPTS_H5_DEFAULT_SEC2;
12486                     break;
12487                 case DB_HDF5_STDIO_OBSOLETE:
12488                     opts_set_id = DB_FILE_OPTS_H5_DEFAULT_STDIO;
12489                     break;
12490                 case DB_HDF5_CORE_OBSOLETE:
12491                     opts_set_id = DB_FILE_OPTS_H5_DEFAULT_CORE;
12492                     break;
12493                 case DB_HDF5_MPIO_OBSOLETE:
12494                     opts_set_id = DB_FILE_OPTS_H5_DEFAULT_MPIO;
12495                     break;
12496                 case DB_HDF5_MPIOP_OBSOLETE:
12497                     opts_set_id = DB_FILE_OPTS_H5_DEFAULT_MPIP;
12498                     break;
12499                 default:
12500                     break;
12501             }
12502         }
12503 #endif
12504     }
12505 
12506     if (type) *type = theType;
12507     if (_opts_set_id) *_opts_set_id = opts_set_id;
12508 }
12509 
12510 /*
12511  *
12512  * The following data structures and functions for manipulating
12513  * character strings representing pathnames was originally written
12514  * by James F. Reus as part of the DSL Library. It was extracted from
12515  * DSL and adapted, slightly, for use in the Silo library by Mark C. Miller
12516  *
12517  * BEGIN CODE FROM JIM REUS' DSL {
12518  *
12519  */
12520 
db_absoluteOf_path(const char * cwg,const char * pathname)12521 char *db_absoluteOf_path (const char *cwg,
12522                           const char *pathname)
12523 {  char *result;
12524 
12525    if (pathname && strlen(pathname))
12526    {  if (db_isAbsolute_path(pathname))
12527           result = db_normalize_path(pathname);
12528       else if (cwg && strlen(cwg))
12529           result = db_join_path(cwg,pathname);
12530       else
12531           result = _db_safe_strdup("");
12532    }
12533    else
12534    {
12535       result = _db_safe_strdup("");
12536    }
12537    return result;
12538 }
12539 
12540 /*-------------------------------------------------------------------------- - -
12541 |
12542 |   Description: This function returns a string representing the basename part
12543 |                of the given pathname (stripping off the parent path).  Note
12544 |                that special cases arise...
12545 |
12546 |                    pathname == 0            Return value is 0.
12547 |                    pathname == "/"            Return value is "/".
12548 |                    pathname == "/base"        Return value is "base".
12549 |                    pathname == "base"         Return value is "base".
12550 |                    pathname == "path/base"    Return value is "base".
12551 |
12552 |   Return:      A pointer to a NULL-terminated string is returned when this
12553 |                function is successful.  Note that this string is constructed
12554 |                from allocated dynamic memory, it is up to the caller to
12555 |                release this string when it is no longer needed.  A 0
12556 |                pointer is returned on error.
12557 |
12558 +-----------------------------------------------------------------------------*/
12559 
db_basename(const char * pathname)12560 char *db_basename ( const char *pathname )
12561 {  char *result;
12562 
12563    result = 0;
12564    {  if (0 < strlen(pathname))
12565       {  if (strcmp(pathname,"/") == 0)
12566             result = STRDUP("/");
12567          else
12568          {  int i;
12569 
12570             for (i=(int)strlen(pathname)-1; 0<=i; --i)
12571                if (pathname[i] == '/')
12572                {  result = STRDUP(&(pathname[i+1]));
12573                   goto theExit;
12574                }
12575             result = STRDUP(pathname);
12576          }
12577       }
12578    }
12579 theExit:
12580    return result;
12581 }
12582 
12583 /*-------------------------------------------------------------------------- - -
12584 |
12585 |   Description: This function is used to release all storage associated
12586 |                with the given pathname component list.  Such a pathname
12587 |                component list is typically derived from a NULL-terminated
12588 |                string using the db_split_path() function.
12589 |
12590 |   Return:      A 0 pointer is always returned.
12591 |
12592 +-----------------------------------------------------------------------------*/
12593 
db_cleanup_path(db_Pathname * p)12594 db_Pathname *db_cleanup_path ( db_Pathname *p )
12595 {
12596    {  if (p != 0)
12597       {  while (p->firstComponent != 0)
12598          {  db_PathnameComponent *c;
12599 
12600             c                                  = p->firstComponent;
12601             p->firstComponent                  = c->nextComponent;
12602             if (c->nextComponent == 0)
12603                p->lastComponent                = 0;
12604             else
12605                c->nextComponent->prevComponent = 0;
12606             if (c->name != 0)
12607             {  free(c->name);
12608                c->name                         = 0;
12609             }
12610             c->prevComponent                   = 0;
12611             c->nextComponent                   = 0;
12612             free(c);
12613          }
12614          free(p);
12615          p = 0;
12616       }
12617    }
12618    return p;
12619 }
12620 
12621 /*-------------------------------------------------------------------------- - -
12622 |
12623 |   Description: This function returns a string representing the dirname part
12624 |                of the given pathname (stripping off the parent path).  Note
12625 |                that special cases arise...
12626 |
12627 |                    pathname == 0            Return value is 0.
12628 |                    pathname == "/"            Return value is "".
12629 |                    pathname == "/base"        Return value is "/".
12630 |                    pathname == "base"         Return value is ".".
12631 |                    pathname == "path/base"    Return value is "path".
12632 |
12633 |   Return:      A pointer to a NULL-terminated string is returned when this
12634 |                function is successful.  Note that this string is constructed
12635 |                from allocated dynamic memory, it is up to the caller to
12636 |                release this string when it is no longer needed.  A 0
12637 |                pointer is returned on error.
12638 |
12639 +-----------------------------------------------------------------------------*/
12640 
db_dirname(const char * pathname)12641 char *db_dirname ( const char *pathname )
12642 {  char *result;
12643 
12644    result = 0;
12645    {  if (0 < strlen(pathname))
12646       {  if (strcmp(pathname,"/") == 0)
12647             result = STRDUP("");
12648          else
12649          {  int  i;
12650             char tmp[32767];
12651 
12652             strcpy(tmp,pathname);
12653             for (i=(int)strlen(tmp)-1; 0<=i; --i)
12654                if (tmp[i] == '/')
12655                {  if (i == 0)
12656                      tmp[1] = '\0';
12657                   else
12658                      tmp[i] = '\0';
12659                   result = STRDUP(tmp);
12660                   goto theExit;
12661                }
12662             result = STRDUP(".");
12663          }
12664       }
12665    }
12666 theExit:
12667    return result;
12668 }
12669 
12670 /*-------------------------------------------------------------------------- - -
12671 |
12672 |   Description: This function is used to determine if the given pathname
12673 |                is an absolute pathname.  Note that this is really just a
12674 |                test for a leading '/'.
12675 |
12676 |   Return:      A value of TRUE is returned when the function is
12677 |                successful, otherwise a value of FALSE is returned.
12678 |
12679 +-----------------------------------------------------------------------------*/
12680 
db_isAbsolute_path(const char * pathname)12681 int db_isAbsolute_path ( const char *pathname )
12682 {  int result;
12683 
12684    result = FALSE;
12685    if (0 < strlen(pathname))
12686       if (pathname[0] == '/')
12687          result = TRUE;
12688    return result;
12689 }
12690 
12691 /*-------------------------------------------------------------------------- - -
12692 |
12693 |   Description: This function is used to determine if the given pathname is an
12694 |                relative pathname.  Note that this is really just a test for a
12695 |                leading '/'.
12696 |
12697 |   Return:      A value of TRUE is returned when the function is
12698 |                successful, otherwise a value of FALSE is returned.
12699 +-----------------------------------------------------------------------------*/
12700 
db_isRelative_path(const char * pathname)12701 int db_isRelative_path ( const char *pathname )
12702 {  int result;
12703 
12704    result = FALSE;
12705    if (0 < strlen(pathname))
12706       if (pathname[0] != '/')
12707          result = TRUE;
12708    return result;
12709 }
12710 
12711 /*-------------------------------------------------------------------------- - -
12712 |
12713 |   Description: This function joins the two given pathname components to form
12714 |                a new pathname.  The result is normalized to deal properly
12715 |                with absolute pathnames, `.' and `..' components.  For
12716 |                example: joining "abc/def" and "../xyz/123" would result
12717 |                in "abc/xyz/123".  Note that joining "abc/123" and "/xyz"
12718 |                will yield "/xyz" since the second part is an absolute
12719 |                path. Note that the first operand, a, is treated as the
12720 |                "root" for any '.' or '..' in operand b.
12721 |
12722 |   Return:      A pointer to a NULL-terminated string is returned when this
12723 |                function is successful.  Note that this string is constructed
12724 |                from allocated dynamic memory, it is up to the caller to
12725 |                release this string when it is no longer needed.  A 0
12726 |                pointer is returned on error.
12727 |
12728 |   Modifications:
12729 |
12730 |     Mark C. Miller, Wed Oct 18 08:41:33 PDT 2006
12731 |     Fixed bug where result was set at top of function but then uninitialized
12732 |     tmp was tested at end causing result to be set to zero
12733 +-----------------------------------------------------------------------------*/
12734 
db_join_path(const char * a,const char * b)12735 char *db_join_path ( const char *a,
12736                      const char *b )
12737 {  char       *result;
12738    char *tmp;
12739 
12740    if (strlen(b) == 0)
12741       return db_normalize_path(a);
12742    else if (strlen(a) == 0)
12743       return db_normalize_path(b);
12744    else if (db_isAbsolute_path(b))
12745       return db_normalize_path(b);
12746    else
12747    {  db_Pathname *Pa;
12748 
12749       tmp = 0;
12750       if ((Pa=db_split_path(a)) != 0)
12751       {  db_Pathname *Pb;
12752 
12753          if ((Pb=db_split_path(b)) != 0)
12754          {  db_Pathname *t;
12755 
12756             if ((t=(db_Pathname *)malloc(sizeof(db_Pathname))) != 0)
12757             {  db_PathnameComponent *c;
12758                int          ok;
12759 
12760                t->firstComponent = 0;
12761                t->lastComponent  = 0;
12762                ok                = TRUE;
12763                c                 = Pa->firstComponent;
12764                while (c != 0)
12765                {  db_PathnameComponent *k;
12766 
12767                   if ((k=(db_PathnameComponent *)malloc(sizeof(db_PathnameComponent))) != 0)
12768                   {  if (c->name != 0)
12769                         k->name                         = STRDUP(c->name);
12770                      else
12771                         k->name                         = 0;
12772                      k->prevComponent                   = t->lastComponent;
12773                      k->nextComponent                   = 0;
12774                      if (t->lastComponent == 0)
12775                         t->firstComponent               = k;
12776                      else
12777                         t->lastComponent->nextComponent = k;
12778                      t->lastComponent                   = k;
12779                   }
12780                   else
12781                   {  ok = FALSE;
12782                      break;
12783                   }
12784                   c = c->nextComponent;
12785                }
12786                if (ok)
12787                {  c = Pb->firstComponent;
12788                   while (c != 0)
12789                   {  db_PathnameComponent *k;
12790 
12791                      if ((k=(db_PathnameComponent *)malloc(sizeof(db_PathnameComponent))) != 0)
12792                      {  if (c->name != 0)
12793                            k->name                         = STRDUP(c->name);
12794                         else
12795                            k->name                         = 0;
12796                         k->prevComponent                   = t->lastComponent;
12797                         k->nextComponent                   = 0;
12798                         if (t->lastComponent == 0)
12799                            t->firstComponent               = k;
12800                         else
12801                            t->lastComponent->nextComponent = k;
12802                         t->lastComponent                   = k;
12803                      }
12804                      else
12805                      {  ok = FALSE;
12806                         break;
12807                      }
12808                      c = c->nextComponent;
12809                   }
12810                   if (ok)
12811                      tmp = db_unsplit_path(t);
12812                }
12813                db_cleanup_path(t);
12814             }
12815             db_cleanup_path(Pb);
12816          }
12817          db_cleanup_path(Pa);
12818       }
12819    }
12820    if (tmp != 0)
12821    {
12822       result = db_normalize_path(tmp);
12823       free(tmp);
12824    }
12825    else
12826       result = 0;
12827    return result;
12828 }
12829 
12830 /*-------------------------------------------------------------------------- - -
12831 |
12832 |   Description: This function is used to normalize the given pathname, dealing
12833 |                with dots, double-dots and such.
12834 |
12835 |                This function resolves:
12836 |
12837 |                    - double slashes (such as abc//123)
12838 |                    - trailing slashes (such as abc/)
12839 |                    - embedded single dots (such as abc/./123) except for
12840 |                      some leading dots.
12841 |                    - name-double dot sets (such as abc/../123)
12842 |
12843 |   Return:      A pointer to a NULL-terminated string is returned when this
12844 |                function is successful.  Note that this string is constructed
12845 |                from allocated dynamic memory, it is up to the caller to
12846 |                release this string when it is no longer needed.  A 0
12847 |                pointer is returned on error.
12848 |
12849 +-----------------------------------------------------------------------------*/
12850 
db_normalize_path(const char * pathname)12851 char *db_normalize_path ( const char *pathname )
12852 {  char *result;
12853 
12854    result = 0;
12855    if (0 < strlen(pathname))
12856    {  db_Pathname *p;
12857 
12858         /*--------------------------------------
12859         |
12860         |   Break into separate components...
12861         |
12862         +-------------------------------------*/
12863 
12864       if ((p=(db_split_path(pathname))) != 0)
12865       {  db_PathnameComponent *c;
12866 
12867         /*--------------------------------------
12868         |
12869         |   Eliminate . components
12870         |
12871         +-------------------------------------*/
12872 
12873          c = p->firstComponent;
12874          while (c != 0)
12875          {  if (c != p->firstComponent)
12876             {  if (c->name && (strcmp(c->name,".") == 0))
12877                {  db_PathnameComponent *cc;
12878 
12879                   cc                                 = c->nextComponent;
12880                   if (c->prevComponent == 0)
12881                      p->firstComponent               = c->nextComponent;
12882                   else
12883                      c->prevComponent->nextComponent = c->nextComponent;
12884                   if (c->nextComponent == 0)
12885                      p->lastComponent                = c->prevComponent;
12886                   else
12887                      c->nextComponent->prevComponent = c->prevComponent;
12888                   free(c->name);
12889                   c->name                            = 0;
12890                   c->prevComponent                   = 0;
12891                   c->nextComponent                   = 0;
12892                   free(c);
12893                   c                                  = cc;
12894                }
12895                else
12896                   c = c->nextComponent;
12897             }
12898             else
12899                c = c->nextComponent;
12900          }
12901 
12902         /*--------------------------------------
12903         |
12904         |   Eliminate .. components, note
12905         |   that this process is a little
12906         |   tougher then the . case, this
12907         |   is due to things like ../../a/b
12908         |
12909         +-------------------------------------*/
12910 
12911 tryAgain:c = p->firstComponent;
12912          while (c != 0)
12913          {  if (c->name && (strcmp(c->name,"..") == 0))
12914             {  db_PathnameComponent *k;
12915 
12916                if ((k=c->prevComponent) != 0)
12917                {  if (k->name != 0 && strcmp(k->name,"..") != 0)
12918                   {
12919                      if (k->prevComponent == 0)
12920                         p->firstComponent                   = k->nextComponent;
12921                      else
12922                         k->prevComponent->nextComponent     = k->nextComponent;
12923                      if (k->nextComponent == 0)
12924                         p->lastComponent                    = k->prevComponent;
12925                      else
12926                         k->nextComponent->prevComponent     = k->prevComponent;
12927                      if (k->name != 0)
12928                         free(k->name);
12929                      k->name                                = 0;
12930                      k->prevComponent                       = 0;
12931                      k->nextComponent                       = 0;
12932                      free(k);
12933                      k                                      = 0;
12934                      if (c->prevComponent == 0)
12935                         p->firstComponent                   = c->nextComponent;
12936                      else
12937                         c->prevComponent->nextComponent     = c->nextComponent;
12938                      if (c->nextComponent == 0)
12939                         p->lastComponent                    = c->prevComponent;
12940                      else
12941                         c->nextComponent->prevComponent     = c->prevComponent;
12942                      if (c->name != 0)
12943                         free(c->name);
12944                      c->name                                = 0;
12945                      c->prevComponent                       = 0;
12946                      c->nextComponent                       = 0;
12947                      free(c);
12948                      c                                      = 0;
12949                      goto tryAgain;
12950                   }
12951                }
12952             }
12953             c = c->nextComponent;
12954          }
12955 
12956         /*--------------------------------------
12957         |
12958         |   Rejoin components into a string...
12959         |
12960         +-------------------------------------*/
12961 
12962          result = db_unsplit_path(p);
12963          db_cleanup_path(p);
12964       }
12965    }
12966    return result;
12967 }
12968 
makePathname(void)12969 static db_Pathname *makePathname ( void )
12970 {  db_Pathname *p;
12971 
12972    if ((p=(db_Pathname *)malloc(sizeof(db_Pathname))) != 0)
12973    {  p->firstComponent = 0;
12974       p->lastComponent  = 0;
12975    }
12976    return p;
12977 }
12978 
appendComponent(db_Pathname * p,char * s)12979 static db_Pathname *appendComponent ( db_Pathname *p, char *s )
12980 {  if (p == 0)
12981       p = makePathname();
12982    if (p != 0)
12983    {  db_PathnameComponent *c;
12984 
12985       if ((c=(db_PathnameComponent *)malloc(sizeof(db_PathnameComponent))) != 0)
12986       {  c->name                            = STRDUP(s);
12987          c->prevComponent                   = p->lastComponent;
12988          c->nextComponent                   = 0;
12989          if (p->lastComponent == 0)
12990             p->firstComponent               = c;
12991          else
12992             p->lastComponent->nextComponent = c;
12993          p->lastComponent                   = c;
12994       }
12995    }
12996    return p;
12997 }
12998 
12999 /*-------------------------------------------------------------------------- - -
13000 |
13001 |   Description: This function splits a given pathname into its components.
13002 |                The split is generally made at the embedded slashes (/),
13003 |                forming a linked list of pathname components.  For example
13004 |                the pathname "abc/def/123/xyz" has four components: "abc",
13005 |                "def", "123", and "xyz".  Note that the list of components
13006 |                returned by this function is formed using allocated dynamic
13007 |                memory and should be released using the db_cleanup_path()
13008 |                function when it is no longer needed.  This function is
13009 |                intended for internal use only.
13010 |
13011 |   Return:      A pointer to the first component of a list of pathname
13012 |                components is returned when this function succeeds, otherwise
13013 |                a 0 pointer is returned.
13014 |
13015 +-----------------------------------------------------------------------------*/
13016 
db_split_path(const char * pathname)13017 db_Pathname *db_split_path ( const char *pathname )
13018 {  db_Pathname *result;
13019 
13020    result = 0;
13021    if (0 < strlen(pathname))
13022    {  if ((result=makePathname()) != 0)
13023       {  int  L;
13024          int  state;
13025          char tmp[32767];
13026 
13027          L      = 0;
13028          tmp[L] = '\0';
13029          state  = 0;
13030          for (;;)
13031          {  char c;
13032 
13033             c = *pathname;
13034             switch (state)
13035             { case 0: switch (c)
13036                       { case '\0': goto done;
13037                         case '/':  result        = appendComponent(result,0);
13038                                    state         = 1;
13039                                    break;
13040                         default:   L             = 0;
13041                                    tmp[L]        = c;
13042                                    L            += 1;
13043                                    tmp[L]        = '\0';
13044                                    state         = 2;
13045                                    break;
13046                       }
13047                       break;
13048               case 1: switch (c)
13049                       { case '\0': goto done;
13050                         case '/':  state         = 1;
13051                                    break;
13052                         default:   L             = 0;
13053                                    tmp[L]        = c;
13054                                    L            += 1;
13055                                    tmp[L]        = '\0';
13056                                    state         = 2;
13057                                    break;
13058                       }
13059                       break;
13060               case 2: switch (c)
13061                       { case '\0': result        = appendComponent(result,tmp);
13062                                    goto done;
13063                         case '/':  result        = appendComponent(result,tmp);
13064                                    state         = 1;
13065                                    break;
13066                         default:   tmp[L]        = c;
13067                                    L            += 1;
13068                                    tmp[L]        = '\0';
13069                                    state         = 2;
13070                                    break;
13071                       }
13072                       break;
13073             }
13074             pathname += 1;
13075          }
13076 done:    ;
13077       }
13078    }
13079    return result;
13080 }
13081 
13082 /*------------------------------------------------------------------------------
13083 |
13084 |   Description: This function forms a pathname string from a linked set of
13085 |                pathname components.  Note that this function is intended for
13086 |                internal use only.
13087 |
13088 |   Modifications:
13089 |     Mark C. Miller, Wed Jul 11 17:01:09 PDT 2012
13090 |     Initialize tmp buffer to the empty string with tmp[0] = '\0'
13091 +-----------------------------------------------------------------------------*/
13092 
db_unsplit_path(const db_Pathname * p)13093 char *db_unsplit_path ( const db_Pathname *p )
13094 {  char *result;
13095 
13096    result = 0;
13097    if (p != 0)
13098    {  db_PathnameComponent *c;
13099       int          first;
13100       int          slashed;
13101       static char  tmp[4096];
13102 
13103       tmp[0] = '\0';
13104       first   = TRUE;
13105       slashed = FALSE;
13106       c       = p->firstComponent;
13107       while (c != 0)
13108       {
13109          if ((c->name == 0) || (strlen(c->name) == 0))
13110          {  strcpy(tmp,"/");
13111             slashed = TRUE;
13112          }
13113          else
13114          {  if ((!slashed) && (!first))
13115             {  strcat(tmp,"/");
13116                slashed = TRUE;
13117             }
13118             strcat(tmp,c->name);
13119             slashed = FALSE;
13120          }
13121          first = FALSE;
13122          c     = c->nextComponent;
13123       }
13124       result = STRDUP(tmp);
13125    }
13126    return result;
13127 }
13128 
13129 /*
13130  * END CODE FROM JIM REUS' DSL }
13131  */
13132 
13133 static void
DBFreeMrgnode(DBmrgtnode * tnode,int walk_order,void * data)13134 DBFreeMrgnode(DBmrgtnode *tnode, int walk_order, void *data)
13135 {
13136     if (tnode == 0)
13137         return;
13138     FREE(tnode->name);
13139     if (tnode->narray > 0)
13140     {
13141         if (strchr(tnode->names[0], '%') == 0)
13142         {
13143             int i;
13144             for (i = 0; i < tnode->narray; i++)
13145                 FREE(tnode->names[i]);
13146             FREE(tnode->names);
13147         }
13148         else
13149         {
13150             FREE(tnode->names[0]);
13151             FREE(tnode->names);
13152         }
13153     }
13154     FREE(tnode->maps_name);
13155     FREE(tnode->seg_ids);
13156     FREE(tnode->seg_lens);
13157     FREE(tnode->seg_types);
13158     FREE(tnode->children);
13159     FREE(tnode);
13160 }
13161 
DBFreeMrgtree(DBmrgtree * tree)13162 void DBFreeMrgtree(DBmrgtree *tree)
13163 {
13164     if (tree == 0)
13165         return;
13166     DBWalkMrgtree(tree, (DBmrgwalkcb) DBFreeMrgnode, 0, DB_POSTORDER);
13167     FREE(tree->name);
13168     FREE(tree->src_mesh_name);
13169     if (tree->mrgvar_onames)
13170     {
13171         int i = 0;
13172         while (tree->mrgvar_onames[i] != 0)
13173         {
13174             FREE(tree->mrgvar_onames[i]);
13175             i++;
13176         }
13177         FREE(tree->mrgvar_onames);
13178     }
13179     if (tree->mrgvar_rnames)
13180     {
13181         int i = 0;
13182         while (tree->mrgvar_rnames[i] != 0)
13183         {
13184             FREE(tree->mrgvar_rnames[i]);
13185             i++;
13186         }
13187         FREE(tree->mrgvar_rnames);
13188     }
13189     FREE(tree);
13190 }
13191 
DBPrintMrgtree(DBmrgtnode * tnode,int walk_order,void * data)13192 void DBPrintMrgtree(DBmrgtnode *tnode, int walk_order, void *data)
13193 {
13194     FILE *f = (FILE *) data;
13195     int level = -1;
13196     DBmrgtnode *tmp = tnode;
13197 
13198     /* walk to top to determine level of indentation */
13199     while (tmp != 0)
13200     {
13201         tmp = tmp->parent;
13202         level++;
13203     }
13204     level *= 3;
13205 
13206     if (f == 0)
13207         f = stdout;
13208 
13209     /* print this node using special '*' field width specifier */
13210     fprintf(f, "%*s name = \"%s\" {\n", level, "", tnode->name);
13211     fprintf(f, "%*s     walk_order = %d\n", level, "", tnode->walk_order);
13212     fprintf(f, "%*s         parent = \"%s\"\n", level, "", tnode->parent?tnode->parent->name:"");
13213     fprintf(f, "%*s         narray = %d\n", level, "", tnode->narray);
13214     if (tnode->narray > 0)
13215     {
13216         if (strchr(tnode->names[0], '%') == 0)
13217         {
13218             int j;
13219             fprintf(f, "%*s          names = ...\n", level, "");
13220             for (j = 0; j < tnode->narray; j++)
13221                 fprintf(f, "%*s                  \"%s\"\n", level, "", tnode->names[j]);
13222         }
13223         else
13224         {
13225             fprintf(f, "%*s          names = \"%s\"\n", level, "", tnode->names[0]);
13226         }
13227     }
13228     fprintf(f, "%*s type_info_bits = %d\n", level, "", tnode->type_info_bits);
13229     fprintf(f, "%*s   max_children = %d\n", level, "", tnode->max_children);
13230     fprintf(f, "%*s      maps_name = \"%s\"\n", level, "", tnode->maps_name?tnode->maps_name:"");
13231     fprintf(f, "%*s          nsegs = %d\n", level, "", tnode->nsegs);
13232     if (tnode->nsegs > 0)
13233     {
13234         int j;
13235         fprintf(f, "%*s       segments =     ids   |   lens   |   types\n", level, "");
13236         for (j = 0; j < tnode->nsegs*(tnode->narray?tnode->narray:1); j++)
13237             fprintf(f, "%*s                  %.10d|%.10d|%.10d\n", level, "",
13238                 tnode->seg_ids[j], tnode->seg_lens[j], tnode->seg_types[j]);
13239 
13240     }
13241     fprintf(f, "%*s   num_children = %d\n", level, "", tnode->num_children);
13242     if (tnode->num_children > 0)
13243     {
13244         int j;
13245         for (j = 0; j < tnode->num_children && tnode->children[j] != 0; j++)
13246             fprintf(f, "%*s              \"%s\"\n", level, "", tnode->children[j]->name);
13247     }
13248     fprintf(f, "%*s} \"%s\"\n", level, "", tnode->name);
13249 }
13250 
13251 void
DBLinearizeMrgtree(DBmrgtnode * tnode,int walk_order,void * data)13252 DBLinearizeMrgtree(DBmrgtnode *tnode, int walk_order, void *data)
13253 {
13254     DBmrgtnode **ltree = (DBmrgtnode **) data;
13255     ltree[walk_order] = tnode;
13256     tnode->walk_order = walk_order;
13257 }
13258 
13259 static void
DBWalkMrgtree_r(DBmrgtnode const * node,int * walk_order,DBmrgwalkcb wcb,void * wdata,int traversal_flags)13260 DBWalkMrgtree_r(DBmrgtnode const *node, int *walk_order, DBmrgwalkcb wcb, void *wdata,
13261     int traversal_flags)
13262 {
13263     if (node == 0)
13264         return;
13265 
13266     /* if we're at a terminal node, issue the callback */
13267     if (node->children == 0)
13268     {
13269        wcb(node, *walk_order, wdata);
13270        (*walk_order)++;
13271     }
13272     else
13273     {
13274         int i;
13275 
13276         /* issue callback first if in pre-order mode */
13277         if (traversal_flags & DB_PREORDER)
13278         {
13279             wcb(node, *walk_order, wdata);
13280             (*walk_order)++;
13281         }
13282 
13283         /* recurse on all the children */
13284         for (i = 0; i < node->num_children && node->children[i] != 0; i++)
13285             DBWalkMrgtree_r(node->children[i], walk_order, wcb, wdata,
13286                 traversal_flags);
13287 
13288         /* issue callback last if in post-order mode */
13289         if (traversal_flags & DB_POSTORDER)
13290         {
13291             wcb(node, *walk_order, wdata);
13292             (*walk_order)++;
13293         }
13294     }
13295 }
13296 
13297 void
DBWalkMrgtree(DBmrgtree const * tree,DBmrgwalkcb cb,void * wdata,int traversal_flags)13298 DBWalkMrgtree(DBmrgtree const *tree, DBmrgwalkcb cb, void *wdata, int traversal_flags)
13299 {
13300     int walk_order = 0;
13301     DBmrgtnode *start = tree->root;
13302 
13303     if (cb == 0)
13304         return;
13305 
13306     if (traversal_flags & DB_FROMCWR)
13307         start = tree->cwr;
13308 
13309     DBWalkMrgtree_r(start, &walk_order, cb, wdata, traversal_flags);
13310 }
13311 
13312 PUBLIC DBmrgtree *
DBMakeMrgtree(int source_mesh_type,int type_info_bits,int max_root_descendents,DBoptlist * opts)13313 DBMakeMrgtree(int source_mesh_type, int type_info_bits,
13314     int max_root_descendents, DBoptlist *opts)
13315 {
13316     DBmrgtree *tree = NULL;
13317     DBmrgtnode *root = NULL;
13318 
13319     API_BEGIN("DBMakeMrgtree", DBmrgtree *, NULL) {
13320         if (!(source_mesh_type == DB_MULTIMESH ||
13321               source_mesh_type == DB_QUADMESH ||
13322               source_mesh_type == DB_UCDMESH ||
13323               source_mesh_type == DB_POINTMESH ||
13324               source_mesh_type == DB_CSGMESH ||
13325               source_mesh_type == DB_CURVE))
13326             API_ERROR("source_mesh_type", E_BADARGS);
13327         if (type_info_bits != 0)
13328             API_ERROR("type_info_bits", E_BADARGS);
13329         if (max_root_descendents <= 0)
13330             API_ERROR("max_root_descendents", E_BADARGS);
13331         tree = ALLOC(DBmrgtree);
13332         if (!tree) API_ERROR(NULL, E_NOMEM);
13333         memset(tree, 0, sizeof(DBmrgtree));
13334         root = ALLOC(DBmrgtnode);
13335         if (!root) {
13336             FREE(tree);
13337             API_ERROR(NULL, E_NOMEM);
13338         }
13339         memset(root, 0, sizeof(DBmrgtnode));
13340         root->children = ALLOC_N(DBmrgtnode*, max_root_descendents);
13341         if (!root->children) {
13342             FREE(root);
13343             FREE(tree);
13344             API_ERROR(NULL, E_NOMEM);
13345         }
13346 
13347         /* fill in the tree header */
13348         tree->type_info_bits = type_info_bits;
13349         tree->src_mesh_type = source_mesh_type;
13350         tree->src_mesh_name = 0;
13351         tree->name = 0;
13352 
13353         /* update internal node info */
13354         root->walk_order = -1;
13355         root->parent = 0;
13356 
13357         /* update client data data */
13358         root->name = STRDUP("whole");
13359         root->narray = 0;
13360         root->names = 0;
13361         root->type_info_bits = 0;
13362         root->num_children = 0;
13363         root->max_children = max_root_descendents;
13364         root->maps_name = 0;
13365         root->nsegs = 0;
13366         root->seg_ids = 0;
13367         root->seg_lens = 0;
13368         root->seg_types = 0;
13369 
13370         /* add the new tnode to the tree */
13371         tree->root = root;
13372         tree->cwr = root;
13373         tree->num_nodes = 1;
13374 
13375         API_RETURN(tree);
13376     }
13377     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
13378 }
13379 
13380 PUBLIC int
DBAddRegion(DBmrgtree * tree,const char * region_name,int type_info_bits,int max_descendents,const char * maps_name,int nsegs,int const * seg_ids,int const * seg_lens,int const * seg_types,DBoptlist const * opts)13381 DBAddRegion(DBmrgtree *tree, const char *region_name,
13382     int type_info_bits, int max_descendents,
13383     const char *maps_name, int nsegs, int const *seg_ids,
13384     int const *seg_lens, int const *seg_types, DBoptlist const *opts)
13385 {
13386     DBmrgtnode *tnode = NULL;
13387 
13388     API_BEGIN("DBAddRegion", int, -1) {
13389 
13390         if (!tree)
13391             API_ERROR("tree pointer", E_BADARGS);
13392         if (!region_name || !*region_name)
13393             API_ERROR("region_name", E_BADARGS);
13394         if (type_info_bits != 0)
13395             API_ERROR("type_info_bits", E_BADARGS);
13396         if (max_descendents < 0)
13397             API_ERROR("max_descendents", E_BADARGS);
13398         if (tree->cwr->num_children >= tree->cwr->max_children) {
13399             API_ERROR("exceeded max_descendents", E_BADARGS);
13400         }
13401         if (nsegs > 0)
13402         {
13403             if (seg_ids == 0)
13404                 API_ERROR("seg_ids", E_BADARGS);
13405             if (seg_lens == 0)
13406                 API_ERROR("seg_lens", E_BADARGS);
13407             if (seg_types == 0)
13408                 API_ERROR("seg_types", E_BADARGS);
13409         }
13410         if (NULL == (tnode = ALLOC(DBmrgtnode)))
13411             API_ERROR(NULL, E_NOMEM);
13412         memset(tnode, 0, sizeof(DBmrgtnode));
13413         if (NULL == (tnode->children = ALLOC_N(DBmrgtnode*, max_descendents)) &&
13414             max_descendents) {
13415             FREE(tnode);
13416             API_ERROR(NULL, E_NOMEM);
13417         }
13418 
13419         /* update internal node info */
13420         tnode->walk_order = -1;
13421         tnode->parent = tree->cwr;
13422 
13423         /* update client data data */
13424         tnode->name = STRDUP(region_name);
13425         tnode->narray = 0;
13426         tnode->names = 0;
13427         tnode->type_info_bits = type_info_bits;
13428         tnode->num_children = 0;
13429         tnode->max_children = max_descendents;
13430         tnode->maps_name = STRDUP(maps_name);
13431         tnode->nsegs = nsegs;
13432         if (nsegs > 0)
13433         {
13434             int i;
13435 
13436             tnode->seg_ids = ALLOC_N(int, nsegs);
13437             tnode->seg_lens = ALLOC_N(int, nsegs);
13438             tnode->seg_types = ALLOC_N(int, nsegs);
13439 
13440             if (!tnode->seg_ids || !tnode->seg_lens || !tnode->seg_types)
13441             {
13442                 FREE(tnode->seg_types);
13443                 FREE(tnode->seg_lens);
13444                 FREE(tnode->seg_ids);
13445                 FREE(tnode->maps_name);
13446                 FREE(tnode->name);
13447                 FREE(tnode->children);
13448                 FREE(tnode);
13449                 API_ERROR(NULL, E_NOMEM);
13450             }
13451 
13452             for (i = 0; i < nsegs; i++)
13453             {
13454                 tnode->seg_ids[i] = seg_ids[i];
13455                 tnode->seg_lens[i] = seg_lens[i];
13456                 tnode->seg_types[i] = seg_types[i];
13457             }
13458         }
13459         else
13460         {
13461             tnode->seg_ids = 0;
13462             tnode->seg_lens = 0;
13463             tnode->seg_types = 0;
13464         }
13465 
13466 
13467         /* add the new tnode to the tree */
13468         tree->cwr->children[tree->cwr->num_children] = tnode;
13469         tree->cwr->num_children++;
13470         tree->num_nodes++;
13471 
13472     }
13473     API_END;
13474 
13475     return(tree->cwr->num_children-1);
13476 }
13477 
13478 PUBLIC int
DBAddRegionArray(DBmrgtree * tree,int nregns,char const * const * regn_names,int type_info_bits,char const * maps_name,int nsegs,int const * seg_ids,int const * seg_lens,int const * seg_types,DBoptlist const * opts)13479 DBAddRegionArray(DBmrgtree *tree, int nregns,
13480     char const * const *regn_names, int type_info_bits,
13481     char const *maps_name, int nsegs, int const *seg_ids,
13482     int const *seg_lens, int const *seg_types, DBoptlist const *opts)
13483 {
13484     DBmrgtnode *tnode = NULL;
13485     int i;
13486 
13487     API_BEGIN("DBAddRegionArray", int, -1) {
13488 
13489         if (!tree)
13490             API_ERROR("tree pointer", E_BADARGS);
13491         if (nregns <= 0)
13492             API_ERROR("nregns", E_BADARGS);
13493         if (tree->cwr->num_children + nregns > tree->cwr->max_children) {
13494             API_ERROR("exceeded max_descendents", E_BADARGS);
13495         }
13496         if (NULL == (tnode = ALLOC(DBmrgtnode)))
13497             API_ERROR(NULL, E_NOMEM);
13498         memset(tnode, 0, sizeof(DBmrgtnode));
13499         if (nsegs > 0)
13500         {
13501             if (seg_ids == 0)
13502                 API_ERROR("seg_ids", E_BADARGS);
13503             if (seg_lens == 0)
13504                 API_ERROR("seg_lens", E_BADARGS);
13505             if (seg_types == 0)
13506                 API_ERROR("seg_types", E_BADARGS);
13507         }
13508 
13509         /* update internal node info */
13510         tnode->walk_order = -1;
13511         tnode->parent = tree->cwr;
13512 
13513         /* update client data data */
13514         tnode->name = 0;
13515         tnode->narray = nregns;
13516         if (strchr(regn_names[0], '%') != 0)
13517         {
13518             if (NULL == (tnode->names = ALLOC_N(char*, 1))) {
13519                 FREE(tnode);
13520                 API_ERROR(NULL, E_NOMEM);
13521             }
13522             tnode->names[0] = STRDUP(regn_names[0]);
13523         }
13524         else
13525         {
13526             if (NULL == (tnode->names = ALLOC_N(char*, nregns))) {
13527                 FREE(tnode);
13528                 API_ERROR(NULL, E_NOMEM);
13529             }
13530             for (i = 0; i < nregns; i++)
13531                 tnode->names[i] = STRDUP(regn_names[i]);
13532         }
13533         tnode->type_info_bits = type_info_bits;
13534         tnode->num_children = 0;
13535         tnode->max_children = 0;
13536         tnode->children = 0;
13537         tnode->maps_name = STRDUP(maps_name);
13538         tnode->nsegs = nsegs;
13539         if (nsegs > 0)
13540         {
13541             tnode->seg_ids = ALLOC_N(int, nsegs*nregns);
13542             tnode->seg_lens = ALLOC_N(int, nsegs*nregns);
13543             tnode->seg_types = ALLOC_N(int, nsegs*nregns);
13544 
13545             if (!tnode->seg_ids || !tnode->seg_lens || !tnode->seg_types) {
13546                 FREE(tnode->seg_types);
13547                 FREE(tnode->seg_lens);
13548                 FREE(tnode->seg_ids);
13549                 if (strchr(regn_names[0], '%') != 0) {
13550                     FREE(tnode->names[0]);
13551                     FREE(tnode->names);
13552                 } else {
13553                     for (i = 0; i < nregns; i++)
13554                         FREE(tnode->names[i]);
13555                     FREE(tnode->names);
13556                 }
13557                 FREE(tnode);
13558                 API_ERROR(NULL, E_NOMEM);
13559             }
13560 
13561             for (i = 0; i < nsegs*nregns; i++)
13562             {
13563                 tnode->seg_ids[i] = seg_ids[i];
13564                 tnode->seg_lens[i] = seg_lens[i];
13565                 tnode->seg_types[i] = seg_types[i];
13566             }
13567         }
13568         else
13569         {
13570             tnode->seg_ids = 0;
13571             tnode->seg_lens = 0;
13572             tnode->seg_types = 0;
13573         }
13574 
13575         /* add the new tnode to the tree */
13576         tree->cwr->children[tree->cwr->num_children] = tnode;
13577         tree->cwr->num_children++;
13578         tree->num_nodes++;
13579 
13580     }
13581     API_END;
13582 
13583     return(tree->cwr->num_children-1);
13584 }
13585 
13586 PUBLIC int
DBSetCwr(DBmrgtree * tree,char const * path)13587 DBSetCwr(DBmrgtree *tree, char const *path)
13588 {
13589     int retval = -1;
13590 
13591     API_BEGIN("DBSetCwr", int, -1)
13592     {
13593         if (tree == 0)
13594             API_ERROR("tree", E_BADARGS);
13595         if (!path || !*path)
13596             API_ERROR("path", E_BADARGS);
13597         if (path[0] == '.' && path[1] == '.')
13598         {
13599             DBmrgtnode *tnode = tree->cwr;
13600             if (tnode != tree->root)
13601             {
13602                 tree->cwr = tnode->parent;
13603                 retval = 1;
13604             }
13605         }
13606         else
13607         {
13608             DBmrgtnode *tnode = tree->cwr;
13609             int i = 0;
13610             while (i < tnode->num_children)
13611             {
13612                 if (strcmp(tnode->children[i]->name, path) == 0)
13613                 {
13614                     tree->cwr = tnode->children[i];
13615                     break;
13616                 }
13617                 i++;
13618             }
13619             if (i < tnode->num_children)
13620                 retval = i;
13621         }
13622         API_RETURN(retval);
13623     }
13624     API_END_NOPOP;  /* BEWARE: If API_RETURN above is removed use API_END */
13625 }
13626 
13627 PUBLIC char const *
DBGetCwr(DBmrgtree * tree)13628 DBGetCwr(DBmrgtree *tree)
13629 {
13630     const char *retval = NULL;
13631 
13632     API_BEGIN("DBGetCwr", const char *, NULL)
13633     {
13634         if (tree == 0)
13635             API_ERROR("tree", E_BADARGS);
13636 
13637         retval = tree->cwr->name;
13638         API_RETURN(retval);
13639     }
13640     API_END_NOPOP;  /* BEWARE: If API_RETURN above is removed use API_END */
13641 }
13642 
13643 PUBLIC int
DBPutMrgtree(DBfile * dbfile,char const * name,char const * mesh_name,DBmrgtree const * tree,DBoptlist const * opts)13644 DBPutMrgtree(DBfile *dbfile, char const *name, char const *mesh_name,
13645     DBmrgtree const *tree, DBoptlist const *opts)
13646 {
13647     int retval;
13648 
13649     API_BEGIN2("DBPutMrgtree", int, -1, name)
13650     {
13651         if (!dbfile)
13652             API_ERROR(NULL, E_NOFILE);
13653         if (SILO_Globals.enableGrabDriver == TRUE)
13654             API_ERROR("DBPutMrgtree", E_GRABBED) ;
13655         if (!name || !*name)
13656             API_ERROR("mrgtree name", E_BADARGS);
13657         if (db_VariableNameValid(name) == 0)
13658             API_ERROR("mrgtree name", E_INVALIDNAME);
13659         if (!mesh_name || !*mesh_name)
13660             API_ERROR("mesh_name", E_BADARGS);
13661         if (db_VariableNameValid(mesh_name) == 0)
13662             API_ERROR("mesh_name", E_INVALIDNAME);
13663         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
13664             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
13665         if (NULL == dbfile->pub.p_mrgt)
13666             API_ERROR(dbfile->pub.name, E_NOTIMP);
13667 
13668         retval = (dbfile->pub.p_mrgt) (dbfile, name, mesh_name,
13669                                        tree, opts);
13670 
13671         db_FreeToc(dbfile);
13672         API_RETURN(retval);
13673     }
13674     API_END_NOPOP; /* BEWARE: If API_RETURN above is removed use API_END */
13675 }
13676 
13677 PUBLIC DBmrgtree *
DBGetMrgtree(DBfile * dbfile,const char * name)13678 DBGetMrgtree(DBfile *dbfile, const char *name)
13679 {
13680     DBmrgtree *retval = NULL;
13681 
13682     API_BEGIN2("DBGetMrgtree", DBmrgtree *, NULL, name) {
13683         if (!dbfile)
13684             API_ERROR(NULL, E_NOFILE);
13685         if (SILO_Globals.enableGrabDriver == TRUE)
13686             API_ERROR("DBGetMrgtree", E_GRABBED) ;
13687         if (!name || !*name)
13688             API_ERROR("mrgtree name", E_BADARGS);
13689         if (!dbfile->pub.g_mrgt)
13690             API_ERROR(dbfile->pub.name, E_NOTIMP);
13691 
13692         retval = (dbfile->pub.g_mrgt) (dbfile, name);
13693         API_RETURN(retval);
13694     }
13695     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
13696 }
13697 
13698 PUBLIC int
DBPutGroupelmap(DBfile * dbfile,const char * name,int num_segments,int const * groupel_types,int const * segment_lengths,int const * segment_ids,int const * const * segment_data,DBVCP2_t segment_fracs,int fracs_data_type,DBoptlist const * opts)13699 DBPutGroupelmap(DBfile *dbfile, const char *name,
13700     int num_segments, int const *groupel_types, int const *segment_lengths,
13701     int const *segment_ids, int const * const *segment_data, DBVCP2_t segment_fracs,
13702     int fracs_data_type, DBoptlist const *opts)
13703 {
13704     int retval;
13705 
13706     API_BEGIN2("DBGroupelmap", int, -1, name) {
13707         if (!dbfile)
13708             API_ERROR(NULL, E_NOFILE);
13709         if (SILO_Globals.enableGrabDriver == TRUE)
13710             API_ERROR("DBPutGroupelmap", E_GRABBED) ;
13711         if (!name || !*name)
13712             API_ERROR("groupel map name", E_BADARGS);
13713         if (db_VariableNameValid(name) == 0)
13714             API_ERROR("groupel map name", E_INVALIDNAME);
13715         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
13716             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
13717         if (num_segments < 0)
13718             API_ERROR("num_segments", E_BADARGS);
13719         if (!groupel_types)
13720             API_ERROR("groupel_types", E_BADARGS);
13721         if (!segment_lengths)
13722             API_ERROR("segment_lengths", E_BADARGS);
13723         if (!segment_data)
13724             API_ERROR("segment_data", E_BADARGS);
13725         if (!dbfile->pub.p_grplm)
13726             API_ERROR(dbfile->pub.name, E_NOTIMP);
13727 
13728         retval = (dbfile->pub.p_grplm) (dbfile, name,
13729             num_segments, groupel_types, segment_lengths, segment_ids,
13730             segment_data, segment_fracs, fracs_data_type, opts);
13731 
13732         db_FreeToc(dbfile);
13733         API_RETURN(retval);
13734     }
13735     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
13736 }
13737 
13738 PUBLIC DBgroupelmap *
DBGetGroupelmap(DBfile * dbfile,const char * name)13739 DBGetGroupelmap(DBfile *dbfile, const char *name)
13740 {
13741     DBgroupelmap *retval = NULL;
13742 
13743     API_BEGIN2("DBGetGroupelmap", DBgroupelmap *, NULL, name) {
13744         if (!dbfile)
13745             API_ERROR(NULL, E_NOFILE);
13746         if (SILO_Globals.enableGrabDriver == TRUE)
13747             API_ERROR("DBGetGroupelmap", E_GRABBED) ;
13748         if (!name || !*name)
13749             API_ERROR("groupel map name", E_BADARGS);
13750         if (!dbfile->pub.g_grplm)
13751             API_ERROR(dbfile->pub.name, E_NOTIMP);
13752 
13753         retval = (dbfile->pub.g_grplm) (dbfile, name);
13754         API_RETURN(retval);
13755     }
13756     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
13757 }
13758 
13759 PUBLIC int
DBPutMrgvar(DBfile * dbfile,const char * name,const char * mrgt_name,int ncomps,char const * const * compnames,int nregns,char const * const * reg_pnames,int datatype,DBVCP2_t data,DBoptlist const * opts)13760 DBPutMrgvar(DBfile *dbfile, const char *name, const char *mrgt_name,
13761     int ncomps, char const * const *compnames, int nregns, char const * const *reg_pnames,
13762     int datatype, DBVCP2_t data, DBoptlist const *opts)
13763 {
13764     int retval;
13765 
13766     API_BEGIN2("DBPutMrgvar", int, -1, name) {
13767         if (!dbfile)
13768             API_ERROR(NULL, E_NOFILE);
13769         if (SILO_Globals.enableGrabDriver == TRUE)
13770             API_ERROR("DBPutMrgvar", E_GRABBED) ;
13771         if (!name || !*name)
13772             API_ERROR("mrgvar name", E_BADARGS);
13773         if (db_VariableNameValid(name) == 0)
13774             API_ERROR("mrgvar name", E_INVALIDNAME);
13775         if (!mrgt_name || !*mrgt_name)
13776             API_ERROR("mrgt_name", E_BADARGS);
13777         if (db_VariableNameValid(mrgt_name) == 0)
13778             API_ERROR("mrgt_name", E_INVALIDNAME);
13779         if (!SILO_Globals.allowOverwrites && DBInqVarExists(dbfile, name))
13780             API_ERROR("overwrite not allowed", E_NOOVERWRITE);
13781         if (nregns < 0)
13782             API_ERROR("nregns", E_BADARGS);
13783         if (ncomps < 0)
13784             API_ERROR("ncomps", E_BADARGS);
13785         if (!reg_pnames)
13786             API_ERROR("reg_pnames", E_BADARGS);
13787         if (!data)
13788             API_ERROR("data", E_BADARGS);
13789         if (!dbfile->pub.p_mrgv)
13790             API_ERROR(dbfile->pub.name, E_NOTIMP);
13791 
13792         retval = (dbfile->pub.p_mrgv) (dbfile, name, mrgt_name, ncomps,
13793             compnames, nregns, reg_pnames, datatype, data, opts);
13794 
13795         db_FreeToc(dbfile);
13796         API_RETURN(retval);
13797     }
13798     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
13799 }
13800 
13801 PUBLIC DBmrgvar *
DBGetMrgvar(DBfile * dbfile,const char * name)13802 DBGetMrgvar(DBfile *dbfile, const char *name)
13803 {
13804     DBmrgvar *retval = NULL;
13805 
13806     API_BEGIN2("DBGetMrgvar", DBmrgvar *, NULL, name) {
13807         if (!dbfile)
13808             API_ERROR(NULL, E_NOFILE);
13809         if (SILO_Globals.enableGrabDriver == TRUE)
13810             API_ERROR("DBGetMrgvar", E_GRABBED) ;
13811         if (!name || !*name)
13812             API_ERROR("mrgvar name", E_BADARGS);
13813         if (!dbfile->pub.g_mrgv)
13814             API_ERROR(dbfile->pub.name, E_NOTIMP);
13815 
13816         retval = (dbfile->pub.g_mrgv) (dbfile, name);
13817         API_RETURN(retval);
13818     }
13819     API_END_NOPOP; /*BEWARE: If API_RETURN above is removed use API_END */
13820 }
13821 /**********************************************************************
13822  *
13823  * Purpose: Provide a strdup command which correctly handles
13824  *          a NULL string.
13825  *
13826  * Programmer: Sean Ahern
13827  * Date: April 1999
13828  *
13829  * Input arguments:
13830  *    s             The string to copy.
13831  *
13832  * Global variables:
13833  *    None
13834  *
13835  * Local variables:
13836  *    retval        The new string, with memory allocated.
13837  *
13838  * Assumptions and Comments:
13839  *
13840  * Modifications:
13841  *
13842  *    Lisa J. Roberts, Tue Jul 27 12:44:57 PDT 1999
13843  *    Modified the function so it returns the string.
13844  *
13845  *    Jeremy Meredith, Tue Aug 31 13:41:29 PDT 1999
13846  *    Made it handle 0-length strings correctly.
13847  *
13848  *       Thomas R. Treadway, Wed Nov 28 15:25:53 PST 2007
13849  *       Moved from src/swat/sw_string.c
13850  *
13851  ***********************************************************************/
13852 char *
_db_safe_strdup(const char * s)13853 _db_safe_strdup(const char *s)
13854 {
13855     char *retval = NULL;
13856     int n;
13857 
13858     if (!s)
13859         return NULL;
13860 
13861     n = strlen(s);
13862     retval = (char*)malloc(sizeof(char)*(n+1));
13863     memcpy(retval, s, n);
13864     retval[n] = '\0';
13865 
13866     return(retval);
13867 }
13868 
13869 /*-------------------------------------------------------------------------
13870  * Function:    different
13871  *
13872  * Purpose:     Determines if A and B are same or different based on an
13873  *              absolute tolerance and relative tolerance.  A and B differ
13874  *              if and only if
13875  *
13876  *                      | A-B | > ABSTOL
13877  *
13878  *              or
13879  *
13880  *                      2 | A-B |
13881  *                      ---------  > RELTOL
13882  *                       | A+B |
13883  *
13884  *              If ABSTOL or RELTOL is negative then the corresponding
13885  *              test is not performed.  If both are negative then this
13886  *              function degenerates to a `!=' operator.
13887  *
13888  * Return:      Success:        0 if same, 1 if different.
13889  *
13890  *              Failure:        never fails
13891  *
13892  * Programmer:  Robb Matzke
13893  *              matzke@viper.llnl.gov
13894  *              Feb  6 1997
13895  *
13896  * Modifications:
13897  *
13898  *  Mark C. Miller, Wed Nov 11 22:18:17 PST 2009
13899  *  Added suppot for alternate relative diff option.
13900  *
13901  * Mark C. Miller, Tue Feb  7 15:18:38 PST 2012
13902  * Made reltol_eps diff mutually exclusive with abstol || reltol diff.
13903  *-------------------------------------------------------------------------
13904  */
DBIsDifferentDouble(double a,double b,double abstol,double reltol,double reltol_eps)13905 int DBIsDifferentDouble(double a, double b, double abstol, double reltol, double reltol_eps)
13906 {
13907    double       num, den;
13908 
13909    /*
13910     * First, see if we should use the alternate diff.
13911     * check |A-B|/(|A|+|B|+EPS) in a way that won't overflow.
13912     */
13913    if (reltol_eps >= 0 && reltol > 0)
13914    {
13915       if ((a<0 && b>0) || (b<0 && a>0)) {
13916          num = fabs (a/2 - b/2);
13917          den = fabs (a/2) + fabs(b/2) + reltol_eps/2;
13918          reltol /= 2;
13919       } else {
13920          num = fabs (a - b);
13921          den = fabs (a) + fabs(b) + reltol_eps;
13922       }
13923       if (0.0==den && num) return 1;
13924       if (num/den > reltol) return 1;
13925       return 0;
13926    }
13927    else /* use the old Abs|Rel difference test */
13928    {
13929       /*
13930        * Now the |A-B| but make sure it doesn't overflow which can only
13931        * happen if one is negative and the other is positive.
13932        */
13933       if (abstol>0) {
13934          if ((a<0 && b>0) || (b<0 && a>0)) {
13935             if (fabs (a/2 - b/2) > abstol/2) return 1;
13936          } else {
13937             if (fabs(a-b) > abstol) return 1;
13938          }
13939       }
13940 
13941       /*
13942        * Now check 2|A-B|/|A+B| in a way that won't overflow.
13943        */
13944       if (reltol>0) {
13945          if ((a<0 && b>0) || (b<0 && a>0)) {
13946             num = fabs (a/2 - b/2);
13947             den = fabs (a/2 + b/2);
13948             reltol /= 2;
13949          } else {
13950             num = fabs (a - b);
13951             den = fabs (a/2 + b/2);
13952          }
13953          if (0.0==den && num) return 1;
13954          if (num/den > reltol) return 1;
13955       }
13956 
13957       if (abstol>0 || reltol>0) return 0;
13958    }
13959 
13960    /*
13961     * Otherwise do a normal exact comparison.
13962     */
13963    return a!=b;
13964 }
13965 
13966 /*-------------------------------------------------------------------------
13967  * Function:    differentll
13968  *
13969  * Purpose:     Implement above difference function for long long type.
13970  *
13971  * Programmer:  Mark C. Miller, Mon Dec  7 07:05:39 PST 2009
13972  *
13973  * Modifications:
13974  *   Mark C. Miller, Mon Dec  7 09:50:19 PST 2009
13975  *   Change conditional compilation logic to compile this routine
13976  *   whenever a double is NOT sufficient to hold full precision of long
13977  *   or long long.
13978  *
13979  *   Mark C. Miller, Mon Jan 11 16:20:16 PST 2010
13980  *   Made it compiled UNconditionally.
13981  *-------------------------------------------------------------------------
13982  */
13983 #define FABS(A) ((A)<0?-(A):(A))
DBIsDifferentLongLong(long long a,long long b,double abstol,double reltol,double reltol_eps)13984 int DBIsDifferentLongLong(long long a, long long b, double abstol, double reltol, double reltol_eps)
13985 {
13986 
13987    long long num, den;
13988 
13989    /*
13990     * First, see if we should use the alternate diff.
13991     * check |A-B|/(|A|+|B|+EPS) in a way that won't overflow.
13992     */
13993    if (reltol_eps >= 0 && reltol > 0)
13994    {
13995       if ((a<0 && b>0) || (b<0 && a>0)) {
13996          num = FABS (a/2 - b/2);
13997          den = FABS (a/2) + FABS(b/2) + reltol_eps/2;
13998          reltol /= 2;
13999       } else {
14000          num = FABS (a - b);
14001          den = FABS (a) + FABS(b) + reltol_eps;
14002       }
14003       if (0.0==den && num) return 1;
14004       if (num/den > reltol) return 1;
14005       return 0;
14006    }
14007    else
14008    {
14009       /*
14010        * Now the |A-B| but make sure it doesn't overflow which can only
14011        * happen if one is negative and the other is positive.
14012        */
14013       if (abstol>0) {
14014          if ((a<0 && b>0) || (b<0 && a>0)) {
14015             if (FABS(a/2 - b/2) > abstol/2) return 1;
14016          } else {
14017             if (FABS(a-b) > abstol) return 1;
14018          }
14019       }
14020 
14021       /*
14022        * Now check 2|A-B|/|A+B| in a way that won't overflow.
14023        */
14024       if (reltol>0) {
14025          if ((a<0 && b>0) || (b<0 && a>0)) {
14026             num = FABS (a/2 - b/2);
14027             den = FABS (a/2 + b/2);
14028             reltol /= 2;
14029          } else {
14030             num = FABS (a - b);
14031             den = FABS (a/2 + b/2);
14032          }
14033          if (0.0==den && num) return 1;
14034          if (num/den > reltol) return 1;
14035 
14036          if (abstol>0 || reltol>0) return 0;
14037       }
14038    }
14039 
14040    /*
14041     * Otherwise do a normal exact comparison.
14042     */
14043    return a!=b;
14044 }
14045 
14046 PUBLIC char *
DBGetDatatypeString(int dt)14047 DBGetDatatypeString(int dt)
14048 {
14049     return db_GetDatatypeString(dt);
14050 }
14051