1 
2 /*
3  * parse library stdio and malloc utility classes.
4  */
5 
6 /*
7  * Version 2.05
8  *
9  * Author: Graeme W. Gill
10  * Date:   2002/10/24
11  *
12  * Copyright 2002, Graeme W. Gill
13  * All rights reserved.
14  *
15  * This material is licensed with an "MIT" free use license:-
16  * see the License4.txt file in this directory for licensing details.
17  *
18  * These are kept in a separate file to allow them to be
19  * selectively ommitted from the cgats library.
20  *
21  */
22 
23 
24 #define _PARSSTD_C_
25 
26 #ifndef COMBINED_STD
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <math.h>
37 #include <time.h>
38 #ifdef __sun
39 #include <unistd.h>
40 #endif
41 
42 #include "pars.h"
43 
44 #endif /* !COMBINED_STD */
45 
46 #if defined(SEPARATE_STD) || defined(COMBINED_STD)
47 
48 /* ----------------------------------------------- */
49 /* Standard Heap allocator cgatsAlloc compatible class */
50 /* Just call the standard system function */
51 
52 #ifdef CGATS_DEBUG_MALLOC
53 
54 /* Make sure that inline malloc #defines are turned off for this file */
55 #undef was_debug_malloc
56 #ifdef malloc
57 #undef malloc
58 #undef calloc
59 #undef realloc
60 #undef free
61 #define was_debug_malloc
62 #endif	/* dmalloc */
63 
cgatsAllocStd_dmalloc(struct _cgatsAlloc * pp,size_t size,char * file,int line)64 static void *cgatsAllocStd_dmalloc(
65 struct _cgatsAlloc *pp,
66 size_t size,
67 char *file,
68 int line
69 ) {
70 	void *rv = malloc(size);
71 	return rv;
72 }
73 
cgatsAllocStd_dcalloc(struct _cgatsAlloc * pp,size_t num,size_t size,char * file,int line)74 static void *cgatsAllocStd_dcalloc(
75 struct _cgatsAlloc *pp,
76 size_t num,
77 size_t size,
78 char *file,
79 int line
80 ) {
81 	void *rv = calloc(num, size);
82 	return rv;
83 }
84 
cgatsAllocStd_drealloc(struct _cgatsAlloc * pp,void * ptr,size_t size,char * file,int line)85 static void *cgatsAllocStd_drealloc(
86 struct _cgatsAlloc *pp,
87 void *ptr,
88 size_t size,
89 char *file,
90 int line
91 ) {
92 	void *rv = realloc(ptr, size);
93 	return rv;
94 }
95 
96 
cgatsAllocStd_dfree(struct _cgatsAlloc * pp,void * ptr,char * file,int line)97 static void cgatsAllocStd_dfree(
98 struct _cgatsAlloc *pp,
99 void *ptr,
100 char *file,
101 int line
102 ) {
103 	free(ptr);
104 }
105 
106 /* we're done with the AllocStd object */
cgatsAllocStd_delete(cgatsAlloc * pp)107 static void cgatsAllocStd_delete(
108 cgatsAlloc *pp
109 ) {
110 	cgatsAllocStd *p = (cgatsAllocStd *)pp;
111 
112 	free(p);
113 }
114 
115 /* Create cgatsAllocStd */
new_cgatsAllocStd()116 cgatsAlloc *new_cgatsAllocStd() {
117 	cgatsAllocStd *p;
118 	if ((p = (cgatsAllocStd *) calloc(1,sizeof(cgatsAllocStd))) == NULL)
119 		return NULL;
120 	p->dmalloc  = cgatsAllocStd_dmalloc;
121 	p->dcalloc  = cgatsAllocStd_dcalloc;
122 	p->drealloc = cgatsAllocStd_drealloc;
123 	p->dfree    = cgatsAllocStd_dfree;
124 	p->del      = cgatsAllocStd_delete;
125 
126 	return (cgatsAlloc *)p;
127 }
128 
129 #ifdef was_debug_malloc
130 #undef was_debug_malloc
131 #define malloc( p, size )	    dmalloc( p, size, __FILE__, __LINE__ )
132 #define calloc( p, num, size )	dcalloc( p, num, size, __FILE__, __LINE__ )
133 #define realloc( p, ptr, size )	drealloc( p, ptr, size, __FILE__, __LINE__ )
134 #define free( p, ptr )	        dfree( p, ptr , __FILE__, __LINE__ )
135 #endif	/* was_debug_malloc */
136 
137 #else /* !CGATS_DEBUG_MALLOC */
138 
cgatsAllocStd_malloc(struct _cgatsAlloc * pp,size_t size)139 static void *cgatsAllocStd_malloc(
140 struct _cgatsAlloc *pp,
141 size_t size
142 ) {
143 	void *rv = malloc(size);
144 	return rv;
145 }
146 
cgatsAllocStd_calloc(struct _cgatsAlloc * pp,size_t num,size_t size)147 static void *cgatsAllocStd_calloc(
148 struct _cgatsAlloc *pp,
149 size_t num,
150 size_t size
151 ) {
152 	void *rv = calloc(num, size);
153 	return rv;
154 }
155 
cgatsAllocStd_realloc(struct _cgatsAlloc * pp,void * ptr,size_t size)156 static void *cgatsAllocStd_realloc(
157 struct _cgatsAlloc *pp,
158 void *ptr,
159 size_t size
160 ) {
161 	void *rv = realloc(ptr, size);
162 	return rv;
163 }
164 
165 
cgatsAllocStd_free(struct _cgatsAlloc * pp,void * ptr)166 static void cgatsAllocStd_free(
167 struct _cgatsAlloc *pp,
168 void *ptr
169 ) {
170 	free(ptr);
171 }
172 
173 /* we're done with the AllocStd object */
cgatsAllocStd_delete(cgatsAlloc * pp)174 static void cgatsAllocStd_delete(
175 cgatsAlloc *pp
176 ) {
177 	cgatsAllocStd *p = (cgatsAllocStd *)pp;
178 
179 	free(p);
180 }
181 
182 /* Create cgatsAllocStd */
new_cgatsAllocStd()183 cgatsAlloc *new_cgatsAllocStd() {
184 	cgatsAllocStd *p;
185 	if ((p = (cgatsAllocStd *) calloc(1,sizeof(cgatsAllocStd))) == NULL)
186 		return NULL;
187 	p->malloc  = cgatsAllocStd_malloc;
188 	p->calloc  = cgatsAllocStd_calloc;
189 	p->realloc = cgatsAllocStd_realloc;
190 	p->free    = cgatsAllocStd_free;
191 	p->del     = cgatsAllocStd_delete;
192 
193 	return (cgatsAlloc *)p;
194 }
195 
196 #endif /* !CGATS_DEBUG_MALLOC */
197 
198 /* ------------------------------------------------- */
199 /* Standard Stream file I/O cgatsFile compatible class */
200 
201 /* Get the size of the file (Only valid for reading file. */
cgatsFileStd_get_size(cgatsFile * pp)202 static size_t cgatsFileStd_get_size(cgatsFile *pp) {
203 	cgatsFileStd *p = (cgatsFileStd *)pp;
204 
205 	return p->size;
206 }
207 
208 /* Set current position to offset. Return 0 on success, nz on failure. */
cgatsFileStd_seek(cgatsFile * pp,unsigned int offset)209 static int cgatsFileStd_seek(
210 cgatsFile *pp,
211 unsigned int offset
212 ) {
213 	cgatsFileStd *p = (cgatsFileStd *)pp;
214 
215 	return fseek(p->fp, offset, SEEK_SET);
216 }
217 
218 /* Read count items of size length. Return number of items successfully read. */
cgatsFileStd_read(cgatsFile * pp,void * buffer,size_t size,size_t count)219 static size_t cgatsFileStd_read(
220 cgatsFile *pp,
221 void *buffer,
222 size_t size,
223 size_t count
224 ) {
225 	cgatsFileStd *p = (cgatsFileStd *)pp;
226 
227 	return fread(buffer, size, count, p->fp);
228 }
229 
230 /* Read a character */
cgatsFileStd_getch(cgatsFile * pp)231 static int cgatsFileStd_getch(
232 cgatsFile *pp
233 ) {
234 
235 	cgatsFileStd *p = (cgatsFileStd *)pp;
236 
237 	return fgetc(p->fp);
238 }
239 
240 /* write count items of size length. Return number of items successfully written. */
cgatsFileStd_write(cgatsFile * pp,void * buffer,size_t size,size_t count)241 static size_t cgatsFileStd_write(
242 cgatsFile *pp,
243 void *buffer,
244 size_t size,
245 size_t count
246 ) {
247 	cgatsFileStd *p = (cgatsFileStd *)pp;
248 
249 	return fwrite(buffer, size, count, p->fp);
250 }
251 
252 /* do a printf */
cgatsFileStd_printf(cgatsFile * pp,const char * format,...)253 static int cgatsFileStd_printf(
254 cgatsFile *pp,
255 const char *format,
256 ...
257 ) {
258 	int rv;
259 	va_list args;
260 	cgatsFileStd *p = (cgatsFileStd *)pp;
261 
262 	va_start(args, format);
263 	rv = vfprintf(p->fp, format, args);
264 	va_end(args);
265 	return rv;
266 }
267 
268 /* flush all write data out to secondary storage. Return nz on failure. */
cgatsFileStd_flush(cgatsFile * pp)269 static int cgatsFileStd_flush(
270 cgatsFile *pp
271 ) {
272 	cgatsFileStd *p = (cgatsFileStd *)pp;
273 
274 	return fflush(p->fp);
275 }
276 
277 /* Return the memory buffer. Error if not cgatsFileMem */
cgatsFileStd_get_buf(cgatsFile * pp,unsigned char ** buf,size_t * len)278 static int cgatsFileStd_get_buf(
279 cgatsFile *pp,
280 unsigned char **buf,
281 size_t *len
282 ) {
283 	return 1;
284 }
285 
286 /* return the filename */
cgatsFileStd_fname(cgatsFile * pp)287 static char *cgatsFileStd_fname(
288 cgatsFile *pp
289 ) {
290 	cgatsFileStd *p = (cgatsFileStd *)pp;
291 
292 	if (p->filename != NULL)
293 		return p->filename;
294 	else
295 		return "**Unknown**";
296 }
297 
298 
299 /* we're done with the file object, return nz on failure */
cgatsFileStd_delete(cgatsFile * pp)300 static int cgatsFileStd_delete(
301 cgatsFile *pp
302 ) {
303 	int rv = 0;
304 	cgatsFileStd *p = (cgatsFileStd *)pp;
305 	cgatsAlloc *al = p->al;
306 	int del_al   = p->del_al;
307 
308 	if (p->doclose != 0) {
309 		if (fclose(p->fp) != 0)
310 			rv = 2;
311 	}
312 
313 	if (p->filename != NULL)
314 		al->free(al, p->filename);
315 
316 	al->free(al, p);	/* Free object */
317 	if (del_al)			/* We are responsible for deleting allocator */
318 		al->del(al);
319 
320 	return rv;
321 }
322 
323 /* Create cgatsFile given a (binary) FILE* */
new_cgatsFileStd_fp(FILE * fp)324 cgatsFile *new_cgatsFileStd_fp(
325 FILE *fp
326 ) {
327 	return new_cgatsFileStd_fp_a(fp, NULL);
328 }
329 
330 /* Create cgatsFile given a (binary) FILE* and allocator */
new_cgatsFileStd_fp_a(FILE * fp,cgatsAlloc * al)331 cgatsFile *new_cgatsFileStd_fp_a(
332 FILE *fp,
333 cgatsAlloc *al		/* heap allocator, NULL for default */
334 ) {
335 	cgatsFileStd *p;
336 	int del_al = 0;
337 	struct stat sbuf;
338 
339 	if (al == NULL) {	/* None provided, create default */
340 		if ((al = new_cgatsAllocStd()) == NULL)
341 			return NULL;
342 		del_al = 1;		/* We need to delete it */
343 	}
344 
345 	if ((p = (cgatsFileStd *) al->calloc(al, 1, sizeof(cgatsFileStd))) == NULL) {
346 		if (del_al)
347 			al->del(al);
348 		return NULL;
349 	}
350 	p->al       = al;				/* Heap allocator */
351 	p->del_al   = del_al;			/* Flag noting whether we delete it */
352 	p->get_size = cgatsFileStd_get_size;
353 	p->seek     = cgatsFileStd_seek;
354 	p->read     = cgatsFileStd_read;
355 	p->getch    = cgatsFileStd_getch;
356 	p->write    = cgatsFileStd_write;
357 	p->gprintf  = cgatsFileStd_printf;
358 	p->flush    = cgatsFileStd_flush;
359 	p->get_buf  = cgatsFileStd_get_buf;
360 	p->fname    = cgatsFileStd_fname;
361 	p->del      = cgatsFileStd_delete;
362 
363 	if (fstat(fileno(fp), &sbuf) == 0) {
364 		p->size = sbuf.st_size;
365 	} else {
366 		p->size = 0;
367 	}
368 
369 	p->fp = fp;
370 	p->doclose = 0;
371 
372 	return (cgatsFile *)p;
373 }
374 
375 /* Create cgatsFile given a file name */
new_cgatsFileStd_name(const char * name,const char * mode)376 cgatsFile *new_cgatsFileStd_name(
377 const char *name,
378 const char *mode
379 ) {
380 	return new_cgatsFileStd_name_a(name, mode, NULL);
381 }
382 
383 /* Create given a file name and allocator */
new_cgatsFileStd_name_a(const char * name,const char * mode,cgatsAlloc * al)384 cgatsFile *new_cgatsFileStd_name_a(
385 const char *name,
386 const char *mode,
387 cgatsAlloc *al			/* heap allocator, NULL for default */
388 ) {
389 	FILE *fp;
390 	cgatsFile *p;
391 	char nmode[50];
392 
393 	strcpy(nmode, mode);
394 #if !defined(O_CREAT) && !defined(_O_CREAT)
395 # error "Need to #include fcntl.h!"
396 #endif
397 #if defined(O_BINARY) || defined(_O_BINARY)
398 	strcat(nmode, "b");
399 #endif
400 
401 	if ((fp = fopen(name, nmode)) == NULL)
402 		return NULL;
403 
404 	p = new_cgatsFileStd_fp_a(fp, al);
405 
406 	if (p != NULL) {
407 		cgatsFileStd *pp = (cgatsFileStd *)p;
408 		pp->doclose = 1;
409 
410 		pp->filename = pp->al->malloc(pp->al, strlen(name) + 1);
411 		strcpy(pp->filename, name);
412 	}
413 	return p;
414 }
415 
416 /* Create a memory image file access class with the std allocator */
417 /* Don't free the buffer on delete */
new_cgatsFileMem(void * base,size_t length)418 cgatsFile *new_cgatsFileMem(
419 void *base,			/* Pointer to base of memory buffer */
420 size_t length		/* Number of bytes in buffer */
421 ) {
422 	cgatsFile *p;
423 	cgatsAlloc *al;			/* memory allocator */
424 
425 	if ((al = new_cgatsAllocStd()) == NULL)
426 		return NULL;
427 
428 	if ((p = new_cgatsFileMem_a(base, length, al)) == NULL) {
429 		al->del(al);
430 		return NULL;
431 	}
432 
433 	((cgatsFileMem *)p)->del_al = 1;		/* Get cgatsFileMem->del to cleanup al */
434 	return p;
435 }
436 
437 /* Create a memory image file access class with the std allocator */
438 /* Free buffer on delete */
new_cgatsFileMem_d(void * base,size_t length)439 cgatsFile *new_cgatsFileMem_d(
440 void *base,			/* Pointer to base of memory buffer */
441 size_t length		/* Number of bytes in buffer */
442 ) {
443 	cgatsFile *p;
444 	cgatsAlloc *al;			/* memory allocator */
445 
446 	if ((al = new_cgatsAllocStd()) == NULL)
447 		return NULL;
448 
449 	if ((p = new_cgatsFileMem_a(base, length, al)) == NULL) {
450 		al->del(al);
451 		return NULL;
452 	}
453 
454 	((cgatsFileMem *)p)->del_al = 1;		/* Get cgatsFileMem->del to cleanup al */
455 	((cgatsFileMem *)p)->del_buf = 1;		/* Get cgatsFileMem->del to cleanup buffer */
456 	return p;
457 }
458 
459 /* ------------------------------------------------- */
460 
461 /* Create an empty parse object, default standard allocator */
462 parse *
new_parse(cgatsFile * fp)463 new_parse(cgatsFile *fp) {
464 	parse *p;
465 	cgatsAlloc *al;			/* memory allocator */
466 
467 	if ((al = new_cgatsAllocStd()) == NULL)
468 		return NULL;
469 
470 	if ((p = new_parse_al(al, fp)) == NULL) {
471 		al->del(al);
472 		return NULL;
473 	}
474 
475 	p->del_al = 1;			/* Get parse->del to cleanup allocator */
476 	return p;
477 }
478 
479 
480 #endif /* defined(SEPARATE_STD) || defined(COMBINED_STD) */
481