1 /* Copyright (C) 1992-1998 The Geometry Center
2  * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3  *
4  * This file is part of Geomview.
5  *
6  * Geomview is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Geomview is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Geomview; see the file COPYING.  If not, write
18  * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
19  * USA, or visit http://www.gnu.org.
20  */
21 
22 
23 /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
24 
25 #ifndef OOGLUTILDEF
26 #define OOGLUTILDEF
27 
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "iobuffer.h"
32 
33 #ifdef _WIN32
34 # define M_PI 3.14159265358979323
35 extern int finite(double v);
36 extern int strcasecmp(char *s1, char *s2);
37 #endif
38 
39 
40 /*
41  * Definition so that (obsolete Irix 3) SGIs won't barf on member function prototypes.
42  */
43 #ifdef no_prototypes
44 #define P(foo) ()
45 #else
46 #define P(foo) foo
47 #endif
48 
49 
50 #define	COUNT(array)	(int)(sizeof(array)/sizeof(array[0]))
51 
52 /*
53  * Public definitions for miscellaneous useful OOGL internal stuff.
54  */
55 
56 #define	OOGLMagic(key, vers)    (0x9c800000 | (((key)&0x7f)<<16) | ((vers)&0xffff) )
57 #define OOGLIsMagic(magic)	(((magic) & 0xff800000) == 0x9c800000)
58 
59 /*
60  * Memory allocation
61  */
62 #ifndef OOG_NewP
63 extern void *(*OOG_NewP)(size_t);
64 #endif
65 #ifndef OOG_RenewP
66 extern void *(*OOG_RenewP)(void *, size_t);
67 #endif
68 
69 #ifndef OOGLFree
70 extern void (*OOGLFree)(void *);
71 #endif
72 #ifndef OOG_NewE
73 extern void *OOG_NewE(int, char *);
74 #endif
75 #ifndef OOG_RenewE
76 extern void *OOG_RenewE(void *, int, char *);
77 #endif
78 
_OOGLNew(size_t size)79 static inline void *_OOGLNew(size_t size)
80 {
81   return OOG_NewP(size);
82 }
_OOGLRenew(void * p,size_t size)83 static inline void *_OOGLRenew(void *p, size_t size)
84 {
85   return OOG_RenewP(p, size);
86 }
87 #define	OOGLNew(t)		(t *)_OOGLNew(sizeof(t))
88 #define	OOGLNewN(t,N)		(t *)_OOGLNew(sizeof(t)*(N))
89 #define	OOGLRenewN(t,p,N)	(t *)_OOGLRenew(p, sizeof(t)*(N))
90 #define	OOGLRealloc(t,p)	(t *)_OOGLRenew(p, sizeof(t))
91 
92 #define	OOGLNewE(t, errmsg)	(t *)OOG_NewE(sizeof(t), errmsg)
93 #define	OOGLNewNE(t,N, errmsg)	(t *)OOG_NewE(sizeof(t)*(N), errmsg)
94 #define	OOGLRenewNE(t,p,N, errmsg) (t *)OOG_RenewE(p, sizeof(t)*(N), errmsg)
95 
96 /*
97  * Backward compatibility
98  */
99 #define	GeomNew(t)		OOGLNew(t)
100 #define	GeomNewN(t,N)		OOGLNewN(t,N)
101 #define	GeomFree(p)		OOGLFree(p)
102 #define	GeomError  		OOGLError
103 
104 /*
105  * Error handling
106  */
107 extern char *_GFILE;		/* Name of file where error is found */
108 extern int _GLINE;		/* Line number in file where error is found */
109 extern int OOGL_Errorcode;	/* Unique integer error code */
110 extern void OOGLWarn (char *fmt, ...);
111 extern const char *sperrno(unsigned int);
112 extern const char *sperror(void);
113 
114 /* Kludge for obtaining file name and line number of error: */
115 #define OOGLError (_GFILE= __FILE__, _GLINE=__LINE__,0)?0:_OOGLError
116 
117 extern int _OOGLError(int, char *fmt, ...);
118 
119 extern void OOGLSyntax(IOBFILE *, char *fmt, ...);
120 
121 	/* Bit fields in error codes */
122 #define	OE_VERBOSE	0x1
123 #define	OE_FATAL	0x2
124 
125 /*
126  * Variable-sized arrays ("vectors").  Manipulates variables of type "vvec".
127  * Maintains the data they point to, but doesn't allocate the vvec's themselves;
128  * typical use might be
129  *   vvec myvec;
130  *   VVINIT(myvec, float, 10);
131  *   while( ... ) {
132  *	*VVAPPEND(myvec, float) = something;
133  *   }
134  *   for(i = 0; i < VVSIZE(myvec); i++)
135  *	... VVEC(myvec, float)[i] ...
136  *
137  */
138 typedef struct vvec {
139 	char *base;	/* The real data */
140 	int count;	/* Number of elements in use (indices 0..count-1) */
141 	int allocated;	/* Number of elements allocated */
142 	int elsize;	/* sizeof(element type) */
143 	char dozero;	/* Zero-fill all new elements */
144 	char malloced;	/* "base" has been malloced */
145 	char spare1, spare2; /* for future extensions */
146 } vvec;
147 
148 #include <vvec.h> /* inline vv-functions */
149 
150 /*
151  * Macros take 'vvec' arguments, while functions take addresses of vvec's.
152  * VVINIT() : initialize new empty array; first malloc will grab >= 'minelems'.
153  * VVZERO() : request that all newly allocated elements be cleared to zeros
154  * VVINDEX() : return address of index'th element, ensuring that it exists.
155  * VVAPPEND() : increments array size, returning address of new last element
156  * VVEC()   : returns address of array base; VVEC()[i] is the i'th element
157  *		assuming that its existence was ensured by earlier call to
158  *		VVAPPEND() or VVINDEX() or vvneeds().
159  * VVCOUNT() : number of valid elements in array.  Maintained by user.
160  */
161 #define	VVINIT(vv,type,minelems)  vvinit(&(vv), sizeof(type), minelems)
162 #define	VVEC(vv, type)		((type *)((vv).base))
163 #define	VVCOUNT(vv)		(vv).count
164 #define	VVINDEX(vv,type,index)	((type *)vvindex(&(vv), (index)))
165 #define	VVAPPEND(vv, type)  	VVINDEX(vv, type, (vv).count++)
166 
167 /* Functions take addresses of vvec's.  Besides the above, there are
168  * vvtrim() : trim allocated but unused space (beyond VVCOUNT()'th element).
169  * vvfree() : free malloced array.
170  * vvneeds(): ensure that at least this many elements are allocated
171  * vvzero() : all newly allocated elements will be filled with binary zeros
172  * vvuse()  : Use the given non-malloced buffer until more room is needed;
173  *		call vvuse() after vvinit() but before allocating anything.
174  * vvcopy() : copies one vvec into another, allocating space in the
175  *              destination to accommodate the data and copying everything.
176  */
177 static inline void vvinit(vvec *v, int elsize, int minelems);
178 static inline void vvuse(vvec *v, void *buf, int allocated);
179 static inline void vvtrim(vvec *v); /* Trim allocated but unused data */
180 static inline void vvfree(vvec *v); /* Free all malloced data */
181 static inline void vvneeds(vvec *v, int needed);
182 static inline void *vvindex(vvec *v, int index);
183 static inline void vvzero(vvec *v);
184 static inline void vvcopy(vvec *src, vvec *dest);
185 
186 /*
187  * File-I/O utility routines
188  */
189 /*
190  * int iobfnextc(IOBFILE *f, int flags)
191  *	Advances f to the next "interesting" character and
192  *	returns it.  The returned char is ungetc'ed so the next getc()
193  *	will yield the same value.
194  *	Interesting depends on flags:
195  *	  0 : Skip blanks, tabs, newlines, and comments (#...\n).
196  *	  1 : Skip blanks, tabs, and comments, but newlines are interesting
197  *		(including the \n that terminates a comment).
198  *	  2 : Skip blanks, tabs, and newlines, but stop at #.
199  *	  3 : Skip blanks and tabs but stop at # or \n.
200  *
201  * int
202  * iobfexpectstr(IOBFILE *file, char *string)
203  *	Expect the given string to appear immediately on file.
204  *	Return 0 if the complete string is found,
205  *	else the offset+1 of the last matched char within string.
206  *	The first unmatched char is ungetc'd.
207  *
208  * int
209  * iobfexpecttoken(IOBFILE *file, char *string)
210  *	Expect the given string to appear on the file, possibly after
211  *	skipping some white space and comments.
212  *	Return 0 if found, else the offset+1 of last matched char in string.
213  *	The first unmatched char is ungetc'd.
214  *
215  * char *iobftoken(IOBFILE *f, int flags)
216  *	Skips uninteresting characters with fnextc(f, flags),
217  *	then returns a "token" - string of consecutive interesting characters.
218  *	Returns NULL if EOF is reached with no token, or if
219  *	flags specifies stopping at end-of-line and this is encountered with
220  *	no token found.
221  *	The token is effectively statically allocated and will be
222  *	overwritten by the next ftoken() call.
223  *
224  * int iobfgetnd(file, ndouble, doublep, binary)
225  *	Read an array of doubles from a file in "ascii" or "binary" format.
226  *	Returns number of doubles successfully read, should = nfloats.
227  *	"Binary" means "Bit-Endian IEEE 64-bit floating-point" format.
228  *
229  * int iobfgetnf(file, nfloats, floatp, binary)
230  *	Read an array of floats from a file in "ascii" or "binary" format.
231  *	Returns number of floats successfully read, should = nfloats.
232  *	"Binary" means "Big-Endian IEEE 32-bit floating-point" format.
233  *
234  * int iobfgetni(IOBFILE *file, int nints, int *intsp, int binary)
235  *	Read an array of ints from a file in "ascii" or "binary" format.
236  *	Returns number of ints successfully read, should = nints.
237  *	"Binary" means "32-bit big-endian" integer format.
238  *
239  * int iobfgetns(IOBFILE *file, int nshorts, short *intsp, int binary)
240  *	Read an array of shorts from a file in "ascii" or "binary" format.
241  *	Returns number of shorts successfully read, should = nints.
242  *	"Binary" means "16-bit big-endian" integer format.
243  *
244  * int iobfgettransform(IOBFILE *f,
245  *                      int ntransforms, float *transforms, int binary)
246  *	Reads 4x4 matrices from IOBFILE.  Returns the number of matrices found,
247  *	up to ntransforms.  Returns 0 if no numbers are found.
248  *	On finding incomplete matrices (not a multiple of 16 floats)
249  *	returns -1, regardless of whether any whole matrices were found.
250  *	In ASCII (binary==0) mode, matrices are read in conventional order
251  *	which is the transpose of the internal form.  Binary mode reads
252  *	32-bit IEEE floats in internal order.
253  *
254  * int fputtransform(FILE *f, int ntransforms, float *transforms, int binary)
255  *	Writes 4x4 matrices to FILE.  Returns the number written, i.e.
256  *	ntransforms unless an error occurs.  See fgettransform() for format.
257  *
258  */
259 
260 #define	NODATA	-2	/* async_fnextc() and async_getc() return NODATA if
261 			 * none is immediately available
262 			 */
263 
264 extern int async_iobfgetc(IOBFILE *f);
265 extern int async_iobfnextc(IOBFILE *f, int flags);
266 extern char *iobfcontext(IOBFILE *f);
267 extern char *iobftoken(IOBFILE *iobf, int flags);
268 extern char *iobfquotetoken(IOBFILE *iobf, int flags, int *quote);
269 extern char *
270 iobfquotedelimtok(const char *delims, IOBFILE *iobf, int flags, int *quote);
271 extern char *iobfdelimtok(const char *delims, IOBFILE *iobf, int flags);
272 extern int iobfescape(IOBFILE *f);
273 extern int iobfexpectstr(IOBFILE *iobf, char *str);
274 extern int iobfexpecttoken(IOBFILE *iobf, char *str);
275 extern int iobfgetnd(IOBFILE *f, int maxd, double *dv, int binary);
276 extern int iobfgetnf(IOBFILE *f, int maxf, float *fv, int binary);
277 extern int iobfgetni(IOBFILE *f, int maxi, int *iv, int binary);
278 extern int iobfgetns(IOBFILE *f, int maxs, short *sv, int binary);
279 extern int iobfgettransform(IOBFILE *iobf, int ntrans, float *trans, int bin);
280 extern int iobfhasdata(IOBFILE *f);
281 extern int iobfnextc(IOBFILE *f, int flags);
282 
283 extern char *fdelimtok(const char *delims, FILE *f, int flags);
284 extern int fescape(FILE *f);
285 extern int fexpectstr(FILE *f, char *str);
286 extern int fexpecttoken(FILE *f, char *str);
287 extern int fgetnd(FILE *f, int maxd, double *dv, int binary);
288 extern int fgetnf(FILE *f, int maxf, float *fv, int binary);
289 extern int fgetni(FILE *f, int maxi, int *iv, int binary);
290 extern int fgetns(FILE *f, int maxs, short *sv, int binary);
291 extern int fgettransform(FILE *f, int ntrans, float *trans, int bin);
292 extern int fnextc(FILE *f, int flags);
293 extern char *ftoken(FILE *f, int flags);
294 extern int fputnf(FILE *, int nfloats, float *floatp, int binary);
295 extern int fputtransform(FILE *, int ntrans, float *transforms, int binary);
296 
297 extern char *findfile(char *superfile, char *file);
298 extern void filedirs(char *dirs[]);
299 extern char **getfiledirs();
300 char *envexpand(char *s);
301 
302 extern char **ooglglob(char *s);
303 extern void ooglblkfree(char **av0);
304 
305 /* gettimeofday, where WHEN may be NULL */
306 struct timeval *timeof(struct timeval *when);
307 /* Add offset to base, yielding result */
308 void addtime(struct timeval *result, struct timeval *base, double offset);
309 /* Time in second since base */
310 double timeoffset(struct timeval *base, struct timeval *when);
311 
312 /*
313  * macro for grabbing the next value from either a region of
314  * memory or a va_list.
315  * al should be the address of the va_list
316  * p should be the address of a poiner to the region of memory,
317  *   or NULL, which means use the va_list instead.
318  */
319 #define OOGL_VA_ARG(type,al,p) (p ? ((type*)((*p)+=sizeof(type)))[-1] \
320     : (va_arg (*al, type)))
321 
322 
323 #include "porting.h"
324 
325 
326 #endif
327