1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11
12 #include <dx/dx.h>
13 #include <stdio.h>
14 #include <ctype.h>
15 #include <string.h>
16 #include <stdarg.h>
17 #include <stdlib.h>
18
19 #if defined(HAVE_SYS_ERRNO_H)
20 #include <sys/errno.h>
21 #endif
22
23 #if defined(HAVE_ERRNO_H)
24 #include <errno.h>
25 #endif
26
27 #if defined(HAVE_SYS_FILE_H)
28 #include <sys/file.h>
29 #endif
30
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <math.h>
34
35 #if ! DXD_HAS_UNIX_SYS_INCLUDES
36 typedef unsigned long mode_t;
37 #endif
38
39 #include "edf.h"
40
41 #include <stdlib.h>
42
43 #if defined(DXD_NON_UNIX_DIR_SEPARATOR)
44 #define DX_DIR_SEPARATOR ';'
45 #else
46 #define DX_DIR_SEPARATOR ':'
47 #endif
48 /* prototypes
49 */
50
51 static Error check_parms(struct getby *gp, char *fname, char **namelist,
52 int *start, int *end, int *delta);
53 static Error is_dir(FILE *fp, char *name);
54
55 #if DXD_POPEN_OK && DXD_HAS_LIBIOP
56 #define popen popen_host
57 #define pclose pclose_host
58 #endif
59
60
61 /* messages about components and their consistency with each other
62 */
63 #define Err_MustBeString "#10700"
64 #define Err_MustBeStringList "#10701"
65 #define Err_MissingComp "#10702"
66 #define Wrn_NotPosConnFac "#10704"
67 #define Err_NotArray "#10706"
68 #define Err_DiffCount "#10708"
69 #define Err_RefNotInt "#10710"
70 #define Err_BadElemType "#10712"
71 #define Err_OutOfRange "#10714"
72
73
ending(int num)74 static char *ending(int num)
75 {
76 switch(num % 10) {
77 case 1:
78 return (num%100)==11 ? "th" : "st";
79
80 case 2:
81 return (num%100)==12 ? "th" : "nd";
82
83 case 3:
84 return (num%100)==13 ? "th" : "rd";
85 }
86
87 return "th";
88 }
89
elemtypecheck(int num,char * str)90 static Error elemtypecheck(int num, char *str)
91 {
92 char rightstr[20];
93
94 switch(num) {
95 case 0:
96 strcpy(rightstr, "points");
97 break;
98 case 1:
99 strcpy(rightstr, "lines");
100 break;
101 case 2:
102 strcpy(rightstr, "quads");
103 break;
104 case 3:
105 strcpy(rightstr, "cubes");
106 break;
107 default:
108 sprintf(rightstr, "cubes%dD", num);
109 break;
110 }
111
112 if (strcmp(rightstr, str)) {
113 DXSetError(ERROR_DATA_INVALID, Err_BadElemType, str, rightstr);
114 return ERROR;
115 }
116
117 return OK;
118 }
119
120 Error
_dxfValidate(Field f)121 _dxfValidate(Field f)
122 {
123 Array current = NULL;
124 Array target = NULL;
125 char *tname, *cname;
126 int ncurrent, ntarget, *ip;
127 int index;
128 unsigned char *cp;
129 int i, j, lim, nitems;
130 Type type, ref_type;
131 Category cat;
132 String s = NULL;
133 Object o = NULL;
134 int rank, shape[MAXRANK];
135 int counts[MAXRANK];
136
137 for (i=0; (current=(Array)DXGetEnumeratedComponentValue(f, i, &cname)); i++) {
138
139 /* dep */
140 if ((s = (String)DXGetAttribute((Object)current, "dep")) != NULL) {
141 /* make sure number of items matches number of items in dep */
142 if ((DXGetObjectClass((Object)s) != CLASS_STRING) ||
143 ((tname = DXGetString(s)) == NULL)) {
144 DXSetError(ERROR_DATA_INVALID,
145 Err_MustBeString, "dep", cname);
146 return ERROR;
147 }
148
149 if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) {
150 DXSetError(ERROR_DATA_INVALID,
151 Err_MissingComp, tname, "dep", cname);
152 return ERROR;
153 }
154
155 if (DXGetObjectClass((Object)target) != CLASS_ARRAY) {
156 DXSetError(ERROR_DATA_INVALID,
157 Err_NotArray, tname, "dep", cname);
158 return ERROR;
159 }
160
161 if (!DXGetArrayInfo(current, &nitems, &type, &cat, &rank, shape))
162 return ERROR;
163
164 ncurrent = nitems;
165
166 if (!DXGetArrayInfo(target, &nitems, &type, &cat, &rank, shape))
167 return ERROR;
168
169 ntarget = nitems;
170
171 if (ncurrent != ntarget) {
172 DXSetError(ERROR_DATA_INVALID,
173 Err_DiffCount, "dep",
174 ncurrent, cname, ntarget, tname);
175 return ERROR;
176 }
177
178 } /* end of if (has dep) */
179
180
181 /* ref */
182 if ((s = (String)DXGetAttribute((Object)current, "ref")) != NULL) {
183 if ((DXGetObjectClass((Object)s) != CLASS_STRING) ||
184 ((tname = DXGetString(s)) == NULL)) {
185 DXSetError(ERROR_DATA_INVALID,
186 Err_MustBeString, "ref", cname);
187 return ERROR;
188 }
189
190 if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) {
191 DXSetError(ERROR_DATA_INVALID,
192 Err_MissingComp, tname, "ref", cname);
193 return ERROR;
194 }
195
196 if (DXGetObjectClass((Object)target) != CLASS_ARRAY) {
197 DXSetError(ERROR_DATA_INVALID,
198 Err_NotArray, tname, "ref", cname);
199 return ERROR;
200 }
201
202 if (!DXGetArrayInfo(current, &nitems, &type, &cat, &rank, shape))
203 return ERROR;
204
205 if ( !( type == TYPE_INT || type == TYPE_UBYTE ) ) {
206 DXSetError(ERROR_DATA_INVALID, Err_RefNotInt, cname);
207 return ERROR;
208 }
209 ref_type = type;
210
211 ncurrent = nitems;
212 for (j=0; j<rank; j++)
213 ncurrent *= shape[j];
214
215 if (ncurrent > 0) {
216
217 if (!DXGetArrayInfo(target, &nitems, &type, &cat, &rank, shape))
218 return ERROR;
219
220 ntarget = nitems;
221
222 /* only do this if they are already irregular */
223 if (DXGetArrayClass(current) == CLASS_ARRAY) {
224 if ((ip = (int *)DXGetArrayData(current)) == NULL)
225 return ERROR;
226 cp = (unsigned char *) ip;
227
228 /* neighbors can have -1's as indicies */
229 lim = strcmp(cname, "neighbors") ? 0 : -1;
230
231 for (j=0; j < ncurrent; j++) {
232 if (ref_type == TYPE_INT) index = *(ip++);
233 else index = *(cp++);
234
235 if (index < lim || index >= ntarget) {
236 DXSetError(ERROR_DATA_INVALID, Err_OutOfRange,
237 j+1, ending(j+1), cname, index, lim, ntarget-1);
238 return ERROR;
239 }
240 }
241
242 } else if (DXQueryGridConnections(current, &rank, counts)) {
243 for (j=0, ncurrent=1; j<rank; j++)
244 ncurrent *= counts[j];
245 if (ncurrent > ntarget) {
246 DXSetError(ERROR_DATA_INVALID,
247 Err_DiffCount, "ref",
248 ncurrent, cname, ntarget, tname);
249 return ERROR;
250 }
251 } else {
252 /* mesh array of mixed path and irregular arrays. */
253 /* have to handle the terms separately */
254 }
255 }
256 } /* end of if (has ref) */
257
258
259 /* der - can be string lists here */
260 if ((o = DXGetAttribute((Object)current, "der")) != NULL) {
261
262 if (DXExtractString(o, &tname)) { /* simple string? */
263 if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) {
264 DXSetError(ERROR_DATA_INVALID,
265 Err_MissingComp, tname, "der", cname);
266 return ERROR;
267 }
268
269 if (DXGetObjectClass((Object)target) != CLASS_ARRAY) {
270 DXSetError(ERROR_DATA_INVALID,
271 Err_NotArray, tname, "der", cname);
272 return ERROR;
273 }
274 } else if (DXExtractNthString(o, 0, &tname)) { /* string list? */
275 for (j=0; DXExtractNthString(o, j, &tname); j++) {
276
277 if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) {
278 DXSetError(ERROR_DATA_INVALID,
279 Err_MissingComp, tname, "der", cname);
280 return ERROR;
281 }
282
283 if (DXGetObjectClass((Object)target) != CLASS_ARRAY) {
284 DXSetError(ERROR_DATA_INVALID,
285 Err_NotArray, tname, "der", cname);
286 return ERROR;
287 }
288 }
289 } else { /* neither string or string list */
290 DXSetError(ERROR_DATA_INVALID,
291 Err_MustBeStringList, "der", cname);
292 return ERROR;
293 }
294
295 } /* end of if (has der) */
296
297 /* element type */
298 if ((s = (String)DXGetAttribute((Object)current, "element type")) != NULL) {
299 if ((DXGetObjectClass((Object)s) != CLASS_STRING) ||
300 ((tname = DXGetString(s)) == NULL)) {
301 DXSetError(ERROR_DATA_INVALID,
302 Err_MustBeString, "element type", cname);
303 return ERROR;
304 }
305
306 if (!strcmp(cname, "connections") &&
307 DXQueryGridConnections(current, &rank, counts)) {
308
309 if (!elemtypecheck(rank, tname))
310 return ERROR;
311 }
312
313 } /* end of if (has element type) */
314
315 } /* for each component in the field */
316
317 /* check for missing positions component if the field has more than
318 * one component.
319 */
320 if (i > 1 && !DXGetComponentValue(f, "positions"))
321 DXWarning("importing a field with no `positions' component");
322
323 return OK;
324 }
325
326 /* stolen from system.m (cpv's code)
327 */
328 #if !defined(DXD_POPEN_OK)
mkfifo(char * path,mode_t mode)329 static Error mkfifo(char *path, mode_t mode)
330 {
331 int rc;
332 char *cmd = (char *)DXAllocateLocal(strlen("mknod ") +
333 strlen(path) +
334 strlen(" p; chmod ") +
335 12 +
336 strlen(path) + 1);
337 sprintf(cmd, "mknod %s p; chmod 0%o %s", path, mode, path);
338 rc = system(cmd);
339
340 DXFree((Pointer)cmd);
341 return (rc==0) ? OK : ERROR;
342 }
Unlink(char * path)343 static Error Unlink(char *path)
344 {
345 int rc;
346 char *cmd = (char *)DXAllocateLocal(strlen("rm -f") +
347 strlen(path) + 1);
348 sprintf(cmd, "rm -f %s", path);
349 rc = system(cmd);
350
351 DXFree((Pointer)cmd);
352 return (rc==0) ? OK : ERROR;
353 }
354 #endif
355
356
357
358 /*
359 *
360 * entry point for processing a file
361 *
362 */
363
DXImportDX(char * filename,char ** namelist,int * start,int * end,int * delta)364 Object DXImportDX(char *filename, char **namelist,
365 int *start, int *end, int *delta)
366 {
367 struct finfo f;
368 Object o = NULL;
369 char needfree = 1;
370 int rc;
371
372 /* setup finfo struct
373 */
374
375 /* clear struct to be sure all pointers are NULL, and set stuff which
376 * we know the value of now. then call the init subroutine to finish
377 * the rest of the initialization.
378 */
379 memset(&f, '\0', sizeof(f));
380
381 f.fd = _dxfopen_dxfile(filename, NULL, &f.fname,".dx");
382 if (!f.fd)
383 goto done;
384
385 rc = check_parms(&f.gb, NULL, namelist, start, end, delta);
386 if (!rc)
387 goto done;
388
389 if (!f.fname) {
390 f.fname = "<NULL>";
391 needfree = 0;
392 }
393
394 f.recurse = 0;
395 f.onepass = filename[0]=='!' ? 1 : 0;
396
397 rc = _dxfinitfinfo(&f);
398 if (!rc) {
399 if (needfree)
400 DXFree((Pointer)f.fname);
401 DXFree((Pointer)f.gb.gbuf);
402 return NULL;
403 }
404
405
406 /* read the file and construct the requested object
407 */
408 rc = _dxfparse_file(&f, &o);
409 if (!rc)
410 goto done;
411
412
413 done:
414 #if DXD_POPEN_OK
415 _dxfclose_dxfile(f.fd, filename); /* original filename possibly w/ ! */
416 #else
417 _dxfclose_dxfile(f.fd, filename);
418 #endif
419
420 if (needfree)
421 DXFree((Pointer)f.fname);
422
423 DXFree((Pointer)f.gb.gbuf);
424
425 _dxffreefinfo(&f);
426
427 /* special routine which decrements ref count without deleting the object.
428 * the object was referenced when added to the dictionary, so that
429 * cleanup could delete all things not being returned.
430 */
431 if (o)
432 DXUnreference(o);
433
434 return o;
435 }
436
437
438 /* special internal entry point. input is a single open stream pointer,
439 * which can't be closed. the caller has to ensure the file stream
440 * is a valid open file or pipe, and the default object will be imported
441 * and the format MUST be follows (can't seek on pipes, so can't look
442 * for forward references to data).
443 */
_dxfImportDX_FD(FILE * fptr)444 Object _dxfImportDX_FD(FILE *fptr)
445 {
446 struct finfo f;
447 Object o = NULL;
448 int rc;
449
450 /* setup finfo struct
451 */
452
453 /* clear struct to be sure all pointers are NULL, and set stuff which
454 * we know the value of now. then call the init subroutine to finish
455 * the rest of the initialization.
456 */
457 memset(&f, '\0', sizeof(f));
458
459 rc = check_parms(&f.gb, NULL, NULL, NULL, NULL, NULL);
460 if (!rc)
461 goto done;
462
463 f.fd = fptr;
464 f.fname = "<NULL>";
465 f.recurse = 0;
466 f.onepass = 1;
467
468 rc = _dxfinitfinfo(&f);
469 if (!rc) {
470 DXFree((Pointer)f.gb.gbuf);
471 return NULL;
472 }
473
474
475 /* read the file and construct the requested object
476 */
477 rc = _dxfparse_file(&f, &o);
478 if (!rc)
479 goto done;
480
481 done:
482
483 DXFree((Pointer)f.gb.gbuf);
484 _dxffreefinfo(&f);
485
486 /* special routine which decrements ref count without deleting the object.
487 * the object was referenced when added to the dictionary, so that
488 * cleanup could delete all things not being returned.
489 */
490 if (o)
491 DXUnreference(o);
492
493 return o;
494 }
495
496
497
498 /*
499 * open a file, trying to append 'ext' and using each part of the DXDATA path
500 * if the environment variable is defined. if auxname is defined, use
501 * the basename of that directory first before using the search path.
502 */
_dxfopen_dxfile(char * inname,char * auxname,char ** outname,char * ext)503 FILE *_dxfopen_dxfile(char *inname, char *auxname, char **outname,char *ext)
504 {
505 FILE *fd = NULL;
506 char *datadir = NULL, *cp;
507 char *basename = NULL;
508 int bytes = 0;
509 int rc;
510
511 *outname = NULL;
512
513 /* support for external filters
514 */
515 if (inname[0] == '!') {
516 if (inname[1] == '\0') {
517 DXSetError(ERROR_BAD_PARAMETER, "#10200", "external filter name");
518 return NULL;
519 }
520
521 #if DXD_POPEN_OK
522
523 if ((fd = popen(inname+1, "r")) == NULL) {
524 DXSetError(ERROR_BAD_PARAMETER, "#10720", inname+1);
525 return NULL;
526 }
527 /* popen appears to succeed even if the program trying to
528 * be run doesn't get started. this is trying to test for
529 * that case and give a more reasonable error message.
530 */
531 if ((rc=fgetc(fd)) == EOF) {
532 DXSetError(ERROR_BAD_PARAMETER, "#10722", inname+1);
533 return NULL;
534 } else
535 ungetc(rc, fd);
536
537 *outname = (char *)DXAllocateLocalZero(strlen(inname)+1);
538 if (!*outname) {
539 pclose(fd);
540 return NULL;
541 }
542
543 strcpy(*outname, inname+1);
544
545 return fd;
546
547 #else
548 #if os2
549 DXSetError(ERROR_BAD_PARAMETER, "'!' is not supported by os2");
550 return ERROR;
551 #else
552
553 /* popen() is currently not supported on ibmpvs, so for now, use
554 * a named pipe as a substitute.
555 */
556 #define TEMPLATE "!/tmp/DXI%08d.0"
557
558 bytes = strlen("(%s) > %s &") +
559 strlen(inname) + 1 +
560 strlen(TEMPLATE) + 6;
561
562 if ((cmd = (char *)DXAllocateLocalZero(bytes)) == NULL)
563 return NULL;
564
565 if ((*outname = (char *)DXAllocateLocalZero(strlen(TEMPLATE) + 6)) == NULL)
566 return NULL;
567
568 pid = getpid();
569 sprintf(*outname, TEMPLATE, pid);
570
571 if (mkfifo(*outname+1, 0600) == ERROR)
572 goto npipe_error;
573
574 sprintf(cmd, "(%s) > %s &", inname+1, *outname+1);
575
576 rc = system(cmd);
577 DXFree((Pointer) cmd);
578
579 if (rc != 0)
580 goto npipe_error2;
581
582 /* open for reading */
583 DXDebug("F", "trying at (0) to open pipe");
584 fd = fopen(*outname+1, "r");
585 if (fd == NULL)
586 goto npipe_error;
587
588
589 return fd;
590
591 npipe_error:
592 DXSetError(ERROR_DATA_INVALID, "%s: %s", *outname+1, strerror(errno));
593 Unlink(*outname+1);
594 return ERROR;
595
596 npipe_error2:
597 DXSetError(ERROR_BAD_PARAMETER, "#10720", inname+1);
598 Unlink(*outname+1);
599 return ERROR;
600 #endif
601 #endif
602 }
603
604
605 /* try to open the filename as given, and save the name
606 * for error messages later.
607 */
608 DXDebug("F", "trying at (1) to open `%s'", inname);
609 fd = fopen(inname, "r");
610 if (fd) {
611 if (is_dir(fd, inname) != OK)
612 goto error;
613
614 *outname = (char *)DXAllocateLocalZero(strlen(inname)+1);
615 if (!*outname)
616 goto error;
617
618 strcpy(*outname, inname);
619 return fd;
620 }
621
622
623 #define XXTRA 12 /* space for the null, the / and .general - plus some extra */
624
625 /* allocate space to construct variations of the given filename.
626 * get enough space the first time so we can construct any variation
627 * without having to reallocate.
628 */
629 bytes = strlen(inname) + XXTRA;
630 if (auxname)
631 bytes += strlen(auxname);
632
633 datadir = (char *)getenv("DXDATA");
634 if (datadir)
635 bytes += strlen(datadir);
636
637 *outname = (char *)DXAllocateLocalZero(bytes);
638 if (!*outname)
639 goto error;
640
641 /* name as given, with extension appended to the end
642 */
643 strcpy(*outname, inname);
644 strcat(*outname, ext);
645 DXDebug("F", "trying at (2) to open `%s'", *outname);
646 if ((fd=fopen(*outname, "r"))!=NULL) {
647 if (is_dir(fd, *outname) != OK)
648 goto error;
649
650 DXMessage("opening file '%s'", *outname);
651 return fd;
652 }
653
654
655 /* if absolute pathname, it's not found.
656 */
657 #if defined(DXD_NON_UNIX_DIR_SEPARATOR)
658 if (inname[0] == '/' || inname[0] == '\\' || inname[1] == ':') {
659 #else
660 if (inname[0] == '/') {
661 #endif
662 DXSetError(ERROR_BAD_PARAMETER, "#12240", inname);
663 goto error;
664 }
665
666
667 /* on a recursive open, try the same directory as the parent file.
668 */
669 if (auxname != NULL) {
670
671 /* find basename, keeping the last '/' */
672 #if defined(DXD_NON_UNIX_DIR_SEPARATOR)
673 basename = strrchr(auxname, '/');
674 if(!basename)
675 basename = strrchr(auxname, '\\');
676 if(!basename)
677 basename = strrchr(auxname, ':');
678 #else
679 basename = strrchr(auxname, '/');
680 #endif
681 if (basename) {
682
683 /* try basename + file */
684 strcpy(*outname, auxname);
685 (*outname)[basename-auxname+1] = '\0';
686 strcat(*outname, inname);
687 DXDebug("F", "trying at (3) to open `%s'", *outname);
688 if ((fd=fopen(*outname, "r"))!=NULL) {
689 if (is_dir(fd, *outname) != OK)
690 goto error;
691
692 DXMessage("opening file '%s'", *outname);
693 return fd;
694 }
695
696 /* basename + file + extension */
697 strcat(*outname, ext);
698 DXDebug("F", "trying at (4) to open `%s'", *outname);
699 if ((fd=fopen(*outname, "r"))!=NULL) {
700 if (is_dir(fd, *outname) != OK)
701 goto error;
702
703 DXMessage("opening file '%s'", *outname);
704 return fd;
705 }
706 }
707 }
708
709
710 /* if the DXDATA environment variable existed, try the list of
711 * directory names.
712 */
713 while (datadir) {
714
715 strcpy(*outname, datadir);
716 if ((cp = strchr(*outname, DX_DIR_SEPARATOR)) != NULL)
717 *cp = '\0';
718 strcat(*outname, "/");
719 strcat(*outname, inname);
720 DXDebug("F", "trying at (5) to open `%s'", *outname);
721 if ((fd=fopen(*outname, "r"))!=NULL) {
722 if (is_dir(fd, *outname) != OK)
723 goto error;
724
725 DXMessage("opening file '%s'", *outname);
726 return fd;
727 }
728
729 strcat(*outname, ext);
730 DXDebug("F", "trying at (6) to open `%s'", *outname);
731 if ((fd=fopen(*outname, "r"))!=NULL) {
732 if (is_dir(fd, *outname) != OK)
733 goto error;
734
735 DXMessage("opening file '%s'", *outname);
736 return fd;
737 }
738
739 datadir = strchr(datadir, DX_DIR_SEPARATOR);
740 if (datadir)
741 datadir++;
742 }
743
744 /* if you get here, you didn't find the file. fall thru
745 * into error section.
746 */
747 DXSetError(ERROR_BAD_PARAMETER, "#12240", inname);
748
749 error:
750 if (*outname) {
751 DXFree((Pointer)*outname);
752 *outname = NULL;
753 }
754
755 if (fd)
756 fclose(fd);
757
758 return NULL;
759
760 }
761
762 /* take care of pipes, if supported on this architecture
763 */
764 Error _dxfclose_dxfile(FILE *fptr, char *filename)
765 {
766 #if DXD_POPEN_OK
767 if (fptr) {
768 if (filename[0] == '!') {
769 pclose(fptr);
770 } else {
771 fclose(fptr);
772 }
773 }
774 #else
775 if (fptr) {
776 fclose(fptr);
777 if (filename[0] == '!')
778 Unlink(filename+1);
779 }
780
781 #endif
782
783 return OK;
784 }
785
786
787 /*
788 * make sure the file pointer doesn't point to a directory. on random
789 * occasions we're gotten segfaults (which don't reproduce later) when
790 * the file opened is a directory.
791 */
792 static Error is_dir(FILE *fp, char *fname)
793 {
794 struct stat sbuf;
795
796 if (fstat(fileno(fp), &sbuf) < 0) {
797 DXSetError(ERROR_BAD_PARAMETER, "%s: %s", fname, strerror(errno));
798 return ERROR;
799 }
800
801 if (S_ISDIR(sbuf.st_mode)) {
802 DXSetError(ERROR_BAD_PARAMETER, "%s is a directory", fname);
803 return ERROR;
804 }
805
806 return OK;
807 }
808
809 /*
810 * rangecheck input parms, and fill the 'getby' struct.
811 */
812 static Error check_parms(struct getby *gp, char *fname, char **namelist,
813 int *start, int *end, int *delta)
814 {
815 gp->which = GETBY_NONE;
816 gp->numlist = NULL;
817 gp->gbuf = NULL;
818
819 gp->fname = fname;
820
821 if (namelist && *namelist) {
822 gp->which = GETBY_NAME;
823 gp->namelist = namelist;
824 }
825
826 gp->seriesflag = 0;
827
828 if (start) {
829 if (*start < 0) {
830 DXSetError(ERROR_BAD_PARAMETER, "#10030", "start");
831 return ERROR;
832 }
833 gp->seriesflag |= SL_START;
834 gp->serieslim[0] = *start;
835 }
836 if (end) {
837 if (*end < 0) {
838 DXSetError(ERROR_BAD_PARAMETER, "#10030", "end");
839 return ERROR;
840 }
841 gp->seriesflag |= SL_END;
842 gp->serieslim[1] = *end;
843 }
844 if (delta) {
845 if (*delta <= 0) {
846 DXSetError(ERROR_BAD_PARAMETER, "#10020", "delta");
847 return ERROR;
848 }
849 gp->seriesflag |= SL_DELTA;
850 gp->serieslim[2] = *delta;
851 }
852
853 if (start && end) {
854 if (*start > *end) {
855 DXSetError(ERROR_BAD_PARAMETER, "#10185", "start", "end");
856 return ERROR;
857 }
858 }
859
860 return OK;
861 }
862
863 /* initialize the finfo struct
864 */
865 Error _dxfinitfinfo(struct finfo *fp)
866 {
867
868 /* initialize the dictionary
869 */
870 fp->d = (struct dict *)DXAllocateLocal(sizeof(struct dict));
871 if(!fp->d)
872 goto done;
873
874 if (!_dxfinitdict(fp->d))
875 goto done;
876
877 /* initialize the object list
878 */
879 if (!_dxfinitobjlist(fp))
880 goto done;
881
882
883 /* initialize the parsing code
884 */
885 if (!_dxfinitparse(fp)) {
886 DXSetError(ERROR_DATA_INVALID, "#10730", fp->fname);
887 goto done;
888 }
889
890
891 return OK;
892
893
894 done:
895 _dxffreefinfo(fp);
896 return ERROR;
897 }
898
899
900 void _dxffreefinfo(struct finfo *fp)
901 {
902 _dxfdeleteparse(fp);
903
904 _dxfdeletedict(fp->d);
905 DXFree((Pointer)fp->d);
906
907 _dxfdeleteobjlist(fp);
908 }
909
910 /* copy contents of finfo struct.
911 * source, destination.
912 */
913 void _dxfdupfinfo(struct finfo *fp1, struct finfo *fp2)
914 {
915 memcpy((void *)fp2, (void *)fp1, sizeof(struct finfo));
916 }
917
918
919