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